Java 项目接 Redis 时,经常会同时看到 RedisTemplate、StringRedisTemplate、Jedis、Lettuce、Redisson。它们名字都像客户端,但定位不同。用错倒不一定马上出事故,却会让序列化、锁、连接池和排障变得混乱。
我的理解是:RedisTemplate 管“怎么存取 Redis 数据”,Redisson 管“多实例之间怎么借 Redis 协作”。
RedisTemplate 解决普通读写
RedisTemplate 是 Spring Data Redis 提供的模板 API。它把 Redis 命令封装成几类操作:
opsForValueopsForHashopsForListopsForSetopsForZSet
它底层依赖 RedisConnectionFactory,连接实现可以是 Lettuce,也可以是 Jedis。Template 自己不直接代表某个网络客户端,它更多是 Spring 风格的命令封装和序列化入口。
普通缓存、简单 KV、Hash、List、计数器、过期时间,这类场景用 RedisTemplate 或 StringRedisTemplate 就够了。
StringRedisTemplate 为什么常用
StringRedisTemplate 可以理解成 RedisTemplate<String, String>。它默认 key 和 value 都按字符串序列化,和 redis-cli 里看到的内容最接近。
很多线上问题来自序列化不一致:
- key 用了 JDK 序列化,redis-cli 看到乱码。
- value 原来是 JDK 序列化,后来改 JSON,旧数据读不出来。
- JSON 里带类型信息,跨语言读取困难。
- Long、Integer、String 混用导致反序列化类型异常。
所以如果只是存简单字符串、ID、状态、计数,StringRedisTemplate 更直接。复杂对象再明确选择 JSON 序列化,并把 key serializer 和 value serializer 分开配置。
RedisTemplate 的坑主要在序列化
RedisTemplate 默认序列化如果没配好,很容易留下长期包袱。
几个建议:
- key 尽量用 String 序列化。
- value 不要随意在 JDK 序列化和 JSON 之间切换。
- 对象结构变化要考虑旧数据兼容。
- ID、编号、状态这类数据能用字符串就别存复杂对象。
- 不要把超大对象塞进 Redis。
如果 Jackson 报 UnrecognizedPropertyException,不只要看字段,还要看 getter。某些 getXxx() 方法即使没有真实字段,也可能被识别成 JSON 属性。
Redisson 解决分布式协作
Redisson 是另一类东西。它也是 Redis 客户端,但重点不是简单命令封装,而是分布式对象和协调能力。
常见能力包括:
RLock:分布式锁。RMap:分布式 Map。RQueue:队列。RDelayedQueue:延迟队列。RRateLimiter:限流器。RSemaphore:信号量。RBloomFilter:布隆过滤器。
如果只是 get/set,上 Redisson 反而显得重。如果要可重入锁、自动续期、延迟队列、限流等能力,Redisson 会省很多自写 Lua 和边界处理。
Redis 分布式锁的基本要求
自己写 Redis 锁时,至少要满足:
- 加锁必须原子:
set key value nx px timeout。 - value 必须是唯一随机值,标识锁归属。
- 解锁必须校验 value 后删除,避免删掉别人的锁。
- 锁必须有过期时间,避免进程挂掉后永远不释放。
- 业务执行时间不能长期超过锁过期时间。
错误写法是先 setnx 再单独 expire。如果中间进程挂了,锁可能没有过期时间。
解锁也不能直接 del key,要用 Lua 保证“比较 value + 删除”是原子的。
Redisson 的看门狗机制
Redisson 的 RLock 有一个常被提到的能力:watchdog 自动续期。
如果加锁时没有指定固定 lease time,业务线程还活着,Redisson 会周期性延长锁过期时间,避免业务还没执行完锁就过期。
这能降低误释放风险,但也不是万能的。比如:
- 业务线程卡死。
- JVM 长时间 Stop The World。
- Redis 网络抖动。
- 主从切换丢数据。
锁的正确性不能只靠客户端续期,还要看业务是否支持幂等、超时和补偿。
Redlock 要谨慎表达
Redlock 是 Redis 作者提出的一种多节点锁算法,用多个独立 Redis 实例提高锁安全性。但它在分布式系统语义上有争议,尤其在网络分区、时钟漂移、暂停等情况下。
工程里可以这样判断:
- 普通防重复提交、低风险任务:单 Redis 锁加唯一 value、Lua 解锁通常够用。
- 资金、库存、强一致核心链路:不要只依赖 Redis 锁,要结合数据库约束、状态机、幂等表或更强一致组件。
- 多机房强一致:需要重新审视架构,不要把 Redlock 当万能答案。
分布式锁是降低并发冲突概率和控制入口,不是替代数据一致性的最终防线。
怎么选
简单选择规则:
- 普通缓存读写:StringRedisTemplate。
- 复杂对象缓存:配置明确的 RedisTemplate。
- Spring Cache:RedisCacheManager。
- 分布式锁、延迟队列、限流:Redisson。
- 强一致状态变更:数据库约束和事务优先,Redis 锁只能辅助。
最后记一句:Template 管数据访问,Redisson 管分布式协作。先分清目标,再选工具。




