A self-contained Clojure wrapper around RocksDB, providing all necessary binaries via RocksDB Java API.
This is a fork of kotyo/clj-rocksdb with:
multi-get support for efficient batch key retrievalThe source code and documentation is based on Factual/clj-leveldb.
deps.edn:
org.replikativ/clj-rocksdb {:mvn/version "0.1.33"}
Leiningen:
[org.replikativ/clj-rocksdb "0.1.33"]
To create or access a database, use clj-rocksdb/create-db.
The returned database object can be used with clj-rocksdb/get, multi-get, put, delete, batch, and iterator.
By default, RocksDB stores keys and values as byte arrays. You can define custom encoders and decoders in create-db:
clj-rocksdb> (def db (create-db "/tmp/rocksdb"
{:key-encoder taoensso.nippy/freeze :key-decoder taoensso.nippy/thaw
:val-encoder taoensso.nippy/freeze :val-decoder taoensso.nippy/thaw}))
#'clj-rocksdb/db
clj-rocksdb> (put db "a" "b")
nil
clj-rocksdb> (get db "a")
"b"
Both put and delete can take multiple values, which will be written in batch:
clj-rocksdb> (put db "a" "b" "c" "d" "e" "f")
nil
clj-rocksdb> (delete db "a" "c" "e")
nil
If you need to batch a collection of puts and deletes, use batch:
clj-rocksdb> (batch db {:put ["a" "b" "c" "d"] :delete ["j" "k" "l"]})
To efficiently read multiple keys in a single call, use multi-get:
clj-rocksdb> (put db "a" "b" "c" "d" "e" "f")
nil
clj-rocksdb> (multi-get db ["a" "c" "e" "missing"])
{"a" "b", "c" "d", "e" "f"}
Note: multi-get returns a sparse map - keys that don't exist are not included in the result. This uses RocksDB's multiGetAsList API for efficient batch retrieval.
We can also get a sequence of all key/value pairs, either in the entire database or within a given range using iterator:
clj-rocksdb> (put db "a" "b" "c" "d" "e" "f")
nil
clj-rocksdb> (iterator db)
(["a" "b"] ["c" "d"] ["e" "f"])
clj-rocksdb> (iterator db "c" nil)
(["c" "d"] ["e" "f"])
clj-rocksdb> (iterator db nil "c")
(["a" "b"] ["c" "d"])
Syncing writes to disk can be forced via sync, and compaction can be forced via compact.
Originally by kotyo.
EPL-v1.0 - Distributed under the Eclipse Public License, the same as Clojure.
Open the database with :transactional? true and you get an atomic
compare-and-set, built on RocksDB's OptimisticTransactionDB:
(def db (r/create-db "/tmp/db" {:transactional? true
:key-encoder nippy/freeze :key-decoder nippy/thaw
:val-encoder nippy/freeze :val-decoder nippy/thaw}))
(r/compare-and-set! db :k r/absent :first) ;; => true, only if the key is absent
(r/compare-and-set! db :k :first :second) ;; => true, only if it still holds :first
(r/compare-and-set! db :k :first :third) ;; => false, it holds :second now
Both halves of the compare-and-set are enforced. The stored value is compared against
what you expected, and the read is taken with getForUpdate so it becomes a precondition
of the commit — a write by anyone else between your read and your commit refuses the
transaction. A refusal is false, not an exception; it is the answer, not a failure.
The option costs nothing when unused: an OptimisticTransactionDB is a RocksDB, so
every other operation behaves identically.
Can you improve this documentation? These fine people already did:
Tamas Korodi & Christian WeilbachEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |