从事后端开发这些年,Redis几乎是避不开的一环。从最初把它当缓存用,到后来在排行榜、分布式锁、限流、消息队列等场景里反复实践,我对这个工具的认识也在不断变化。这次准备开一个“Redis实战”系列,第一篇文章我打算抛开官方文档式的罗列,直接从实战视角出发,讲清楚为什么学Redis、核心数据结构怎么选型、缓存三大经典问题怎么面对,以及持久化配置如何取舍。就算你是刚接触Redis的新手,或是在项目中用得还不够深,这篇文章都能帮你建立一条清晰的实战主线,读完可直接对照自己项目里的使用方式做优化。
1. 项目整体定位:为什么第一篇文章必须搞懂这些
1.1 Redis不是“缓存”两个字就能概括的
很多同学对Redis的认知停留在“它就是用来做缓存的”,这个认知不算错,但会限制你的使用思路。Redis全称是Remote Dictionary Server,本质是一个基于内存的键值型数据库。它之所以快,是因为数据在内存中读写,同时又提供了丰富的数据结构,只要合理设计key和value的形态,很多原本需要复杂业务计算的场景,用几条命令就能解决。
在实战中,我倾向于把Redis定位成三样东西的组合:第一,高性能缓存层,扛下数据库的热点读流量;第二,轻量级数据结构服务,用它来存储实时排行榜、在线状态、最近浏览记录这类动态数据;第三,分布式系统里的协调基座,像分布式锁、全局唯一ID、计数器、限流令牌桶这些场景,Redis都能提供原子操作支持。
理解了这一层,你在设计系统时就会主动思考“这个数据适不适合放到Redis里,用什么样的结构”。而不是遇到性能瓶颈了才想起来加一层缓存,结果把key设计得一团糟,后续维护成本居高不下。
1.2 这套实战方案适合哪些人参考
这篇博文的内容并不追求大而全,它的核心目标是帮助你完成一次从理论到实战的认知升级。如果你符合下面任意一类情况,这篇文章就是你需要的:
- 已经会用Redis的基本命令,但不知道业务中该怎么设计key和选择数据结构;
- 给项目加了Redis缓存,但线上时不时出现缓存穿透、数据不一致,不知道怎么系统排查;
- 面试或晋升答辩时需要讲清楚Redis项目经验,但缺少一套完整的实战话术;
- 想在公司内部推广Redis规范使用,需要一份从原理到底层操作的参考材料。
文章里的案例都是以模拟项目X为背景展开的,比如模拟项目X的首页内容缓存、排行榜功能、库存扣减等,这些场景在各行业业务里都很常见,你只需要稍微替换一下业务名词,方案可以直接复用。
2. 核心数据结构实战:用对口的数据结构解决对应场景
2.1 String不只是字符串,它还是计数器的基础
String是Redis里最基础的数据结构,key对应一个value,value可以是字符串、数字或者二进制数据。很多人用它缓存JSON序列化后的对象,这确实是最广泛的用法。但String还有一个很关键的用途,就是配合INCR、DECR做原子计数。
举个实际例子,模拟项目X中有一个文章阅读量统计的需求。最初我用MySQL的update语句直接累加,结果热点文章在活动期间单秒有几百次更新,数据库压力陡增。后来把计数放到Redis里,key设计成article:readcount:{articleId},每次用户点击文章就执行INCR。为了防止value无限增长,我还会定期把这个计数异步同步到MySQL,同步后重置为0或者减掉已同步的值。
类似的应用还有生成唯一编号。比如订单号需要按天生成自增序列,用INCR article:order:20250101这种形式很轻松就能拿到当天的自增序号。
需要注意的一点是,String虽然可以存数字,但Redis内部对数字也是有上限的,超过Long型范围会报错。另外,如果value是纯数字,一定要用整数存储而不是字符串拼接,否则INCR命令会失败。
2.2 Hash结构让对象存储不再繁琐
当你要存储一个对象的多个字段,比如用户信息包含用户名、年龄、城市、注册时间,如果直接用String存储整个JSON,每次修改只改一个字段也得把整个JSON拉出来反序列化再写回去。Hash结构就是解决这类问题的。
Hash在Redis里对应的是field-value的映射表。举个例子:
HSET user:1001 name "zhangsan" age 25 city "beijing" HGET user:1001 name HINCRBY user:1001 age 1HINCRBY这个命令很适合做对象内某个字段的原子增减,比如用户积分、等级成长值。在实际项目里,Hash还被用于存储某个商品的实时属性集合,例如库存、价格、状态,这样不同字段的读写互不干扰,可读性也更强。
Hash还有一个隐藏的优势:内存占用比String更省。当field数量小于等于512且字段值小于等于64字节时,Redis会使用ziplist编码,这种紧凑的内存结构能显著降低内存占用。所以同样是存储一批小对象,Hash往往比平铺的String更划算。
但同样要注意,不要把一个Hash塞成超大对象,单个Hash的field数量过多会触发哈希表扩容,内存优势消失,读写耗时也会增加。实战里,超过几千个field的业务场景,通常建议按某种规则拆分Hash。
2.3 List不只是队列,还是时间线数据的天然载体
List结构是双向链表,支持从两端压入弹出元素。它的典型用途包括:消息队列、最新动态列表、浏览历史等。
以模拟项目X的关注动态流为例,用户在首页需要看到最新10条关注对象的动态。如果用数据库拉取,要联表查询关注关系再按时间倒序,响应往往上百毫秒。放在Redis里,每当用户发布一条动态,就把动态ID用LPUSH feed:{userId} {feedId}推到用户自己的List里,同时推到每个粉丝的时间线List中。首页展示时执行LRANGE feed:{userId} 0 9,毫秒级返回。
这个方案有个细节要注意:List的长度需要控制,否则长期累积会让key越来越大,内存和读取成本同时上升。实践中通常设置一个最大长度,比如1000条,用LTRIM截断,或者在一个队列消费任务时,消费完的元素立刻LREM移除。
List做消息队列时有一个问题需要警惕:LPOP/RPOP是取出即删除,如果消费者拿到消息后处理失败,消息就丢了。可以引入RPOPLPUSH命令,从主列表取出的同时推入一个备份列表,处理成功后再从备份列表删除,这样失败后可以从备份列表里找回。这个操作是原子的,分布式环境下也安全。
2.4 Set的交并集,是标签系统和社交关系的利器
Set是无序、去重的字符串集合,最常用的是集合间的交、并、差运算。举几个业务例子你就明白它的价值:
- 去重统计:给某篇文章点过赞的用户ID,全部
SADD article:like:{articleId} userId,天然去重,统计人数直接用SCARD; - 共同好友:两个人的粉丝分别存成两个Set,
SINTER取交集就是共同好友; - 随机抽奖:把所有参与者ID存入Set,
SRANDMEMBER即可随机抽取中奖人; - 用户标签圈选:给每个用户打Set标签,运营平台需要圈出“最近7天活跃且购买过商品”的人群时,直接对两个Set求交集。
Set的运算在数据量大的时候要注意时间复杂度。SINTER两个百万级Set可能会消耗毫秒级时间,虽然是内存操作,但高并发下也要避免频繁执行大集合的交集运算。我的做法是将运算结果缓存成另一个Set,并设置过期时间,这样热路径上只是读取缓存结果。
2.5 ZSet是排行榜功能的灵魂数据结构
ZSet在Set的基础上给每个元素增加了一个score分数,Redis会根据score自动排序,范围查询、排名查询都极其高效。
模拟项目X里有个积分排行榜需求:用户完成任务获得积分,需要在首页展示Top100。最初我用数据库order by,数据量到几十万以后查询耗时完全不可控。切换到ZSet后,结构如下:
ZADD rank:points 1000 user:001 ZADD rank:points 2500 user:002 # 查询Top10 ZREVRANGE rank:points 0 9 WITHSCORES # 查询某用户排名 ZREVRANK rank:points user:001 # 给用户加分 ZINCRBY rank:points 500 user:001ZINCRBY这个原子命令对积分变更加分场景简直量身定做。更妙的是,除了按分数倒序拿排名,还可以用ZRANGEBYSCORE做按分数段的区间查询,例如查询积分在1000到2000之间的所有用户。
它的底层实现是跳表加压缩列表或哈希表的组合,插入和查询的平均复杂度都在对数级别,这意味着百万级数据量的排行操作依然是亚毫秒级。需要注意的是,score只能是双精度浮点数,如果业务中分数可能包含小数或负数,一定要在写入前统一格式化规则。
3. 缓存策略实战:穿透、击穿、雪崩的应对方案
3.1 缓存三兄弟到底是什么
任何使用Redis做缓存的项目,都绕不开“缓存穿透”、“缓存击穿”和“缓存雪崩”这三个问题。很多文章把它们解释得很玄乎,我用最直白的话总结如下:
- 缓存穿透:查询一个根本不存在的数据,Redis中没有,MySQL中也没有,于是请求每次都要穿透到数据库,数据库被无效查询打垮。
- 缓存击穿:某个热点key突然失效,恰好大量请求同时访问这个key,请求全部压到数据库上。
- 缓存雪崩:大量key在同一时间段集中失效,或者Redis服务不可用,导致请求全部打到数据库上,数据库被压垮。
这三个问题的处理思路完全不同,很多新人容易混在一起。我习惯用一个生活中的类比:缓存穿透是“总有人来店里问一个根本不存在的商品”,你每次都要去仓库翻找;缓存击穿是“爆款商品的标签贴纸刚好掉了,所有人一下子都涌进仓库问”;缓存雪崩是“店里所有商品的标签纸同一时间掉了,仓库瞬间被挤爆”。
3.2 缓存穿透:布隆过滤器与空值缓存
最常见的方案是缓存空值。如果数据库查不到,就在Redis里设置一个短过期时间的空值,比如cache:empty:{key} = nil,过期时间60秒。这样相同key的请求在短时间内不会再穿透到数据库。这个办法思路简单,实现成本极低,适合大多数业务场景。
更严谨的方案是布隆过滤器。它可以在请求进入缓存层之前就判定“这个key大概率不存在”,从而直接返回。布隆过滤器的原理是用多个哈希函数将元素映射到一个很长的位数组中,查询时检查对应位是否都为1,只要有一个位为0就一定不存在。它会有一定的误判率,但绝不会漏判。
在模拟项目X的查询接口中,我采用了两层方案:热点数据建布隆过滤器做前置拦截,非热点数据用缓存空值兜底。初始加载时将已有ID全部写入布隆过滤器,启动时一次构建即可。
注意事项:缓存空值时要留意外部接口的success/error状态,不要对错误响应也做缓存;布隆过滤器有误判,不适合对准确性要求苛刻的场景,比如支付校验类。
3.3 缓存击穿:互斥锁与逻辑过期
击穿针对的是单个热点key。解决思路有两个方向:一是让key在失效时不会同时涌入大量请求去数据库重建缓存;二是让key永不过期,但value里保存逻辑过期时间。
互斥锁方案的流程是:请求进来先查缓存,缓存不存在则尝试获取一个分布式锁,拿到锁的线程去数据库加载数据并写回缓存,其他线程等待一段时间后重新查询缓存。因为只有拿到锁的线程能访问数据库,数据库压力大减。
这里的分布式锁在模拟项目X中可以用Redis的SET key value NX EX seconds命令实现,释放时使用Lua脚本保证原子性。一个坑是,锁等待时间设计不合理容易引发大量请求超时。我的经验是等待时间通常设为500ms到1s,且设置合理的重试次数,同时返回降级数据而不是无限等待。
逻辑过期方案则是:缓存中value格式定义为业务数据加过期时间戳。比如缓存值为{"data": {...}, "expireTime": 1700000000000},当发现逻辑过期后,获取锁的线程去加载新数据更新缓存,其他请求在短暂时间内直接返回原有的稍旧数据。这个方案读多写少的场景下体验极好,因为读请求永远不会被阻塞。
3.4 缓存雪崩:过期时间加随机因子
雪崩和击穿的区别在于涉及范围。雪崩的核心应对不是解决访问冲突,而是避免“同时失效”。最简单的做法是,设置过期时间时加入随机因子,让key的失效时间均匀散开。
比如模拟项目X需要给一批商品缓存设置1小时过期,可以写成:
int expireTime = 3600 + RandomUtil.randomInt(0, 300);这样原本同一秒内集体过期的key,就被打散到5分钟内的不同时刻。另一个思路是热点数据采用永久缓存+后台异步刷新,这在缓存击穿部分已经提到。
更高一层的保障是Redis的高可用架构。实战中如果你手头资源允许,尽量配置哨兵模式或者集群模式,避免单节点挂掉导致所有缓存不可用。同时,业务侧还需要做降级方案:如果Redis不可用,直接读取数据库,但要开启线程池隔离和限流,防止数据库被拖垮。
4. 持久化机制选型:RDB与AOF的实战取舍
4.1 RDB快照:适合备份与重启恢复
RDB是Redis默认的持久化方式,它会在指定时间间隔内生成某个时刻的内存快照文件。RDB的优势是文件紧凑、加载速度快,非常适合做定时的冷备和容灾恢复。
它的工作原理是利用fork子进程,子进程将内存数据写入临时文件,写完后原子替换原RDB文件。整个过程中父进程依然服务请求,所以对线上的阻塞时间极短。
在模拟项目X中,我通常把RDB策略配置为:
save 900 1 save 300 10 save 60 10000含义是:900秒内有1次修改就触发快照,300秒内有10次修改触发,60秒内有10000次修改触发。这个配置适合对数据丢失容忍度相对宽松的场景,比如缓存类数据,丢了可以从数据库重建。
RDB有一个不能忽略的短板:两次快照之间的数据会丢失。如果Redis意外宕机,这几分钟内新增的数据就没了,对于需要高可靠性的业务数据,不能只用RDB。
4.2 AOF日志:更可靠的追加写
AOF(Append Only File)记录的是每一条写指令,以Redis协议格式追加到文件中。通过回放这些指令,可以把数据恢复到最后一次写入的状态。
AOF有三种刷盘策略:
appendfsync always:每条指令都同步刷盘,最安全,但性能开销最大;appendfsync everysec:每秒刷一次盘,性能与安全折中;appendfsync no:交给操作系统决定何时刷盘,性能最好但可能丢更多数据。
实战中,我几乎都是使用everysec。它兼顾了性能和数据安全,即使系统崩溃,也最多丢失不到1秒的数据。Redis官方也推荐这个策略。
AOF还有一个需要掌握的机制是AOF重写。随着运行时间变长,AOF文件会越来越大,启动恢复的时间也随之变长。Redis提供了BGREWRITEAOF命令,用当前内存数据集生成最小的AOF文件,替换旧文件。生产环境中,我通常设置自动触发阈值,例如文件大小超过上次重写后的100%时自动重写。
4.3 混合持久化:生产环境的实战推荐
如果你既想要RDB的快速恢复,又想要AOF的可靠性,Redis 4.0之后提供了混合持久化模式,配置项是aof-use-rdb-preamble yes。
在这种模式下,AOF文件头部是RDB格式的快照内容,后面追加增量日志。启动时Redis先加载RDB部分,再回放后续日志,恢复速度比纯AOF快很多,同时数据可靠性也接近AOF。这是我在线上环境的标准配置。
需要注意的点是,持久化不是“配置了就万事大吉”。你需要监控磁盘空间、RDB生成耗时和AOF文件大小。我在生产遇到过AOF文件增长到几十GB的情况,恢复时耗时过长,后来通过监控报警在文件达到一定阈值时手动触发BGREWRITEAOF解决。
另一个常见坑是fork操作耗时过长导致Redis阻塞。如果Redis内存占用极大,fork子进程复制页表会消耗几百毫秒,高并发下这些阻塞会放大成可用性抖动。缓解手段有不少:尽量控制单实例内存不超过8GB,或者改用集群分片降低单实例压力。
5. 实战过程中的常见问题与排查经验
5.1 缓存和数据库的数据不一致,如何根治
这是项目中最容易暴露的问题。比如用户修改了昵称,我们先更新数据库再删除缓存,但删除缓存失败,用户读到的还是旧数据。又或者先删缓存再更新数据库,期间有请求查到旧数据回填了缓存,导致后续读取一直拿到旧值。
解决思路有两个。第一个是延时双删:先更新数据库,再删除缓存,等待几百毫秒后再次删除一次缓存。之所以要延迟一次,是为了让“读请求把旧值写回缓存”这个窗口期过去。
第二个是更可靠的方案:利用消息队列异步删除缓存。将删除key的事件发布到消息队列,消费者获取后执行删除,失败则重试。结合数据库变更监听机制,比如监听MySQL的binlog变更事件,解析出变化的主键ID,再通知缓存删除。这个方案实现成本更高,但数据一致性最可靠。
在模拟项目X中,早期我用延时双删解决了大部分问题,但并发极高时仍然偶发不一致。后来切换到消息队列异步删除方案,配合定时任务扫描补偿,线上不再出现用户反馈数据不更新的情况。
5.2 key过期删除策略与内存淘汰机制
Redis的key过期删除采用惰性删除加定期删除的混合策略。惰性删除是访问时发现过期才删,定期删除是后台每100ms采样删除部分过期key。这两个机制并不能保证过期key被及时清理干净,所以当内存达到maxmemory配置上限时,Redis会触发内存淘汰策略。
常用的淘汰策略有:
noeviction:内存满时不淘汰,直接返回错误;allkeys-lru:从所有key中按LRU淘汰最近最少使用的键;volatile-lru:仅在设置了过期时间的key中按LRU淘汰;allkeys-random:随机淘汰。
实战建议是优先使用allkeys-lru,如果业务中有一些key设置了TLL但热度很高,而别的key永远不过期且很少用,你其实希望系统能淘汰那些“死数据”。allkeys-lru可以做到。
这里有个很多人忽略的点:Key是否设置过期时间,直接影响淘汰策略的行为。不要依赖过期清理来释放内存,而是要保证缓存数据本身有合理的TTL设计。比如模拟项目X中,所有业务缓存必须设置过期时间,禁止无TTL的key直接写入Redis,只有极少数全局配置才允许长期驻留。
5.3 bigkey与热key,线上事故的两大元凶
bigkey是指存储了大量数据的key,比如一个Hash里有几十万字段,或者一个List有几百万元素。bigkey的问题是:删除时阻塞主线程,读取时网络带宽占用高,持久化时fork的负担也更大。排查bigkey可以使用--bigkeys参数扫描,它会统计各类结构中最大的key。
生产上碰到bigkey需要一个治理策略,我的做法是将大对象拆分成多个小key,比如按用户ID范围分片,每个分片控制在较小规模。List这类时序数据则必须按时间窗口滚动,及时清理旧数据。
热key是指短时间被大量请求访问的key,比如秒杀商品的库存、某个明星的微博详情。热key会导致Redis单分片CPU过高,如果该key所在节点挂掉,相关业务全部受损。排查热key可以用redis-cli --hotkeys,配合慢查询日志和监控指标。
缓解热key的手段包括:本地缓存加Redis多级缓存组合;将一个热key复制成多个副本key,比如hotkey:1到hotkey:10,请求随机访问其中一份,分散压力;或者对热点数据升级为独立的Redis分片。在模拟项目X的双十一大促场景中,我们采用本地缓存加副本key的方式,将热点接口的Redis压力降低了八成。
6. Redis客户端选型与连接管理
6.1 主流客户端对比
Java生态里最常用的两个客户端是Jedis和Lettuce。Jedis是直连模型,每个线程独占一个实例,简单直接但连接利用率低;Lettuce基于Netty,连接共享,支持异步和响应式编程,Spring Boot 2.x之后默认集成Lettuce。
如果你用的是Go,比较推荐go-redis,它同时支持单机、哨兵和集群模式,接口设计也很顺手。
在你做技术选型时,我建议优先考虑团队的技术栈和框架生态。Spring Boot项目直接用默认的Lettuce足够,如果遇到连接池不够用的场景,再针对Lettuce做参数调优。不要为了“性能比拼”随意换客户端,客户端层造成的问题往往比收益更麻烦。
6.2 连接池参数与生产配置建议
以Jedis和Lettuce为例,连接池的配置直接决定高并发下的表现。我见过很多项目因为连接池maxIdle设置过小,导致高峰期不断创建新连接,性能骤降。
一个相对合理的初始配置(按单节点内存16MB以内、核心线程池8核计算):
spring: redis: host: 192.168.1.10 port: 6379 timeout: 3000ms lettuce: pool: max-active: 50 max-idle: 20 min-idle: 5 max-wait: 3000msmax-active即最大连接数,一般按照(业务核心线程数 *(1 + 阻塞系数))估算。阻塞系数通常取0.5到1,如果你的请求中Redis操作占比很高,就取大一些。
连接池也不是越大越好,过大的连接数会占用Redis端的内存和文件描述符,反而可能拖垮服务。线上建议通过压测确定最优值,一般单实例应用50到100个连接足够应对绝大多数场景。
7. 从单机到分布式:Redis部署形态的实战思考
7.1 单机、哨兵、集群各自适用什么情况
很多初学者在项目一开始就纠结要不要上集群。我自己的经验是,部署形态应当根据数据量和可用性需求逐步演进。
单机节点适合开发环境或业务量极低的小项目,部署简单,配置方便,但一旦宕机就全盘不可用。当你的项目上了生产并开始有稳定流量后,至少应该用主从加哨兵模式。主从复制解决单点问题,哨兵负责监控和自动故障转移,对业务来说只是换了一个地址,无需改代码,却能把可用性提升到99.9%以上。
当数据量超过单节点内存上限,或者写并发远超单节点能力时,就需要走Redis Cluster模式。Cluster将数据按哈希槽分布到多个节点,每个节点负责一部分槽位。它支持自动分片和水平扩展,但客户端连接方式略有不同,命令也有约束,比如不支持跨节点的MGET。
我的建议是:不要急于上Cluster,数据量几百GB以内、QPS几千到几万的业务,用Redis单机加哨兵完全足够。分布式带来的复杂度会让问题排查难度成倍提升,没有充分理由不要自找麻烦。
7.2 部署时的常见坑与优化项
把Redis部署到生产环境时,有一些系统层面的优化项经常被忽略,但它们对稳定性影响极大。
第一个是关闭透明大页。Linux的THP(Transparent Huge Pages)机制会导致Redis fork子进程时内存页复制效率降低,建议在部署时执行:
echo never > /sys/kernel/mm/transparent_hugepage/enabled第二个是设置合理的vm.overcommit_memory。Redis执行BGSAVE或BGREWRITEAOF时需要fork,如果系统内存不足可能导致fork失败,建议设置为1。第三个是修改somaxconn,默认值太小会导致高并发连接被拒,通常调大到511或1024。这些配置写在系统级的sysctl.conf中,重启后依然生效。
部署完成后,记得用redis-benchmark做一次基础压测,确认当前机器配置下Redis能达到的QPS量级,做到心中有数。模拟项目X上线前,我们通过压测发现单节点在纯读场景下可以达到10万QPS,在写多读少场景下只有4万左右,后续扩容决策全部基于这些数据。
8. 常见操作速查与实战填坑手册
8.1 key设计与命令规范建议
我在多个项目里总结了一套key命名规范,可以大幅降低维护成本:
- 层级之间用冒号分隔,如
业务模块:实体名称:id:属性; - 同一类key的前缀保持一致,方便统计和运维清理;
- 所有缓存key必须设置TTL,除非是明确的全局配置;
- key名称中避免包含空格、换行符和Redis特殊字符;
- 禁止使用超长key,超过128字节也会增加内存和网络开销。
举个例子,模拟项目X的购物车缓存设计为:
cart:{userId}:items cart:{userId}:totalPrice这种设计一眼就能看懂属于哪个业务的哪个实体,后续写清理脚本和监控报警也方便。
8.2 线上应急排查命令
Redis出问题时,先别慌,按顺序执行下面这些命令,基本能定位大多数故障。使用INFO查看整体运行状态,关注内存、连接数、命中率等关键指标。使用SLOWLOG GET查看慢查询,定位耗时操作。使用MONITOR实时监控命令,但这个命令生产环境慎用,会显著影响性能。使用CLIENT LIST查看客户端连接情况,排查连接泄漏。
如果是内存增长异常,先看INFO memory里的used_memory和used_memory_peak,再通过redis-cli --bigkeys或redis-cli --memkeys找出内存占比高的key。如果是延迟抖动,可以观察INFO stats里的瞬时操作数,以及系统层面的CPU和网络指标。
日常巡检时,我建议每台Redis节点都接入基础监控,至少覆盖以下指标:命中率、内存使用率、连接数、命令QPS、key过期总数和主从复制延迟。一旦命中率低于80%或者内存使用率超过70%,就要检查缓存设计是否存在问题。
做Redis实战不是把几条命令背熟就完事,而要把数据结构、缓存策略、存储机制和运维手段串起来,理解每一步操作背后的取舍。这篇作为系列开篇,我把主线框架搭好,后续文章中会围绕分布式锁的几种实现与坑、Redis与MySQL的一致性方案、Redisson源码解析、大促场景下的缓存治理实战等方向继续展开。如果你看完这篇文章,能对自己项目里Redis的使用方式多一些审视和思考,那么这个系列的价值就达到了。