前言

Redisson 不仅仅是一个 Redis 客户端,它更是一个在 Redis 基础上实现的 Java 驻内存数据网格(In-Memory Data Grid)

它的核心目标是让 Java 开发者能够以最自然的方式使用 Redis,将复杂的 Redis 命令封装成大家熟悉的 Java 接口(如 java.util.concurrent 包下的接口)。


一、核心设计理念

Redisson 的原理可以概括为:

通过 Netty 实现高性能、非阻塞的通信,将 Redis 的数据结构映射为 Java 对象和分布式对象,并在此基础上,利用 Redis 的单线程原子性特性,实现了一系列分布式的、线程安全的 Java 常用工具。


二、核心架构与通信层

1. 基于 Netty 的异步非阻塞通信

  • Netty 框架:
    Redisson 使用 Netty 4+ 作为其网络通信框架。这保证了高吞吐量和低延迟的连接管理。它允许同时处理成千上万的连接,而不会为每个连接创建单独的线程。

  • 连接管理:
    Redisson 维护着一个与 Redis 服务器的连接池(可以是单机、哨兵、集群等模式)。通过 ConnectionManager 来统一管理连接生命周期、心跳检测、重连机制等。

  • 异步与响应式:
    所有操作在底层都是异步的。当你调用 get("key") 时,Redisson 会通过 Netty 将请求写入 Channel,然后立即返回一个 RFuture 对象。你可以同步等待(future.get())或添加监听器实现异步回调。


2. 编解码器

Redisson 使用可插拔的编解码器来序列化/反序列化 Java 对象与 Redis 存储的二进制数据。

  • 默认使用 JacksonJsonCodec

  • 也可以选择 StringCodecAvroCodec

  • 或自定义实现

这保证了 存储格式的灵活性


三、关键原理详解:分布式对象与服务

Redisson 的核心在于:

不仅仅发送命令,而是在 Redis 的数据结构上构建了一层对象逻辑。


1. 分布式对象

Redisson 将 Redis 的每种基本数据结构包装成 Java 对象:

  • RList:对应 Redis 的 List。
    调用 RList.add(object) 时,底层执行 RPUSH 命令。实现了 java.util.List 接口。

  • RMap:对应 Redis 的 Hash。
    实现了 java.util.Map 接口。底层使用 HMSETHGETALL 等命令。

  • RSortedSet:对应 Redis 的 Sorted Set。
    实现了 java.util.SortedSet 接口。

这些对象内部持有一个 CommandAsyncExecutor
每一次方法调用(如 map.put(key, value))都会被转换为一个或多个 Redis 命令,通过 Netty 发送给 Redis 服务器。


2. 分布式集合(带本地缓存)

例如:RListCacheRMapCache

原理:

  • 数据同时存在于 Redis 与 JVM 本地缓存中。

  • 通过 Redis 的 发布订阅(Pub/Sub) 机制来保证集群中缓存一致性。

  • 当任一节点修改数据,会发布消息,其他节点收到后失效本地缓存。


3. 分布式锁(核心亮点)

Redisson 实现了 java.util.concurrent.locks.Lock 接口。

原理图如下:

加锁原理(lock()

每个锁请求都会带一个 唯一标识(UUID + 线程ID),防止误释放。

通过 Lua 脚本 保证原子性:

-- KEYS[1] 是锁的key,ARGV[1] 是锁的过期时间,ARGV[2] 是唯一值
if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('hset', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
return redis.call('pttl', KEYS[1]);

看门狗(Watchdog)机制

  • 如果客户端未显式设置锁超时时间,Redisson 会启动一个 看门狗线程

  • 该线程定期(约过期时间的 1/3)刷新锁的过期时间(pexpire)。

  • JVM 挂掉后线程停止,锁最终自然过期,防止死锁。


解锁原理(unlock()

同样通过 Lua 脚本保证原子性:

-- KEYS[1] 是锁的key,ARGV[1] 是唯一值
if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then
    return nil;
end;
local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1);
if (counter > 0) then
    redis.call('pexpire', KEYS[1], 30000);
    return 0;
else
    redis.call('del', KEYS[1]);
    redis.call('publish', KEYS[2], ARGV[2]);
    return 1;
end;
return nil;

等待锁的原理

如果获取锁失败,客户端并不会不断轮询,而是:

  • 订阅特定频道(Pub/Sub);

  • 当前锁释放时,持有锁的客户端发布消息;

  • 所有等待客户端收到后再竞争加锁。

这大大减少了网络请求。


4. 其他同步器(如 RSemaphore, RCountDownLatch

与锁原理类似,均基于 Lua 脚本 + Pub/Sub 实现:

  • RSemaphore
    用字符串结构存储许可数量。acquire() 减少数量,release() 增加数量。
    若无许可,则通过发布订阅等待。

  • RCountDownLatch
    使用字符串结构存储计数。countDown() 递减计数,await() 等待为 0,
    当计数为 0 时发布通知,唤醒所有等待线程。


四、数据分片与集群支持

Redisson 能够无缝支持 Redis 集群模式。

  • 自动重定向:
    当返回 -MOVED 错误时,ClusterConnectionManager 会自动更新 Slot-Node 映射并重新路由命令。

  • Pipelining:
    在集群模式下支持 pipeline,将多个命令批量发送以提升性能。


五、总结:Redisson 的核心原理

模块

核心思想

网络与通信

基于 Netty 的高性能异步通信

原子性

依靠 Lua 脚本的原子执行

事件驱动

通过 Pub/Sub 实现事件通知(锁等待、缓存失效等)

对象映射

将 Redis 数据结构封装为 Java 对象接口

容错与高可用

看门狗机制、连接池、重连、哨兵与集群支持


一句话总结:

Redisson 的原理就是
“用 Redis 的命令做砖瓦,用 Lua 脚本做水泥,用 Netty 做骨架,为 Java 世界构建一座名为『分布式工具』的大厦。”
它让分布式编程几乎和单机应用一样自然。