其实很多朋友第一次看到“设计一个分布式缓存系统”这种题,第一反应是:分布式缓存不就是 Redis 集群吗?把 Redis Cluster 搭起来,客户端连上去,好像就完事了。但在真正的系统设计面试或实际架构评审里,面试官想听的不是“用哪个开源组件”,而是你有没有把缓存当做一个独立系统来思考:数据怎么分片、请求怎么路由、缓存和数据库的一致性怎么保证、节点挂了怎么办、热点数据会不会把集群打爆。这背后的能力,才是架构师和普通开发者的分水岭。
这篇文章我打算按一个完整的模拟面试记录来写,从需求澄清开始,到数据分片、一致性、高可用、监控治理,最后给出一套可以直接套用的答题框架和参考答案。不管你是准备面试,还是公司内部要做缓存中间件选型,这套思路都能直接用上。我会把设计逻辑、常见坑、以及一些面试官喜欢追问的细节都摊开来讲。
1. 开始之前,先把题目边界划清楚
一上来就谈 Redis、Memcached、一致性哈希,这是新手最容易犯的错。系统设计题的第一原则是:没有需求的设计就是耍流氓。同样叫“分布式缓存系统”,你做的是一个几百 QPS 的内部工具,还是要支撑百万 QPS 的电商大促,设计方案完全不一样。所以拿到题目后的第一件事不是画架构图,而是“问问题、定边界、立指标”。
1.1 功能需求和非功能需求怎么拆
功能需求一般来说很直观:读缓存、写缓存、设置过期时间、支持删除 key。只要你做的是通用缓存,基本就是这四类操作。如果有更细的业务场景,比如需要支持按前缀批量扫描、需要支持事务、需要支持 Lua 脚本,那就直接把复杂度拉高了一个等级。正常系统设计面试题,默认不需要把这些高级功能全做进去,提一嘴即可。
非功能需求才是设计的核心。你需要搞清楚这几个数值:
- 数据总量:单机内存能放下吗?比如 100 GB 的数据,单机 64 GB 内存就放不下,必须分片。
- QPS 和延迟:读多写少还是读写均衡?平均延迟要求是多少,p99 延迟要求又是多少。
- 可用性要求:允许缓存节点故障吗?故障后是降级到数据库,还是需要自动切换?
- 一致性要求:缓存和数据库之间是强一致还是最终一致?多副本之间允许短暂不一致吗?
把这些数字拿到手,你才能决定架构的复杂程度。比如说,数据量只有 10 GB,读 QPS 只有 5 万,那我觉得单机 Redis 加一个 AOF 持久化就够用了,非要上一套代理分片集群反而增加了运维负担。但如果是 1 TB 数据、读 QPS 500 万、要求故障 1 分钟内自动恢复,那你就必须考虑分片、副本、多机房容灾这些重机制。
1.2 一张分层架构图,把你和“只会用 Redis”的人区分开
分布式缓存系统从宏观上可以分成四层:
- 客户端层:SDK、连接池、路由算法、故障感知。
- 接入/代理层:处理协议解析、请求路由、灰度发布、限流。
- 缓存存储层:真正存数据的节点,每个节点可以是单机缓存引擎,也可以带副本。
- 治理/控制层:配置管理、监控告警、数据迁移、故障切换。
很多面试者上来就画一堆 Redis Circle,然后指着说“这就是分布式缓存”。但真正有经验的人会说,客户端 SDK 负责一致性哈希路由,代理层负责动态感知节点状态,存储层每个分片采用主从结构,主节点挂了从节点自动提升,控制面负责把路由配置推给客户端或代理。这一套完整链路讲完,面试官就知道你不只是在背八股文。
我自己实际做过一个日请求量几十亿的缓存平台,最后落地的架构就是“代理层 + 存储集群 + 配置中心”的模式。核心原因很简单:客户端直接访问存储节点看起来省了一层开销,但当你有几十个业务方接入时,客户端升级带来的沟通成本、故障排查成本高得惊人。代理层虽然增加了一跳网络开销,但换来的是统一管控和快速灰度,这笔买卖非常划算。
2. 数据分片与路由:缓存系统的地基
分片是分布式系统最核心的机制,没有之一。为什么要分片?因为单机容量和单机吞吐量都有上限。100 GB 数据放在一台机器上,内存不够;即使内存够了,单机处理 100 万 QPS 也不现实。分片就是把数据按照某种规则拆到多台机器上,让每台机器只承担一部分数据和一部分流量。
2.1 哈希取模和一致性哈希,到底怎么选
最简单的分片方式是hash(key) % N。这个方案实现简单,但有一个致命的缺点:当你把节点数从 N 扩容到 N+1 时,绝大部分 key 的映射关系都会发生变化。这意味着缓存全部失效,大量的请求会穿透到数据库,瞬间压力翻倍,这种场景我们一般叫“缓存雪崩”。
所以现实里我用得最多的是一致性哈希。它的核心思想是把哈希值空间组织成一个环,节点也映射到环上,每个 key 从它的哈希位置出发,顺时针找到第一个节点。这样新增或删除节点时,只影响这个节点附近一小段的数据,其他 key 的映射关系保持不变。
一致性哈希也有一个经典问题:节点数少的时候,hash 环上的节点分布不均,会出现数据倾斜。解决办法是给每个物理节点加上很多“虚拟节点”,让它们在环上均匀散开。虚拟节点数量一般建议 100~200 个,具体要看集群规模。比如一个物理节点有 150 个虚拟节点,集群有 10 台机器,那整个环上就有 1500 个虚拟节点,分布已经比较均匀了。
2.2 虚拟节点、数据迁移与扩容缩容的真实代价
面试官特别喜欢接着问:一致性哈希只是让“需要迁移的数据变少了”,但迁移过程具体怎么做?这里很多人的答案会含糊掉。我讲一个实际方案:
假设原来有 4 个节点,环上的 key 分布在 A、B、C、D 上。现在新增一个节点 E,E 的虚拟节点落到环上之后,只有它顺时针方向到前一个节点之间的 key 需要迁移。迁移不是一次性拷完,而是通过“双读双写”的方式平滑完成:先让 E 节点开始接收新写入的 key,同时后台任务把旧节点上属于 E 区间的数据拷贝到 E;拷贝过程中如果客户端查到 E 没有数据,就回源到旧节点,然后再异步回填到 E。等数据全部拷贝完,再把路由配置正式切到 E。
这里有一个很关键的细节:迁移期间数据不一致怎么办?如果业务对一致性要求不高,双读双写加异步回填就够了。如果要求比较高,那就需要引入版本号或者用消息队列保证更新顺序。这套扩展逻辑放到面试里说,面试官立刻知道你真的处理过线上扩容。
2.3 路由方式的选择:SDK 直连、Proxy 代理还是服务端跳转
分片方案定下来,接下来要考虑路由在哪一层做。常见的有三种:
- 客户端直连路由:SDK 里实现一致性哈希,客户端直接连对应节点。优点是性能最好、少一跳;缺点是 SDK 升级困难,Java、Go、Python 每个语言都要维护一套,出问题难以统一处理。
- 代理层路由:客户端只连 Proxy,由 Proxy 做哈希路由。优点是客户端极简,协议转换、限流、监控都可以在 Proxy 层统一做;缺点是增加一跳网络开销,Proxy 可能成为性能和可用性瓶颈。
- 服务端跳转:类似 Redis Cluster 的做法,客户端可以连接任意节点,如果数据不在当前节点,节点返回 MOVED 重定向。让客户端再次请求正确节点。这个方案兼顾了一部分灵活性和性能,但对客户端的协议栈要求比较高。
我自己的经验是:中小团队用客户端直连最省钱,但团队规模超过 20 人、业务方超过 5 个之后,Proxy 模式的优势会越来越明显。因为你能在 Proxy 上做所有策略的集中管控,而不是求着每个业务方升级 SDK。你也不用担心 Proxy 的性能,因为 Proxy 本身可以水平扩展,前面加一层负载均衡即可。
3. 缓存更新策略和一致性保障:这部分的坑最密集
很多架构师能把分片和高可用讲得头头是道,结果一聊到“缓存和数据库怎么保持一致”,就开始含糊了。这一块是分布式缓存系统里最容易出问题的地方,也是最值得花时间深挖的部分。
3.1 Cache Aside、Read Through、Write Back,各自的使用场景
先讲业界最常见的三种模式:
Cache Aside 旁路缓存。读的时候先读缓存,缓存没有就查数据库,然后把结果写回缓存;写的时候先更新数据库,然后删除缓存,或者更新缓存。这个模式最大的优点是实现简单,适合大多数业务场景。最大的坑是:如果先更新数据库再更新缓存,两个操作不是原子的,可能出现缓存里是旧值、数据库里是新值的不一致。所以工程上更推荐“更新数据库后删除缓存”,下一次读的时候再回填。这个方式也被称为 lazy loading。
Read Through 读穿透。缓存系统自己负责从数据库加载数据,业务方只和缓存交互。这个模式适合数据访问模式比较稳定、可以预热的场景。但实现起来更复杂,因为缓存引擎需要内置数据源接口。
Write Back 写回。所有写操作只写缓存,由后台异步批量刷到数据库。这个模式性能极好,适合写多读少、允许数据丢失的场景,比如计数、点赞、埋点。但缺点是万一缓存节点宕机,数据就永久丢了,所以使用门槛很高。
真实业务中最常用的就是 Cache Aside + 删除缓存。有一个很经典的问题:“到底是先删缓存,再更新数据库;还是先更新数据库,再删缓存?”正确答案在多数并发场景下是先更新数据库,再删除缓存。为什么?因为先删缓存、再更新数据库,会导致删完缓存后,还没更新数据库的间隙,另一个请求把旧数据读回缓存,数据库更新后缓存成了永远不一致的旧值。而先更新数据库,再删缓存,虽然删缓存失败的概率也存在,但通常可以用延迟双删或者订阅 binlog 来兜底。
3.2 缓存穿透、击穿、雪崩,一个表讲清楚
缓存设计面试中 90% 的追问都会围绕这三个问题展开。我用一个表格给你梳理清楚,然后在后面一步步说对策。
| 问题 | 表象 | 根本原因 | 典型对策 |
|---|---|---|---|
| 缓存穿透 | 大量请求查询不存在的 key,直接打到数据库 | 缓存无法命中不存在的 key | 布隆过滤器、空值缓存、参数校验 |
| 缓存击穿 | 某个热点 key 过期,大量并发请求同时打到数据库 | 单个热点 key 过期瞬间,没有缓存保护 | 互斥锁重建缓存、逻辑过期、热点 key 不过期 |
| 缓存雪崩 | 大批 key 同时过期,数据库压力骤增 | 大量 key 设成同一个过期时间 | 过期时间加随机值、多级缓存、熔断限流 |
缓存穿透最容易理解。用户不停请求一个 id 为-1或者不存在的商品,每次请求都穿透到数据库。最简单的办法是缓存这个 null 值,设置一个较短的过期时间(比如 5 分钟)。更好的方案是布隆过滤器,把所有存在的 key 先放到布隆过滤器里,请求来了先检查布隆过滤器,不存在直接返回,不再访问缓存和数据库。
缓存击穿最常见的修复方式是用互斥锁。在 key 过期的那一刻,只允许一个请求去数据库加载并重建缓存,其他请求先等待。实现上可以用 Redis 的SETNX,也可以用进程内锁。还有一个思路是“逻辑过期”:不给 key 设物理过期时间,而是在 value 里存一个逻辑过期时间戳;读取时发现逻辑过期后,异步去刷新缓存,同时返回旧值。这个方案在秒杀场景特别实用,可以避免瞬时锁等待。
缓存雪崩的核心修复是“过期时间的随机化”。把过期时间从固定值改成TTL + random(0, 300)秒,让同一批 key 不集中在同一时刻过期。另外可以做多级缓存:本地缓存作为一级缓存,Redis 作为二级缓存,即使 Redis 里大量 key 过期,本地缓存仍然能挡住相当一部分请求。
3.3 多副本数据一致性,别想着强一致
分布式缓存的多个副本之间,以及缓存系统和数据库之间,如果要做到强一致,代价非常大。比如你得引入 Paxos/Raft 这样的共识协议,每次写入都要多数派确认,延迟会明显增加,吞吐量也会下降。而缓存这种场景,绝大多数业务其实是可以容忍短时间不一致的。
所以在设计阶段,我的建议是给缓存和副本之间定义清楚“最终一致”的容忍窗口。比如商品库存、交易金额这种数据不允许缓存不一致太久,那你可以采用“更新数据库后立即删缓存 + 订阅数据库 binlog 异步重试删缓存”的兜底方案;如果是用户头像、文章浏览量这种数据,就算缓存里旧个几秒钟,业务上也没人感知,那异步刷新就足够了。
这里有个非常重要的细节:不要为了追求一致性,把事务和分布式事务引到缓存系统里来。缓存系统不是数据库,它不承诺事务性。如果你发现自己正在设计一个需要跨节点强一致提交的缓存接口,那你大概率是把需求搞错了,应该重新思考业务架构。
4. 高可用架构:节点宕机之后,缓存系统还能撑住吗
聊完数据一致性,接下来是可用性设计。分布式缓存系统的高可用,需要回答三个问题:节点故障怎么感知?数据副本怎么切换?整体流量怎么防护?
4.1 副本机制与自动故障转移
单机缓存挂了,如果后面直接是数据库,流量冲击会非常大。所以常规做法是每个分片配一个主节点和至少一个从节点,主节点负责读写,从节点负责备份。主节点宕机后,从节点自动升级为新的主节点。
这里的关键是“自动升级”如何实现。很多团队直接把 Redis Sentinel 或 Redis Cluster 的故障转移机制拿过来用,确实是省事的选择。但如果要自己实现这套机制,那必须有一个分布式协调组件负责心跳检测、选主和配置通知。比如用 etcd/zookeeper,每个节点向协调中心注册并上报心跳,协调中心发现主节点心跳超时后,在从节点中发起选主,然后更新路由配置。
有一个容易被忽略的细节:故障转移时,已经不完整的数据可能会丢一部分。如果主从复制是异步的,主节点宕机前,有一部分最新写入还没同步到从节点,从节点提升为主节点后,这部分数据就丢了。严格来说,这是可用性和一致性之间的权衡。如果你希望数据不丢,就得用同步复制或者半同步复制,但这会拖慢写入延迟。所以要在设计文档里明确跟你团队说清楚:缓存系统重启或故障可能丢失最近的少量数据,这是可接受范围。
4.2 多机房部署与容灾切换
当缓存系统要支撑核心业务时,单机房是不够的。我参与的缓存平台采用的是“同城主备 + 异地只读”的部署方式。主机房承担读写流量,备机房保持热备,数据通过异步通道同步;如果主机房整体故障,把流量切到备机房。这个过程中数据可能会落后一小段时间,所以需要业务侧接受“秒级延迟”。
多机房间的数据同步有几种方式:基于 binlog 同步、基于消息队列同步、或者直接在缓存引擎上开启主从复制。具体选哪种,取决于你允许的同步延迟和运维复杂度。但有一个原则是不变的:控制面要做全局路由切换,而不是让客户端自动探测机房。因为客户端自动探测很容易出现“脑裂”,两个机房都以为自己应该是主,写冲突很难收拾。
4.3 优雅降级、熔断和限流:保护数据库的最后防线
缓存系统无论设计得多健壮,也要考虑最坏情况。当缓存大面积不可用时,系统不能直接把所有请求透传到数据库。所以设计里必须包含降级开关。正常情况下我们给缓存配了很高的 QPS,但数据库能承受的 QPS 是有限的,比如只能扛 1 万,缓存挂掉后端瞬间来了 50 万 QPS,数据库 5 秒钟就会被打挂。
降级方案一般有三层:
- 本地缓存兜底:Java 进程里用 Caffeine/Guava 做一个小的本地缓存,作为分布式缓存的“影子部队”。分布式缓存挂了,本地缓存还能挡住 80% 的读请求。
- 接口级熔断:当分布式缓存的错误率超过阈值(比如 30%),SDK 自动熔断一段时间,不再请求缓存,直接走数据库,但只允许一小部分请求通过,避免数据库被打挂。
- 最小化降级:对非核心接口直接返回默认值,比如推荐流、热门榜单这种,直接返回空页或旧页面,等缓存恢复后再补全。
这些兜底策略要在设计文档里写清楚,尤其是熔断阈值和恢复策略。很多人只做熔断不做恢复,结果缓存恢复正常了,SDK 里还一直熔断,业务受损时间被白白拉长。正确做法是在熔断后引入半开状态:放少量请求试探,如果成功率达到预期,就把熔断器关闭。
5. 监控、容量规划和日常运维:设计文档里最容易漏的部分
面试官如果只考到“高可用”,那还只是一个中级系统设计的水平。真正拉开差距的,是你有没有考虑到监控和运维。一个设计再完美的分布式缓存系统,如果不做监控、不做容量规划、不治理大 key 和热 key,上线半年后一定是一堆事故等着你。
5.1 监控指标:不能只看命中率
很多团队的缓存监控只盯着命中率,确实命中率是最直观的指标,但远远不够。我建议至少要监控以下四类:
- 性能指标:平均延迟、p99 延迟、p999 延迟、单节点 QPS、网络带宽。
- 容量指标:内存使用率、key 数量、大 key 数量、内存碎片率。
- 错误指标:超时率、异常次数、连接拒绝数、主从复制延迟。
- 业务指标:命中率、热点 key 访问分布、未命中后数据库回源量。
这里我想重点强调一下“回源 QPS”这个指标。很多系统命中率看起来很高,99% 都是缓存命中的,但剩下的 1% 如果是一万个 key 同时过期,瞬间回源的 QPS 也可能把数据库打爆。所以监控里不但要统计回源总量,还要统计回源 QPS 的瞬时峰值,以及回源的 TOP key。
5.2 大 Key 和热 Key 是缓存系统的两大杀手
大 key指的是单个 key 对应的 value 特别大,比如一个 key 里塞了一个几 MB 的 JSON 列表。大 key 的危害在于:网络传输耗时高、单次请求占用内存多、数据迁移时容易阻塞线程。治理方式是从编码上拆分成多个小 key,或者改用 Hash 结构。如果实在拆不了,可以把大 value 压缩后再存,并设计好序列化协议。
热 key指的是某一个 key 在短时间内被超高并发访问,比如双十一的爆款商品 key。大量请求打到一个分片上,导致单个 Redis 节点的 CPU 达到瓶颈,就算你做了分片也解决不了,因为热点 key 永远只会落在其中一个分片。常见的解法是:本地缓存 + 热点 key 识别 + 多副本冗余。比如把热点 key 复制成key#1、key#2、key#3多个副本,分散到不同分片上,客户端随机选一个副本读。这个方法会带来一致性问题,所以一般只对允许短时间不一致的读多写少场景使用。
5.3 容量规划:别等内存满了才想起来换配置
我见过很多线上事故都是内存打满引发的。缓存系统不像数据库那样有完善的磁盘容量管理,Redis 默认就是“全内存”。如果不做内存上限控制,某些业务方一条大 key 就可能把整台机器内存耗尽。所以在容量规划上,有几个点需要提前定好:
- 单机内存上限:比如 Redis 的
maxmemory必须设置,不能是无限大。 - 淘汰策略:内存满时用
allkeys-lru、volatile-lru还是allkeys-random,要提前想清楚。一般业务场景用 LRU 就够了,如果你的 key 基本都会设置过期时间,用volatile-lru更合适。 - 数据增量预估:根据业务增长速度,定期评估未来 3 个月、6 个月的容量。比如当前数据量 200 GB,每月增长 20%,那半年后就到了 440 GB,是扩容还是优化数据结构,要提前规划。
5.4 连接数与内存碎片,细节里藏着事故
还有一个容易踩坑的地方是连接数。不管是 Redis 还是自研缓存引擎,单机连接数都是有上限的。当客户端连接池配置不合理时,高峰期可能出现大量连接超时。我通常建议客户端连接池大小设置为(业务单机 QPS / 单连接承载 QPS) * 节点数,还要留出 20% 冗余。
内存碎片也是一个常被忽略的点。Redis 等内存型存储频繁增删 key 后,内存碎片率高的时候,可用内存看起来还有,但实际可能分配不出连续内存。Redis 4.0 以上支持自动碎片整理,但还是要有监控,碎片率超过 1.5 时就需要人工介入整理或者重启节点。
6. 从拿到题目到讲完答案,一套可直接套用的面试框架
这一节当作整套设计思路的“参考答案”来用。我按照系统设计面试的 30 分钟节奏来划分,你拿去就能练。
6.1 30分钟答题节奏与提纲
| 时间段 | 做什么 | 你要说的重点 |
|---|---|---|
| 0-3 分钟 | 澄清需求和指标 | 明确数据量、QPS、可用性、一致性、延迟要求 |
| 3-8 分钟 | 给出整体架构 | 客户端 + 代理 + 存储分片 + 控制面四层结构 |
| 8-15 分钟 | 深入数据分片和路由 | 一致性哈希、虚拟节点、扩容迁移、路由方式对比 |
| 15-22 分钟 | 深入一致性和缓存策略 | Cache Aside、过期策略、穿透/击穿/雪崩解决 |
| 22-27 分钟 | 深入高可用和容灾 | 主从切换、多机房、熔断降级、数据同步 |
| 27-30 分钟 | 总结和补充 | 监控指标、容量规划、灰度发布、大 key/热 key 治理 |
这套节奏的核心是:把主动权握在自己手里,不要等面试官逐点追问。每讲到一层,顺手把下一层的引子抛出去,比如讲一致性哈希时,主动提一句“扩容的时候我用虚拟节点来做数据迁移,后面可以展开细讲”,面试官大概率会顺着你引导的方向提问。
6.2 高频追问与应对思路
问:“如果缓存和数据库数据不一致,怎么解决?”
答:先分清是“缓存与数据库不一致”还是“缓存多副本不一致”。前者用 Cache Aside + 删除缓存 + binlog 兜底;后者用版本号或让多副本从同一个数据源同步。关键是明确容忍窗口,不要为了强一致牺牲性能。
问:“一致性哈希能完全避免数据迁移吗?”
答:不能。一致性哈希减少的是迁移范围,但迁移过程依然存在。实际方案是双读双写、后台迁移、逐步切流。
问:“这个系统能支持千万 QPS 吗?”
答:能,但要看数据热点分布和资源预算。先横向分片解决容量和单点 QPS,再用本地缓存解决热 key,最后用多机房就近读取解决跨地域延迟。如果千万 QPS 同时集中在一个 key 上,那要先解决业务热点,而不是单纯加机器。
问:“缓存抖动/超时怎么排查?”
答:先看监控里是单节点抖动还是全局抖动。单节点看大 key、热 key、内存碎片、fork 持久化阻塞;全局看网络、连接池、代理层瓶颈和数据迁移。我习惯从“先定位是不是单点问题,再看是不是链路问题”的方向排查。
6.3 面试答题中的三个“加分项”
第一个加分项是说清楚“缓存不是数据库的遮羞布”。很多人把缓存设计成数据库的高可用挡箭牌,一旦缓存挂了,数据库就暴露在流量洪峰里。但真正好的设计是“数据库即使被大量流量打到,也应该有能力降级和自我保护”。你在设计缓存时应该顺带设计数据库限流和降级策略。
第二个加分项是主动聊“成本”。分布式缓存的成本有三个:机器成本、运维成本、一致性成本。你可以说,如果数据量不大,我会先用单机缓存 + 本地缓存,不引入分片;如果业务线多了,我会优先选 Proxy 模式降低业务接入成本。这样面试官会觉得你不是只会堆技术组件,而是会算账。
第三个加分项是拿真实事故来说话。比如你在讲热 key 治理的时候,抛出一个具体案例:“之前大促的时候出现过用户中心的一个 uid key 被恶意刷量,单分片 CPU 被打到 95%,最后通过本地缓存 + 热点副本解决了。”真实案例永远比理论描述更有说服力。
7. 写在最后的一点私货
说完这么多理论,最后分享一个我踩过很多次坑后才明白的道理:分布式缓存系统设计的真正难点,不在于某一个技术细节,而在于所有细节之间的相互制约。一致性哈希做好了,扩容简单了,但热 key 仍然没办法只靠分片解决;主从复制做好了,可用性提升了,但数据可能短时间丢失;本地缓存加多了,延迟降下来了,但数据不一致的概率又上去了。
每次做完一个设计,我都会问自己一个问题:如果缓存系统突然全部宕机 10 分钟,我的业务会怎样?如果这个问题的答案是“数据库会被打死”,那说明这个设计里缺少降级和兜底;如果答案是“用户无感知”,那说明冗余做得到位,但成本可能偏高。这个问题的答案没有对错,它只取决于你们业务对可用性的真实要求。
在实际动手之前,我建议你先拿一张纸把自己的核心场景写下来:预估容量、QPS、一致性要求、可用性要求、运维团队规模。想清楚这个前提,再回头看我前面讲的分片、共识、一致性、高可用,你会发现每一步都变成了必然的选择。分布式缓存不是一套模板走天下,它是一道“根据需求推导架构”的题,而推导的过程,就是你和普通使用者之间最大的区别。