ImDragonfly 是一款模仿Dragonfly的高性能键值存储数据库,通过创新的架构设计和前沿技术,解决了传统 Redis 在大规模场景下的性能瓶颈和扩展性难题。
传统 Redis 受限于单线程模型,在多核服务器上无法充分利用硬件资源。ImDragonfly 采用分片架构 + 协程调度,实现真正的多核并行处理。
ImDragonfly 主分支基于 epoll + 协程 实现高性能网络 IO,同时支持数万级并发连接。未来将引入 io_uring 以进一步降低系统调用开销,相关探索在 io_uring_proactor 分支进行中。
采用 mimalloc 高性能内存分配器,结合定制的内存资源池,提高内存利用率。
ImDragonfly 采用 DashTable 作为核心数据存储引擎,这是一款基于开放寻址的高性能哈希表实现。
核心技术原理:
-
开放寻址 + 线性探测:摒弃传统链式哈希的指针开销,数据直接存储在连续内存槽位中。当发生哈希冲突时,通过线性探测(
NextBid)查找相邻桶,实现 O(1) 平均复杂度的查找和插入操作。每个 Bucket 包含 12 个槽位,使用位图(SlotBitmap)高效管理槽位状态。 -
Fingerprint 指纹优化:提取哈希值的低 8 位作为指纹(
kFingerBits = 8),存储在finger_arr_数组中。查找时先通过 SIMD 指令(_mm_cmpeq_epi8)进行指纹比对,快速过滤不匹配的候选键,显著减少不必要的完整键比较。 -
Stash 溢出处理:每个 Segment 包含 64 个主桶和 4 个 Stash 桶。当主桶及其邻居桶均已满时,数据会被写入 Stash 桶,并通过
SetStashPtr建立反向引用,确保查找时能够追踪到溢出数据。 -
可扩展哈希分段:采用类似 Extendible Hashing 的目录结构,支持动态扩展。通过
Split操作将单个 Segment 分裂为两个,IncreaseDepth扩展全局目录,实现按需扩容而无需重建整个哈希表。
| 技术领域 | 实现方案 | 核心优势 |
|---|---|---|
| 网络 IO | epoll + C++20 协程 | 事件驱动,高并发处理 |
| 异步 IO(分支) | Linux io_uring | 零拷贝,探索更低延迟 |
| 并发模型 | C++ 20 Coroutines | 轻量级线程调度 |
| 内存管理 | mimalloc + PMR | 低碎片、高性能分配 |
| 协议兼容 | Redis RESP | 无缝对接现有生态 |
┌─────────────────────────────────────────────────────────────┐
│ 命令层 (Command Layer) │
│ 命令注册 / 参数解析 / 执行引擎 / 事务管理 │
├─────────────────────────────────────────────────────────────┤
│ 存储层 (Storage Layer) │
│ 分片管理 / 内存表 / 数据同步 │
├─────────────────────────────────────────────────────────────┤
│ 网络层 (Network Layer) │
│ epoll 事件驱动 / 协程调度 │
└─────────────────────────────────────────────────────────────┘
- EngineShardSet: 分片集合管理器,负责分片的创建,分片事务的运行
- CommandRegistry: 命令注册中心
- RedisSession: 客户端会话管理,处理连接生命周期
- Transaction: 事务引擎,处理分片事务
- UringProactor: io_uring 事件循环(
io_uring_proactor分支),主分支使用 epoll
| 操作类型 | DashTable | Redis dict | std::unordered_map | 胜出 |
|---|---|---|---|---|
| Insert (插入) | 274.67 ms | 320.31 ms | 427.24 ms | DashTable |
| Find (查找) | 179.14 ms | 131.53 ms | 237.37 ms | DashTable |
| Erase (删除) | 307.60 ms | 174.25 ms | 357.29 ms | DashTable |
| Memory Usage (内存占用) | 22.8 MB | 37.1 MB | 41.6 MB | DashTable |
- Insert 比 Redis dict 快 14%,比 unordered_map 快 36%
- 内存占用比 Redis dict 降低 39%
| 指标 | 数值 |
|---|---|
| 总 Ops/sec | 354,881 |
| SET 吞吐 | 177,447 ops/s |
| GET 吞吐 | 177,434 ops/s |
| 平均延迟 | 2.25 ms |
| p50 延迟 | 1.86 ms |
| p99 延迟 | 7.87 ms |
| 峰值 CPU 利用率 | 399.5% (4 线程) |
| 测试配置 | 4 线程 × 200 连接, 30 秒 |
# 克隆项目
git clone https://github.com/yy782/ImDragonfly.git
cd ImDragonfly
# 构建并启动
docker compose up -d
# 使用 redis-cli 连接
redis-cli -p 6379提示:Docker 构建采用多阶段优化,最终镜像仅包含运行时依赖,体积精简。如需自定义分片数量,修改
docker-compose.yml中的command参数。
- 操作系统: Linux (内核 >= 3.9,支持 epoll)
- 编译器: Clang 17+ (或 GCC 11+)
- 构建工具: CMake 3.20+
# Ubuntu/Debian
sudo apt-get install -y clang cmake ninja-build \
liburing-dev libmimalloc-dev libboost-dev \
libgoogle-glog-dev libabsl-dev# 克隆项目
git clone --recurse-submodules https://github.com/yy782/ImDragonfly.git
cd ImDragonfly
# 构建
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
# 运行(参数为分片数量,默认 4)
./imdragonfly 4# 使用标准 Redis 客户端连接
redis-cli -p 6379
# 执行命令
127.0.0.1:6379> SET hello "ImDragonfly"
OKImDragonfly/
├── net/ # 网络核心层
│ ├── base/ # 异步 IO 封装、Socket 抽象
│ ├── cppcoro/ # C++ 20 协程库
│ └── util/ # 工具函数、并发原语
├── src/ # 业务逻辑层
│ ├── command_layer/ # 命令处理、参数解析
│ ├── network/ # Redis 协议实现
│ ├── redis/ # RESP 编解码
│ ├── sharding/ # 分片管理、DashTable
│ ├── transaction_layer/ # 事务引擎
│ └── detail/ # 内部实现细节
├── test/ # 测试套件
├── CMakeLists.txt # 构建配置
└── LICENSE # MIT 许可证
欢迎贡献代码!请遵循以下流程:
- Fork 项目
- 创建特性分支 (
git checkout -b feature/your-feature) - 提交代码 (
git commit -m 'Add some feature') - 推送到分支 (
git push origin feature/your-feature) - 创建 Pull Request
MIT License - 详见 LICENSE
如有问题或建议,欢迎通过以下方式联系:
- GitHub Issues: 提交问题
- 邮件: yy782@example.com
ImDragonfly — 让数据飞起来! 🐉