Jodis:一个 Java 实现的内存键值数据库

3 阅读3分钟

Jodis 是一个用 Java 实现的内存键值数据库,兼容 Redis RESP2 协议。项目初衷是学习数据库的设计与实现,同时也提供了一个轻量级的缓存方案。

项目简介

Jodis (Java Object Dictionary Server) 是一个高性能的基于内存的键值数据库,核心特点:

  • 纯 Java 实现:JDK 21+,代码简洁易读
  • 兼容 Redis 协议:支持 RESP2 协议,可用 redis-cli 直接连接
  • 丰富的数据结构:String、List、Hash、Set、Sorted Set 五大类型
  • 双模式部署:支持独立服务器和嵌入式两种使用方式
  • 持久化支持:WAL 预写日志 + JDB 快照双重保障

支持的数据结构

数据类型典型应用场景示例命令
String缓存、计数器、分布式锁SET, GET, INCR
List消息队列、最新列表LPUSH, RPOP, LRANGE
Hash对象存储、购物车HSET, HGET, HGETALL
Set标签系统、社交关系SADD, SMEMBERS, SINTER
Sorted Set排行榜、优先队列ZADD, ZRANGE, ZSCORE

快速上手

1. 编译项目

git clone https://github.com/abel-huang/Jodis.git
cd Jodis
mvn clean package -DskipTests

2. 启动服务器

java -cp target/classes:target/test-classes:$(cat .classpath.deps) \
    cn.abelib.jodis.Jodis conf/jodis.properties

服务器默认监听 6059 端口。

3. 使用 Redis CLI 连接

是的,你可以直接用 redis-cli 连接 Jodis:

redis-cli -h localhost -p 6059

试试这些命令:

127.0.0.1:6059> PING
PONG

127.0.0.1:6059> SET greeting "Hello, Jodis!"
OK

127.0.0.1:6059> GET greeting
"Hello, Jodis!"

127.0.0.1:6059> LPUSH mylist item1 item2 item3
(integer) 3

127.0.0.1:6059> LRANGE mylist 0 -1
1) "item3"
2) "item2"
3) "item1"

127.0.0.1:6059> HSET user:1 name "Alice" age 25
(integer) 2

127.0.0.1:6059> HGETALL user:1
1) "name"
2) "Alice"
3) "age"
4) "25"

Java 客户端使用

Jodis 提供了原生的 Java 客户端,API 设计简洁直观:

import cn.abelib.jodis.client.JodisClient;

public class MyApp {
    public static void main(String[] args) throws Exception {
        try (JodisClient client = new JodisClient("localhost", 6059)) {
            client.connect();

            // String 操作
            client.set("app:name", "My Application");
            String name = client.get("app:name");

            // 计数器
            client.set("counter", "0");
            client.incr("counter");  // 1
            client.incrBy("counter", 10);  // 11

            // Hash 操作 - 存储用户信息
            client.hset("user:1001", "name", "张三");
            client.hset("user:1001", "email", "zhangsan@example.com");
            Map<String, String> user = client.hgetAll("user:1001");

            // List 操作 - 消息队列
            client.lpush("queue:emails", "email1@test.com");
            client.lpush("queue:emails", "email2@test.com");
            String email = client.rpop("queue:emails");  // FIFO

            // Sorted Set - 排行榜
            client.zadd("leaderboard", 100, "player1");
            client.zadd("leaderboard", 200, "player2");
            List<String> topPlayers = client.zrange("leaderboard", 0, 9);
        }
    }
}

嵌入式模式

如果你不想单独部署服务器,Jodis 支持嵌入式运行,直接集成到你的应用中:

import cn.abelib.jodis.EmbeddedJodis;
import cn.abelib.jodis.protocol.Request;

// 启动嵌入式实例
EmbeddedJodis jodis = EmbeddedJodis.start("conf/jodis.properties");

// 直接执行命令
Response response = jodis.execute(new Request("GET", "mykey"));

// 关闭
jodis.close();

这种模式特别适合:

  • 单元测试环境
  • 小型应用内嵌缓存
  • 学习和教学用途

配置说明

Jodis 的配置文件简单明了:

# 服务器配置
jodis.port=6059
server.type=netty
server.max.request=1024
server.max.concurrency=64

# 持久化配置
log.dir=log/
log.jdb=default.jdb
log.wal=default.wal
log.reload.mode=2      # 0=WAL, 1=JDB, 2=混合加载

# 自动保存
store.auto.save.enabled=1
store.auto.save.interval=60  # 每 60 秒自动保存

持久化机制

Jodis 提供两层持久化保障:

WAL (Write-Ahead Log)

  • 所有写操作先记录日志,再更新内存
  • 故障恢复时回放日志,数据不丢失
  • 支持自动重写,避免日志无限增长

JDB (Jodis DataBase Dump)

  • 定期生成数据快照
  • 二进制格式,加载速度快
  • 适合作为冷备份

适用场景

Jodis 适合以下使用场景:

推荐使用:

  • 应用内嵌缓存
  • 开发测试环境
  • 学习 Redis 原理
  • 原型验证
  • 小规模数据存储

不推荐使用:

  • 大规模生产环境(建议使用 Redis)
  • 高并发写入场景
  • 需要集群支持的场景

技术栈

  • 语言: Java 21
  • 网络框架: Netty 4.x (NIO Reactor)
  • 协议: Redis RESP2
  • 构建工具: Maven
  • 测试框架: JUnit

总结

无论你是想学习数据库原理,还是需要一个轻量级的 Java 缓存方案,Jodis 都值得一试。


项目地址: github.com/abel-huang/…

许可证: MIT License