github.com/revectores/merodis · C++17
Merodis is an embeddable C++ library that implements the Redis data-structure API on top of LevelDB or RocksDB.
Instead of running a separate Redis server, you link against libmerodis and issue familiar commands —
Get, LPush, ZAdd — directly from your application, with data durably
persisted in an LSM-tree storage engine.
Merodis 是一个可嵌入的 C++ 库,在 LevelDB 或 RocksDB 之上实现了 Redis 数据结构 API。
无需单独运行 Redis 服务进程,只需链接 libmerodis,即可在应用程序中直接调用熟悉的命令——
Get、LPush、ZAdd——并将数据持久化到 LSM 树存储引擎中。
Merodis は LevelDB または RocksDB 上に Redis データ構造 API を実装した組み込み可能な C++ ライブラリです。
別途 Redis サーバーを立ち上げる必要はなく、libmerodis をリンクするだけで
Get・LPush・ZAdd などのおなじみのコマンドをアプリケーションから直接呼び出せ、
データは LSM ツリーのストレージエンジンに永続化されます。
The motivation is straightforward: Redis keeps its entire dataset in memory and requires a standalone server process. LevelDB and RocksDB offer disk-backed persistence with efficient compaction, but expose only a raw byte key-value interface. Merodis bridges the gap — encoding each Redis data type into LevelDB's key space so you get the semantics of Redis with the durability and memory footprint of an LSM engine.
设计动机很简单:Redis 将全部数据保存在内存中,且需要独立的服务进程。 LevelDB 和 RocksDB 提供基于磁盘的持久化存储与高效 Compaction,但仅暴露原始的字节键值接口。 Merodis 填补了这一空缺——将每种 Redis 数据类型编码到 LevelDB 的键空间中, 使你在享受 Redis 语义的同时,获得 LSM 引擎的持久性与内存效率。
設計の動機はシンプルです。Redis はデータセット全体をメモリに保持し、スタンドアロンのサーバープロセスを必要とします。 LevelDB と RocksDB はディスクバックの永続化と効率的なコンパクションを提供しますが、 インターフェースは生のバイト列のキーバリューに過ぎません。 Merodis はその橋渡しをします。各 Redis データ型を LevelDB のキー空間にエンコードすることで、 Redis のセマンティクスと LSM エンジンの耐久性・メモリ効率を両立させます。
The storage engine is selected at build time via the ENGINE CMake option. LevelDB is the default;
RocksDB can be swapped in without changing any application code, since both expose the same internal adapter
interface. This makes it straightforward to evaluate trade-offs — LevelDB for simplicity and low overhead,
RocksDB for tunable write amplification and column families.
存储引擎通过 CMake 的 ENGINE 选项在构建时指定。默认使用 LevelDB;
也可切换为 RocksDB,无需修改任何应用代码,因为两者共享同一套内部适配器接口。
这使得评估二者的权衡变得简单——LevelDB 更轻量简洁,RocksDB 则提供可调节的写放大参数与列族支持。
ストレージエンジンは CMake の ENGINE オプションでビルド時に選択します。デフォルトは LevelDB で、
RocksDB に切り替えてもアプリケーションコードの変更は不要です。両エンジンが同じ内部アダプターインターフェースを
共有しているためです。これにより、シンプルで低オーバーヘッドな LevelDB か、
書き込み増幅の調整やカラムファミリーをサポートする RocksDB かのトレードオフを気軽に評価できます。
Beyond the engine, each Redis data type has its own impl enum, letting you choose the storage layout
independently per type. For example, String supports both kStringBasicImpl (plain key-value) and
kStringTypedImpl (type-tagged). This design allows experimentation with different key-encoding
strategies while keeping the public API surface identical.
除存储引擎外,每种 Redis 数据类型都有独立的 impl 枚举,允许你为每种类型单独选择存储布局。
例如,String 支持 kStringBasicImpl(纯键值)和 kStringTypedImpl(类型标记)两种实现。
这种设计支持在不改变公开 API 的前提下,试验不同的键编码策略。
エンジンのほか、各 Redis データ型には独自の impl 列挙型 があり、型ごとにストレージレイアウトを
個別に選択できます。たとえば String は kStringBasicImpl(素のキーバリュー)と
kStringTypedImpl(型タグ付き)の両方をサポートします。
この設計により、公開 API を変えることなく異なるキーエンコード戦略を試すことができます。
The core challenge is mapping multi-element Redis types (List, Hash, Set, ZSet) onto a flat ordered key-value store. Merodis uses structured key prefixes to namespace each type and key name, then appends element-specific suffixes. For ordered structures like ZSet, scores are encoded into the key so that a range scan over LevelDB's sorted iterator directly yields results in score order — no in-memory sort needed.
核心挑战在于将多元素的 Redis 类型(List、Hash、Set、ZSet)映射到一个扁平的有序键值存储上。 Merodis 采用结构化键前缀对类型和键名进行命名空间划分,并在末尾附加元素特定的后缀。 对于 ZSet 这类有序结构,分数被编码到键中,从而通过对 LevelDB 有序迭代器的范围扫描, 即可直接按分数顺序返回结果——无需内存排序。
核心的な課題は、複数要素を持つ Redis 型(List・Hash・Set・ZSet)をフラットな順序付きキーバリューストアに マッピングすることです。Merodis は構造化されたキープレフィックスを使って型とキー名を名前空間化し、 末尾に要素固有のサフィックスを付加します。ZSet のような順序構造では、スコアをキーに エンコードすることで、LevelDB のソート済みイテレータのレンジスキャンにより スコア順に結果を直接取得できます——メモリ内ソートは不要です。
The public interface is a single header. Every method returns a merodis::Status.
公开接口只需包含一个头文件。每个方法均返回 merodis::Status。
公開インターフェースはヘッダー1つです。すべてのメソッドは merodis::Status を返します。
#include <merodis/merodis.h>
merodis::Merodis db;
merodis::Options opts;
opts.create_if_missing = true;
db.Open(opts, "/tmp/mydb");
// Strings
db.Set("hello", "world");
std::string val;
db.Get("hello", &val); // val == "world"
// Lists
db.RPush("mylist", "a");
db.RPush("mylist", "b");
uint64_t len;
db.LLen("mylist", &len); // len == 2
// Hashes
uint64_t count;
db.HSet("myhash", "field", "value", &count);
// Sets
db.SAdd("myset", "member", &count);
// Sorted Sets
db.ZAdd("ranking", {{"alice", 100}}, &count);
Building is straightforward — just clone with submodules and run CMake:
构建非常简单——只需克隆仓库(含子模块)并运行 CMake:
ビルドは簡単です。サブモジュールごとクローンして CMake を実行するだけです:
git clone --recurse-submodules https://github.com/revectores/merodis
cd merodis
cmake -B build
cmake --build build -j$(nproc)
Merodis covers the full core command set for all five Redis data types:
Merodis 覆盖了全部五种 Redis 数据类型的核心命令集:
Merodis は Redis の5つすべてのデータ型に対してコアコマンドセット全体をカバーしています:
Get · Set · Incr · IncrBy · Decr · DecrBy
LLen · LIndex · LPos · LRange · LSet · LInsert · LRem · LMove · LTrim
LPush · LPushX · LPop · RPush · RPushX · RPop
HLen · HGet · HMGet · HGetAll · HKeys · HVals · HExists
HSet · HDel
SCard · SIsMember · SMIsMember · SMembers · SRandMember
SAdd · SRem · SPop · SMove
SUnion · SInter · SDiff · SUnionStore · SInterStore · SDiffStore
ZCard · ZScore · ZMScore · ZRank · ZRevRank · ZCount · ZLexCount
ZRange · ZRangeByScore · ZRangeByLex · ZRevRange · ZRevRangeByScore · ZRevRangeByLex
ZRangeWithScores · ZRangeByScoreWithScores · ZRangeByLexWithScores (and ZRev* variants)(及 ZRev* 变体)(および ZRev* 系)
ZAdd · ZRem · ZPopMin · ZPopMax
ZRemRangeByRank · ZRemRangeByScore · ZRemRangeByLex
ZUnion · ZInter · ZDiff · ZUnionStore · ZInterStore · ZDiffStore (with WithScores variants)(含 WithScores 变体)(WithScores 系も含む)
The repository ships with a comprehensive GoogleTest suite covering all command variants, and Google Benchmark microbenchmarks for performance measurement. Run them after building:
仓库内置了覆盖全部命令变体的 GoogleTest 测试套件,以及用于性能测量的 Google Benchmark 微基准。 构建完成后运行:
リポジトリにはすべてのコマンドバリアントをカバーする GoogleTest スイートと、 パフォーマンス測定用の Google Benchmark マイクロベンチマークが同梱されています。 ビルド後に実行します:
# Tests
cd build && ctest --output-on-failure
# Benchmarks (results saved as JSON under bench_results/)
cd ..
python3 bench.py