Redis典型使用场景全解析:缓存、分布式锁、排行榜、消息队列与限流

Redis典型使用场景全解析:缓存、分布式锁、排行榜、消息队列与限流 用Redis这些年我最大的感受是多数人把它当成一个“缓存小工具”存个验证码、顶个Session然后就没有然后了。但Redis能做的事情远比“缓存”两个字宽泛得多。无论你是准备面试还是想把现有项目的架构做得更干净搞清楚Redis的典型使用场景都特别值。这篇文章我打算用实际项目的视角把Redis最常见的五种用途完整拆一遍缓存加速、分布式锁、排行榜、轻量消息队列、计数与限流。每种用途我都会讲清楚底层靠什么数据结构支撑、怎么落地、有哪些坑是文档里不会写的。文章里也会顺带把Redis的安装、持久化、主从搭建、可视化工具选择这些周边话题聊到位毕竟这些是动手实践绕不开的环节。如果你过去只用过get/set看完这篇应该会对Redis有一个完全不一样的认识它其实是一把功能丰富的瑞士军刀就看你会不会用。1. 为什么是这五种用途先看Redis到底强在哪Redis全称是Remote Dictionary Server翻译过来就是远程字典服务。它本质上是一个基于内存的键值数据库所有数据都存储在内存里所以读写速度极快单机QPS可以达到十万甚至更高。这个“快”是最核心的竞争力后面聊到的所有用途本质上都是在利用这个快。1.1 单线程模型与IO多路复用很多人第一次听说Redis是单线程的会有点懵单线程怎么能支撑那么高的并发这里有个容易混淆的概念。Redis的单线程是指它的命令执行是串行的所有命令在同一个线程里按顺序执行不存在多线程竞争问题所以也不需要加锁。但Redis的IO层用的是多路复用机制可以同时处理大量网络连接请求就像一个大厨一个人掌勺虽然一次只能炒一道菜但他能同时接待很多顾客的点单效率并不低。这个设计的妙处在于所有命令都是原子性的天然避免了一堆并发写导致的脏数据问题。你不需要担心两个客户端同时对一个key做增减操作会出错因为Redis会一个一个地执行命令。这一点在后面要讲的分布式锁、计数器、限流场景中非常关键。1.2 五种用途背后的数据结构支撑Redis不是简单的key-value它提供了丰富的底层数据结构不同场景本质上是不同数据结构的合理运用。数据结构底层实现典型使用场景String动态字符串缓存、计数器、分布式锁Hash哈希表对象存储、购物车List双向链表消息队列、时间线Set哈希表或整数集合去重、共同关注ZSet跳表 哈希表排行榜、延时任务Stream消息流结构正式消息队列、日志聚合你会发现文章的这五种用途每一种都对应着至少一种核心数据结构。理解了这个映射关系面试时被问到“Redis为什么快”或者“Redis有哪些数据类型”这类问题你的答案会显得很有体系。我在实际工作中也见过有人用String硬生生堆出排行榜的功能也不是不能用但代码复杂度会高很多这也说明选对数据结构往往比堆逻辑更重要。1.3 怎么判断你的项目该用第几种这个没有标准答案但我有一个比较粗糙的判断框架看你的需求里是否有“高并发读写”、“实时性要求高”、“不想引入重量级组件”这几个特征。比如你需要给首页做热点数据缓存那就用第一种多个服务节点要抢同一批资源就用第二种要展示热销榜、活跃榜用第三种比写SQL联表查询高效得多服务间要做简单的异步通知又不想为此单独部署一套消息队列可以考虑第四种至于计数、限流、用户在线状态这种高频小数据操作第五种就是标准解。记住Redis不是万金油它没有事务的ACID完整性持久化能力也比不上真正的数据库所以在方案选型时要清楚边界。下面的内容我会把每种场景从原理到落地细节逐个展开。2. 用途一缓存加速——最基础也最容易翻车缓存是Redis最广为人知的用途没有之一。把数据放进Redis访问时先查缓存查不到再查数据库然后回填缓存这套流程很多人在项目里第一天就写过。但真正做过线上缓存的人会告诉你缓存带来的麻烦往往和它解决的问题一样多。2.1 缓存穿透、击穿与雪崩这三个词是Redis面试题里的常客也是线上故障的高发原因。缓存穿透查询一个不存在的key缓存里没有数据库里也没有请求直接打到数据库。如果攻击者故意构造这种key数据库压力会瞬间暴涨。缓存击穿某一个热点key在过期的一瞬间大量请求同时进来发现缓存没了全部打到数据库。缓存雪崩大量key在同一时间集体过期或者Redis直接宕机导致所有请求全部压在数据库上。处理穿透的办法是缓存空值或者用布隆过滤器击穿的解法是热点key不设过期时间或者用互斥锁保证只有一个请求去数据库查询雪崩的解法是设置过期时间时加一个随机抖动让key的过期时间分散开同时做Redis的高可用架构。我自己的习惯是三个手段一起用。空值缓存最省事但要注意设置一个较短的过期时间避免一堆不存在的key把内存吃掉。布隆过滤器需要额外的存储和维护成本适合数据量很大且穿透量高的场景。2.2 缓存与数据库的一致性这是缓存场景里争议最大、坑最深的问题。先更新数据库再删除缓存还是先删缓存再更新数据库无论怎么选都存在时间窗口。我目前用得最多的方案是Cache Aside模式读的时候先读缓存读不到读数据库回填写的时候先更新数据库再删除缓存。这个模式配合延迟双删更新数据库后先删一次缓存隔几百毫秒再删一次在大部分业务场景下都能把不一致的概率降到很低。要注意的是如果缓存删除失败会出现旧数据长期存在的隐患。所以我建议删除缓存这个操作要做失败重试最简单的做法是把删除动作丢到消息队列里异步处理保证最终一致。2.3 缓存序列化与内存淘汰策略缓存场景里还有一个特别容易被新手忽略的点序列化。项目里的Java对象没法直接塞进Redis要么用JDK自带的序列化默认会用jdk序列化导致key里出现一堆 \xAC\xED 这种乱码前缀要么用JSON序列化要么用Protobuf这类二进制格式。我的建议是如果你为了实现简单用JSON如果对性能要求高用Protobuf。最好在配置里统一指定序列化器避免项目里出现多种序列化格式混用否则排查问题时会很痛苦。内存淘汰策略也是一个必须提前定好的参数。Redis默认在内存满了之后会拒绝写入这对生产环境来说是致命的。你可以通过配置 maxmemory-policy 来指定淘汰策略maxmemory 4gb maxmemory-policy allkeys-lru常用策略有 noeviction不淘汰写入报错、allkeys-lru所有key按LRU淘汰、volatile-lru仅对设置了过期时间的key做LRU淘汰。我个人推荐大部分业务用 allkeys-lru这样即使有人忘记设置过期时间内存也不会直接被打爆。不过要注意这个参数最好在项目早期定下来线上改策略是有风险的。提示缓存场景非常考验key命名规范。我在项目里统一用“业务名:对象名:ID”的格式比如 user:profile:12345。这样在命令行排查问题时一眼能看懂也方便后续做批量操作。3. 用途二分布式锁——并发安全的硬骨头在单机应用里多个线程抢资源可以用synchronized或Lock解决。但系统一旦拆成多个服务节点或者同一个服务部署多份实例JVM级别的锁就没有意义了因为不同的进程根本不会互相感知。这时候需要一个跨节点的互斥机制Redis分布式锁就是最常用的方案之一。3.1 为什么用Redis做分布式锁分布式锁的常见实现有数据库锁、ZooKeeper锁、Redis锁。数据库锁简单但性能差还会对数据库产生压力ZK锁可靠性高但需要维护一套ZK集群Redis锁性能最好、实现简单而且大部分项目本来就有Redis不需要额外引入组件。这也是它在业界这么流行的原因。Redis实现分布式锁的核心思路是多个客户端同时尝试写入同一个key只有写入成功的那个客户端才算是拿到了锁。因为有单线程模型和原子命令的支撑这个竞争过程是安全的。3.2 最简实现SET NX EX从Redis 2.6.12之后官方推荐用一条命令实现加锁SET lock:order:10001 unique_value NX EX 30这条命令里的NX表示只有key不存在时才设置成功EX 30表示锁的过期时间是30秒unique_value是客户端生成的唯一标识。这样一来加锁和设置过期时间在一个原子操作里完成不会出现“加了锁忘记设过期时间导致死锁”的问题。释放锁的时候不能简单地DEL key因为你可能把别人后来获取的锁给删掉。正确做法是用Lua脚本保证“判断标识删除”是原子的if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end这里的思想就是“谁加的锁谁来解”。只要设置的value是客户端自己的唯一标识释放前先校验就能避免误删其他客户端持有的锁。3.3 三个经典坑死锁、误删、锁过期分布式锁最经典的一类面试连环题就是围绕这三个问题展开的。先说死锁。如果只用了SETNX加锁没有设置过期时间客户端在加锁后还没来得及释放就崩溃了这个锁就永远没人能释放其他客户端一直拿不到锁。解决办法就是加过期时间。然后是误删。如果一个客户端持锁时间太长锁已经过期自动释放了另一个客户端抢到了锁这时第一个客户端执行完业务代码去执行DEL会把第二个客户端的锁删掉。解决办法就是前面提到的唯一标识Lua脚本。最后是锁过期但业务未完成。这个问题比误删更隐蔽。你设置了30秒过期但业务代码执行了50秒锁中途没了另一个客户端又进来执行同样的业务互斥就失效了。解决办法是给锁做自动续期也就是“看门狗”机制。Redisson内部就实现了这个功能默认是每10秒会检查一下锁是否还在如果还在就把过期时间重置为30秒。我自己做项目时如果不想引入Redisson会用定时任务模拟续期但这个复杂度不低所以一般还是建议直接用成熟框架。3.4 Redisson和RedLock到底怎么选Redisson是Java生态里最主流的Redis客户端库之一它封装了分布式锁的全部细节用起来非常方便。如果是Java项目直接用Redisson的RLock就好没必要自己造轮子。RedLock是Redis作者提出的多节点锁方案要求在多个独立部署的Redis节点上同时加锁超过半数成功才算获取成功。这个方案在分布式系统领域一直有争议因为它依赖每台Redis节点的时间同步而且如果节点发生GC暂停锁依然可能失效。我的建议是绝大多数业务场景单节点的Redis分布式锁加Redisson的续期机制已经足够只有对安全性要求极其苛刻的场景才需要考虑RedLock而且那时候你还要思考一个问题——是不是选ZooKeeper更合适。分布式锁相关的话题在Redis面试题里几乎是必考的把这一节的内容吃透应付面试绰绰有余。4. 用途三排行榜、排名与限时活动——有序集合的用武之地排行榜功能看起来简单真正做起来很麻烦。数据量大时SQL的ORDER BY加LIMIT在线上根本扛不住如果榜单还要求实时更新那更是一场灾难。Redis的ZSet就是为解决这类问题而生的。4.1 ZSet的底层原理ZSet有序集合每个元素绑定一个分数scoreRedis会按照分数从小到大自动排序。它的底层实现是跳表加哈希表哈希表用来快速定位元素跳表用来维护有序序列。跳表的查询和更新复杂度都是O(log N)性能非常稳定。ZSet常用命令就那么几个ZADD添加元素或更新分数ZINCRBY对某个元素的分数自增ZREVRANGE按分数从大到小取一段元素ZRANGE按分数从小到大取一段元素ZRANK / ZREVRANK获取某个元素的排名ZSCORE获取某个元素的分数4.2 直播打赏榜与商品热销榜以直播打赏榜为例用户给主播刷礼物时只需要执行一条命令ZINCRBY live:rank:room_1001 100 user_888ZINCRBY会把 user_888 的分数增加100并且自动调整它在集合里的排序位置。排行榜要展示Top10的时候ZREVRANGE live:rank:room_1001 0 9 WITHSCORES这两条命令就能完成从“打赏”到“榜单更新”的全流程不需要任何额外的计算逻辑而且延迟是毫秒级的。如果用MySQL来做每次打赏都要UPDATE查榜单还要ORDER BY数据量大了以后基本没法玩。商品热销榜也是同理用户每下一单就ZINCRBY一次按销量排序的榜单实时就出来了。还有文章的阅读榜、视频的热度榜、游戏玩家的积分榜都是同一个套路。4.3 分页、同分与内存开销Redis的分页和MySQL的分页思路略有不同。ZSet没有LIMIT那种写法但ZREVRANGE本身就支持start和stop参数这就是天然的分页ZREVRANGE leaderboard 0 9 WITHSCORES -- 第一页 ZREVRANGE leaderboard 10 19 WITHSCORES -- 第二页这里要小心一个坑如果榜单里存在大量同分的情况比如一万个人都是100分ZSet在相同分数下会按字典序排列翻页时会出现顺序不稳的问题。解决办法是设计分数时把时间因素编码进去比如用“业务分数 时间戳/10000000”这种格式让分数在业务值相同的情况下仍然有区分度避免同分大量堆积。内存方面也要有心理预期。ZSet内部每个元素都要存储member和score元素越多内存越大。一个包含几百万用户的长榜单内存占用可能会让你惊讶。所以在设计时要想清楚榜单的体量——是全局Top100这种只需要保留部分数据的还是所有用户都需要有排名的。两种场景的存储策略完全不一样。5. 用途四消息队列与延时任务——用Redis做解耦的轻量方案消息队列大家首先会想到RabbitMQ、Kafka这些专业组件但有些小场景性能要求没那么高又不想引入一堆新组件用Redis顶一顶是完全可行的。5.1 List实现简单队列List的LPUSH加BRPOP组合是Redis做消息队列最传统的方案。生产者用LPUSH把消息推入列表消费者用BRPOP阻塞等待新消息一旦有消息就弹出并处理。LPUSH task_queue new_task BRPOP task_queue 0BRPOP的阻塞特性非常方便多个消费者也能同时消费一个列表天然实现了负载均衡。这套方案在数据量不大、对消息可靠性要求不高的场景下足够用。但它的短板也很明显消息不支持广播一个消息只能被一个消费者取走没有确认机制消费者取走消息后如果处理失败消息就丢了List本身也没有消息ID这类概念来重复消费很麻烦。5.2 Stream类型后来的正式答案Redis 5.0引入了Stream类型可以理解成Redis官方对消息队列场景的正规支持。它支持消费者组、消息ID、ACK确认、pending list这些专业消息队列才有的特性。基本用法长这样XADD order_events * event_type create order_id 10001这条命令会往 order_events 这个Stream里追加一条消息星号表示让Redis自动生成消息ID。消费者读取消息用XREAD组内消费用XREADGROUP。消费者处理完消息后要执行XACK告诉Redis这条消息已经处理完毕如果消费者挂了没XACK消息就会一直挂在pending list里可以重新分配给别人消费。我自己实际用过Stream做订单事件的通知体验是比List可靠很多和RabbitMQ相比功能上确实还有差距但胜在简单不需要额外部署任何服务。5.3 延时任务的经典做法ZSet定时扫描延时任务是另一个常见需求。下单后30分钟不支付自动取消、发布的活动到点自动上线这些场景都可以用ZSet实现。实现思路很简单把任务ID作为member执行时间戳作为score存入ZSet。然后用一个后台任务每隔一段时间查询一次把score小于当前时间的元素取出来一个个执行ZADD delay_task 1735200000 order_10001 ZRANGEBYSCORE delay_task 0 现在的时间戳 ZREM delay_task order_10001取出来之后要执行ZREM把它删掉防止重复消费。这里建议用Lua脚本把“取删”做成原子操作避免多实例同时扫描时重复执行任务。这个方案的精度取决于轮询的间隔如果每隔1秒扫一次延时任务的误差就在1秒左右。对于订单取消这种场景完全够用。Redis里还有一套事务命令MULTI/EXEC如果你确实需要多步操作一起执行可以用它保证一段命令连续执行但要注意Redis事务是不支持回滚的别拿它当数据库事务用。5.4 什么场景不该用Redis做消息队列轻量归轻量方案的边界必须讲清楚。首先消息不能丢的场景不要用Redis。Redis的持久化是异步的主从切换时数据会有丢失窗口其次需要消息回溯、消息重放、海量积压的场景不要用。Redis内存再大也有限消息积压到内存被写满会引发连锁故障最后复杂路由、死信队列、延迟重试这些高级特性Redis也基本没有。总的来说小流量、能容忍少量数据丢失、不想维护额外组件的内部场景用Redis没问题核心业务链路的核心消息还是老实上专业MQ。6. 用途五计数、限流与用户状态——原子操作的日常魔法最后一类用途可能没那么起眼但非常高频计数器、限流、用户会话管理、在线状态统计。这类需求的特点是操作小而频繁对性能要求很高Redis几乎成了唯一合理的选项。6.1 INCR做计数器的威力Redis的INCR命令可以对一个String类型的值做加一操作并且是原子性的。播放量、点赞数、评论数、库存扣减这些高频写操作如果直接打在数据库上数据库压力会很大而且并发更新时还会产生行锁竞争。放到Redis里一次INCR就能搞定INCR article:view_count:888同类的还有DECR做减一操作INCRBY/DECRBY做增减指定数值。实际项目中我一般让Redis先扛住高频写入然后通过定时任务把计数定期同步回数据库保证最终一致性。Redis挂了对业务影响也不会太大因为数据库里还有兜底数据。6.2 限流最简单的是计数器限流限流的本质是“单位时间只允许处理N个请求”。最简单粗暴的实现就是用INCR加EXPIREINCR api:call:user_888 -- 请求计数1 EXPIRE api:call:user_888 60 -- 设置60秒过期第一次进来时设置过期时间之后每次先判断当前计数值是否超过阈值超过就拒绝请求。这套逻辑用Lua脚本写可以保证判和增是原子的local count redis.call(INCR, KEYS[1]) if count 1 then redis.call(EXPIRE, KEYS[1], ARGV[1]) end if count tonumber(ARGV[2]) then return 0 end return 1这一段简单的脚本就能做成一个好用的固定窗口限流器。要更平滑的限流效果可以考虑令牌桶或漏桶算法Redis同样能实现只是复杂度高一些。6.3 Session共享与用户状态传统单体应用把Session存在本地内存一上多实例就出问题。解决思路是把Session换到Redis里所有实例共享同一个会话存储。登录成功后把用户信息写入Redis并设置过期时间每次请求校验Redis里的数据即可。用户在线状态也可以用Redis的Set来做用户上线时SADD到online_users集合下线时SREM移除查在线人数直接SCARD查某人在不在线就用SISMEMBER。这套操作全部是O(1)级别比查数据库高效太多了。6.4 位图与日活统计如果你听说过Redis的数据类型里还有一种叫Bitmap位图的玩法那它常常被用在统计类场景。比如要统计一个用户一年里每天是否登录可以用SETBIT命令按天设置位值SETBIT user:login:2024 1 1 -- 用户在第2天登录过 BITCOUNT user:login:2024 -- 统计这一年登录过的天数位图的最大优势是省内存。一个用户存一整年的登录记录只需要365个bit不到50个字节。上亿用户也就几百MB这在传统的统计方案里是难以想象的。日活统计、连续登录天数这些场景用位图来做都非常漂亮。注意Redis没有单独的位图数据结构它是String类型的特殊操作。所以SETBIT之前这个key的底层就是一个普通的String只是被你按位来用了。7. 部署与运维层面的后顾之忧聊完五种用途必须把运维侧的事情补上。因为不管哪种场景前提都是Redis要稳定运行。这里我不聊太复杂的内容只把最常见、最实用的几个内容讲清楚安装部署、持久化、主从、可视化工具以及常见故障排查。7.1 从Windows本地方案到生产环境Docker部署很多人第一次接触Redis是在Windows上。Redis官方其实一直不提供Windows版本目前网上的Windows包大多是微软技术团队维护的老版本移植。如果你只是为了学习装一个Windows版在本地玩完全没问题生产环境一律建议用Linux或者容器部署。生产环境我最推荐的是用Docker Compose一键部署。下面是一个我在多个项目里验证过的部署模板包含数据目录挂载、密码认证、AOF持久化和基础监控services: redis: image: redis:7.2-alpine container_name: redis-server restart: always ports: - 6379:6379 command: redis-server --requirepass your_strong_password --appendonly yes --appendfsync everysec volumes: - ./redis-data:/data - ./redis.conf:/usr/local/etc/redis/redis.conf healthcheck: test: [CMD, redis-cli, -a, your_strong_password, ping] interval: 10s timeout: 3s retries: 5这个Compose文件里我开了AOF持久化这样Redis重启后数据不会丢太多。生产环境还建议把maxmemory和maxmemory-policy也配好避免内存写满。如果你是刚接触Docker部署注意挂载目录的权限就行Redis容器默认用uid 999跑宿主机目录需要设置好写权限。7.2 持久化RDB和AOF怎么选Redis的持久化方式有两种RDB快照和AOF日志。RDB是周期性把内存数据以二进制快照形式写到磁盘恢复速度快适合做数据备份和灾备缺点是两次快照之间的数据会丢失。AOF则是把每次写操作追加到日志文件里数据安全性更高但文件会越来越大恢复速度也更快。Redis 4.0之后支持混合持久化也就是RDB做全量快照AOF只记录增量兼顾了恢复速度和安全性。我的习惯是缓存场景只用RDB甚至不开持久化问题都不大反正丢了可以从数据库回填计数、锁、消息这类不能丢核心数据的场景必须开AOFappendfsync建议设成everysec性能和可靠性相对均衡。7.3 主从复制与高可用主从复制是Redis高可用的基础。一个主节点负责写多个从节点负责读从节点通过replicaof配置同步主节点的数据# 从节点配置 replicaof 192.168.1.10 6379 masterauth your_password配置好之后主节点写进来的数据会自动同步到从节点。这套模式下读流量可以分摊到多个从节点主节点挂了以后配合哨兵Sentinel可以自动把某个从节点提升为主节点。我特别想提醒一句主从复制是异步的主节点写入成功后数据可能还没来得及同步到从节点此时主节点挂了这部分数据就丢了。所以在分布式锁这种对一致性要求高的场景里主从架构反而会引入新的风险这也是RedLock思想出现的背景。你需要根据业务对数据安全的要求在架构层面上做好权衡。当你想搭建多套主从做高可用时建议先把基础的主从同步跑通再考虑增加哨兵。直接上全量架构一旦出问题排查范围会非常大。7.4 可视化管理工具怎么选平时命令行操作Redis够用但复杂一点的排查可视化管理工具会方便很多。目前社区里主流的有这几款工具平台特点Redis Desktop ManagerWindows/Linux/macOS老牌工具UI成熟部分高级功能收费Another Redis Desktop ManagerWindows/Linux/macOS免费开源Golang开发性能不错RedisInsightWindows/Linux/macOSRedis官方出品功能最全支持图形化分析redis-cli命令行轻量SSH远程排查首选我自己常用的组合是命令行的redis-cli加上RedisInsight。redis-cli适合快速连接执行命令RedisInsight用来分析大key、慢日志、内存占用这类问题图形界面能少走不少弯路。也有人习惯用Another Redis Desktop Manager它很轻巧做日常数据浏览和key删除非常顺手。7.5 常见故障排查技巧最后分享几个我实际踩过的坑做成一个速查表供你参考现象排查方向连接超时或拒绝连接检查bind配置和防火墙确认requirepass密码看客户端连接数是否打满内存暴涨检查是否有大量key没设过期时间用MEMORY DOCTOR命令分析内存占用考虑是否大key聚集Redis卡顿、命令阻塞用SLOWLOG查慢命令看是否有KEYS这类O(N)命令检查RDB持久化是否频繁数据丢失检查AOF是否开启、appendfsync配置主从切换时是否有复制延迟主从不同步查看从节点日志确认masterauth配置检查网络和磁盘IO另外还有一个小建议线上Redis别用KEYS命令做模糊匹配它会阻塞整个Redis导致所有请求卡死。如果确实需要扫描key用SCAN命令配合游标分批遍历执行效率虽然低点但不阻塞主进程。这个坑我见过不止一次每次都有人因为一条KEYS命令把线上服务搞挂。Redis的日志也是排查问题的重要入口。容器部署时可以通过docker logs实时看日志物理机部署时日志路径一般在启动命令或配置文件里指定。遇到奇怪问题先看日志往往比瞎猜定位快得多。用了这么多年的Redis我的体会是它确实不是万能的但它把内存操作、数据结构、原子命令这些能力组合在一起几乎覆盖了我们日常开发里最常用的那批场景。这篇文章写的五种用途每一种单独拎出来都能撑起一个大功能模块。如果你正在准备面试把这五种场景的原理、用法、坑都过一遍Redis相关的题目基本不会慌如果你在写业务代码遇到类似需求也可以少走很多弯路。如果有人问我建议从哪里开始我会说先把本机环境装起来把五种用途的示例代码都跑一遍。实践永远比看文章来得快。后面如果有机会我还会再聊聊Redis在缓存治理和集群模式下的更多细节以及如何对Redis做监控和容量规划。