In-memory key/value store designed for concurrent use. A simpler, but less feature-rich version of go-memdb.
✅ Multi-Version Concurrency Control (MVCC) - By leveraging immutable radix trees the database is able to support any number of concurrent readers without locking, and allows a writer to make progress.
✅ Transaction Support - The database allows for rich transactions, in which multiple objects are inserted, updated or deleted. The transactions can span multiple tables, and are applied atomically. The database provides atomicity and isolation in ACID terminology, such that until commit the updates are not visible.
🚫 Rich Indexing - Tables can support any number of indexes, which can be simple like a single field index, or more advanced compound field indexes. Certain types like UUID can be efficiently compressed from strings into byte indexes for reduced storage requirements.
🚫 Watches - Callers can populate a watch set as part of a query, which can be used to detect when a modification has been made to the database which affects the query results. This lets callers easily watch for changes in the database in a very general way.
The benefit of an MVCC system is that reads don't block writes and writes don't block reads. This is unlike sync.RWMutex, where reads block writes and writes block reads.
The way this works is by using an immutable data structure underneath. In the case of mdb and go-memdb, it's using an immutable radix tree. This allows readers to use a snapshot, while a writer's transaction is taking place. The compromise here is that a reader may not have the most up-to-date data.
It's important to note that while the underlying structure is immutable, any pointers will not be, so you'll likely want to wrap this library in a way that also handles copying pointers. You can find a good example of this in this state store.
db := mdb.New()
txn := db.Txn(true)
txn.Put("a.1", "a.1")
txn.Put("a.2", "a.2")
txn.Put("c.1", "c.1")
txn.Commit()
txn = db.Txn(false)
matches := txn.All("a")
vals := []string{}
for _, match := range matches {
vals = append(vals, match.(string))
}
assert.Equal(t, "a.1,a.2", strings.Join(vals, ","))
MIT