开篇介绍:
hello 大家,随着我们一个个主线以及一个个支线课程的完成,我们接下来也要进入一个很关键的支线课程了,那就是 Redis!相信大家心里一定藏着不少疑问:Redis 到底是什么?它能解决什么实际问题?我们为什么非要学它不可?
你有没有想过,为什么双十一购物节时,几万人同时抢一件爆款商品,页面却能秒加载、不卡顿?为什么刷短视频时,每秒推送几十条内容,却依然流畅无延迟?为什么支付账单时,哪怕同时有几十万人转账,资金数据也不会出错?这背后,Redis 和分布式系统就是支撑这些高并发场景的 "核心推手"。
哈哈,大家且看下文!
引言:为什么分布式系统是高并发业务的 "必答题"?
在互联网业务从 "小作坊" 走向 "规模化" 的过程中,"高并发、高可用、海量数据" 是绕不开的三座大山。比如电商平台的 618 秒杀,一秒内数万用户同时点击 "下单" 按钮;外卖平台的午高峰,每分钟几十万笔订单生成,骑手实时接单、商家实时接单;社交平台的热点事件,比如明星官宣、体育赛事夺冠,瞬间数百万用户涌入评论区,每秒产生上万条评论。
这些场景下,单台服务器就像 "一个人干所有活"------ 既要接待顾客、介绍商品,又要拿货、记账,根本扛不住这么大的压力,必然会出现 "卡顿、崩溃、数据错误"。而分布式系统,就是把 "一个人的活分给一群人干",通过多台服务器协作,突破单机性能瓶颈,实现 "再多用户访问也不卡、系统不宕机、数据不出错" 的目标,是高并发业务的 "必答题",而 Redis,就是分布式系统中最关键的 "性能加速器"。
第一部分:Redis 核心认知
Redis 是基于键值对的 NoSQL 数据库,看似简单,却能解决分布式系统中的多个核心问题,核心价值有三点:
1.1 极致性能:内存存储,速度碾压磁盘数据库
Redis 最核心的特点是 "所有数据都存储在内存中",而内存的读写速度是磁盘的上千倍 ------ 内存读写速度约 100 纳秒 / 次(1 纳秒 = 10⁻⁹ 秒),磁盘读写速度约 10 毫秒 / 次(1 毫秒 = 10⁻³ 秒),两者相差 10 万倍!
官方测试数据显示,Redis 的读吞吐量可达 110000 次 / 秒,写吞吐量可达 81000 次 / 秒 ------ 相当于 1 秒内可以处理十几万次请求。而传统磁盘数据库(比如 MySQL)的读写吞吐量通常只有几千次 / 秒,根本无法应对高并发场景。
举个例子:电商平台的爆款商品详情页,每秒有 1 万用户访问,如果用 MySQL 直接查询,数据库瞬间就会崩溃;但如果用 Redis 缓存商品详情,1 秒内 1 万次请求都能被 Redis 轻松处理,响应时间仅需 0.1 秒,用户几乎感觉不到延迟。
一、Redis 核心定义与核心优势
Redis 是一种基于键值对(key-value) 的 NoSQL 数据库,与传统键值对数据库相比,其核心优势在于丰富的数据结构支持与极致性能,堪称数据库领域的 "瑞士军刀"。
- 多样化数据结构,适配多场景需求
Redis 的值支持多种数据结构与算法,覆盖绝大多数业务场景:
- 基础数据结构:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)
- 特色数据结构:Bitmaps(位图)、HyperLogLog(基数统计)、GEO(地理信息定位)
- 极致读写性能,依托内存存储
Redis 将所有数据存储在内存中,规避了磁盘 IO 的性能瓶颈,读写速度极为惊人 ------ 远超传统磁盘数据库,能轻松支撑高并发场景下的高频访问。
- 数据持久化,保障数据安全
为解决内存数据易丢失的问题,Redis 提供两种持久化机制,可在断电或机器故障时保护数据:
- 快照模式(RDB):定期将内存全量数据生成快照保存到硬盘;
- 日志模式(AOF):将每一条写命令以日志形式追加到硬盘文件,重启时通过重放命令恢复数据。
- 丰富附加功能,拓展使用边界
除核心存储功能外,Redis 还内置多种实用功能:
- 键过期:支持为键设置过期时间,自动清理无效数据;
- 发布订阅:实现简单的消息通信模式,支持多对多消息广播;
- 事务:批量执行命令,保证执行过程不被中断;
- 流水线(Pipeline):批量发送命令,减少网络往返开销;
- Lua 脚本:支持自定义脚本,实现复杂原子操作。
二、Redis 的起源与发展
Redis 的诞生源于一次 "需求倒逼" 与 "资源限制" 的双重驱动:
- 2008 年,意大利程序员 Salvatore Sanfilippo 开发日志收集网站 LLOOGG 时,需要一个高性能队列功能;
- 初期使用 MySQL 实现,但无论如何优化 SQL 语句,性能仍无法满足需求,且受限于资金不足,无法购买高性能服务器;
- 为解决自身需求,Salvatore 自主开发了专属于 LLOOGG 的数据库原型,这便是 Redis 的前身;
- 后续,他将 Redis 1.0 源码发布到 GitHub,意外获得开源社区的广泛认可,逐步发展为全球主流的 NoSQL 数据库。
三、Redis 的行业应用与生态价值
如今,Redis 已成为全球最受欢迎的数据库之一,其应用覆盖互联网巨头、开源生态等多个领域:
- 重量级企业用户
- 国外:Twitter、Instagram、Stack Overflow、GitHub 等;
- 国内:新浪微博(全球最大 Redis 使用者)、阿里巴巴、腾讯、搜狐、优酷土豆、美团、小米、唯品会等。
- 开源生态核心组件
许多主流开源技术已将 Redis 纳入核心架构,例如 ELK 日志分析系统,Redis 为其提供缓存与数据暂存支持。
- 可扩展的生态体系
Redis 提供模块系统,支持第三方开发者实现功能扩展,进一步拓宽其应用场景,释放更大技术价值。
- 技术人必备技能
凭借广泛的应用场景与核心功能,熟练使用和运维 Redis,已成为现代开发、运维人员的必备职业技能
分布式缓存核心:拦截 80% 读请求,给数据库 "减负"
在分布式系统中,Redis 最核心的作用是 "分布式缓存"------ 把高频访问的 "热数据"(比如爆款商品详情、用户登录信息)存到 Redis 中,用户请求先查 Redis,命中后直接返回,不用访问数据库。
据统计,电商系统中 80% 的请求都是读请求(查商品、查订单、查库存),且 80% 的读请求都集中在 20% 的热数据上。用 Redis 拦截这些请求后,数据库的读压力会减少 80% 以上,从 "每秒 1 万次请求" 降到 "每秒 2000 次请求",数据库再也不会因为高并发而崩溃。
举个例子:某电商平台的爆款手机,每秒有 8000 次查询请求,用 Redis 缓存后,7900 次请求从 Redis 返回,仅 100 次请求查数据库,数据库 CPU 使用率从 100% 降到 10%,响应时间从 5 秒缩短到 0.5 秒。
第二部分:分布式系统核心概念
在聊架构演进前,先把 "地基" 打牢 ------ 很多人觉得分布式系统难,其实是被专业术语绕晕了。下面用生活中的 "饭店场景" 类比
2.1 基础概念:一张表看懂所有术语
| 技术概念 | 生活类比(饭店场景) | 通俗解释 | 电商系统实战例子 |
|---|---|---|---|
| 应用 / 系统 | 整个饭店(含前厅、后厨、收银、采购) | 为完成某类核心服务的所有程序集合,相当于 "一个完整的团队" | 电商系统(含用户、商品、订单、支付等所有模块) |
| 模块 / 组件 | 饭店的前厅、后厨、收银台 | 应用复杂时,按 "职责" 拆分的独立部分,相当于 "团队中的小组" | 电商系统的 "用户模块""商品模块""订单模块" |
| 分布式 | 饭店的前厅在 1 楼、后厨在 2 楼、采购部在隔壁楼,通过对讲机 / 电梯配合 | 系统的不同模块部署在不同服务器,通过网络通信协作,核心是 "物理上分开,逻辑上一体" | 用户模块部署在上海服务器,商品模块部署在广州服务器,订单模块部署在北京服务器,通过网络协同工作 |
| 集群 | 饭店的多个收银台(都做 "收钱" 这件事) | 多台服务器部署同一类组件,共同完成一个目标,相当于 "多个小组干同一件活" | 3 台 Nginx 服务器组成负载均衡集群,10 台 Redis 服务器组成缓存集群 |
| 主(Master)/ 从(Slave) | 饭店的主收银台(能收款、改价)、副收银台(只能查账、打小票) | 集群中,主节点承担核心职责(如数据写入),从节点做辅助(如数据读取、备份),从节点数据从主节点同步 | MySQL 主从集群:主库负责写操作(下单、改库存),3 个从库负责读操作(查商品、查订单) |
| 中间件 | 饭店的传菜员(连接后厨和前厅) | 不同模块 / 数据库之间的 "桥梁",负责数据传递和协调 | 负载均衡(连接用户和应用服务器)、数据库中间件(连接应用和数据库)、消息队列(连接不同微服务) |
2.2 分布式系统的 "体检指标":怎么判断系统好不好?
评价分布式系统的核心指标,就像判断一家饭店好不好一样,有明确的标准
2.2.1 可用性(Availability):系统 "不宕机" 的概率
- 定义:单位时间内,系统能正常提供服务的比例,常用 "几个 9" 来表示(数字越多,可用性越高)。
- 通俗计算 :一年有 365 天 = 8760 小时 = 525600 分钟,不同 "9" 对应的允许宕机时间:
- 2 个 9(99%):允许一年宕机 8760×1% = 87.6 小时(约 3.6 天)------ 适合个人博客、小网站;
- 3 个 9(99.9%):允许一年宕机 8.76 小时(约 526 分钟)------ 适合中小型企业网站;
- 4 个 9(99.99%):允许一年宕机 0.876 小时 = 52.56 分钟 ------ 电商核心系统的最低要求(比如 618 期间,最多只能宕机 52 分钟);
- 5 个 9(99.999%):允许一年宕机 5.26 分钟 ------ 金融、支付系统的要求(比如银行转账系统,一年只能宕机 5 分钟)。
- 生活例子:饭店的可用性 = 营业时长 / 一年总时长,99.99% 的可用性意味着饭店一年只能关门 52 分钟 ------ 哪怕设备坏了,也要连夜抢修,不能影响第二天营业。
- 实战意义:系统可用性直接影响用户体验和业务收入。比如某电商平台可用性 99.9%,一年宕机 8.76 小时,按日均收入 1 亿元计算,会损失约 365 万元收入。
2.2.2 响应时长(Response Time RT):用户 "等多久"
- 定义:从用户发起请求(比如点击 "查看商品")到系统给出反馈(商品页面加载完成)的时间。
- 核心指标(三个维度,缺一不可) :
- 最长响应时长(P99):最慢的 1% 用户要等多久(比如 1% 的用户加载商品用了 5 秒,这部分用户体验极差);
- 平均响应时长:所有用户的平均等待时间(比如平均 1 秒,只能反映整体水平);
- 中位数响应时长(P50):50% 的用户等待时间(比如中位数 0.8 秒,更能反映大多数用户的真实体验)。
- 用户体验阈值 :
- 0.1 秒:用户感觉 "瞬间加载",体验最好;
- 1 秒:用户感觉 "流畅",可以接受;
- 3 秒:用户开始 "不耐烦",可能会关闭页面;
- 5 秒:大部分用户会 "放弃等待",直接离开。
- 生活例子:顾客点完菜到上菜的时间 ------ 好的饭店中位数时长不超过 10 分钟(大多数顾客能接受),最长不超过 20 分钟(不会让少数顾客等太久)。
2.2.3 吞吐(Throughput)vs 并发(Concurrent):系统 "能接多少客"
这两个指标是分布式系统的 "核心能力体现",最容易混淆 ------ 用 "高速公路" 类比:
| 指标 | 高速公路类比 | 系统中的定义 | 电商实战例子 |
|---|---|---|---|
| 吞吐 | 1 分钟内通过的车辆总数(比如 20 辆) | 单位时间内系统成功处理的请求数 | 1 分钟处理 2000 笔订单,1 秒处理 1000 次商品查询 |
| 并发 | 同一时刻在路上的车辆数(比如单车道最多 2 辆) | 系统同一时刻能支撑的最大请求数 | 同一时刻有 200 个用户在下单,1000 个用户在查商品 |
- 实战技巧:并发量很难直接统计,通常用 "1 秒的吞吐量" 近似替代(比如 1 秒处理 1000 次请求,可认为并发量约 1000)。
- 生活例子:饭店的吞吐 = 1 小时接待 100 桌客人(单位时间处理能力),并发 = 同一时刻店内有 20 桌客人在就餐(同一时刻承载能力)。
第三部分:分布式系统架构演进之路
我们以 "电商系统" 为例,从 "日活 1000" 的小网站,一步步演进到 "日活千万" 的大型平台
阶段 1:单机架构 ------ 小作坊式运作(日活≤1000,并发≤100 / 秒)
3.1.1 演进背景
系统刚上线,团队只有 2-3 个程序员,核心目标是 "快速把业务做出来,验证市场"。用户量少,每天只有几百人访问,单台服务器就能搞定所有工作,不用复杂架构。
3.1.2 架构详情(用 "小区小超市" 类比)
就像小区里的小超市:老板(应用服务)和仓库(数据库)都在同一个房间,顾客(用户)进门后,老板既负责接待、介绍商品,又负责从仓库拿货、记账 ------ 所有工作都在一个 "房间"(单机服务器)里完成,没有分工。
具体流程(一步一步拆解):
- 用户在浏览器输入
www.bit.com(电商网站域名); - DNS 服务器把域名解析成服务器 IP(比如 10.102.41.1)------ 相当于顾客通过 "超市地址" 找到超市;
- 浏览器访问这个 IP,请求直达单机服务器 ------ 顾客走进超市;
- 服务器上的应用服务(比如 Tomcat)处理请求:查本地的数据库(比如 MySQL),获取商品 / 用户 / 订单数据 ------ 老板接待顾客,从仓库拿货、查账本;
- 应用服务把数据组装成网页(比如商品列表页),返回给用户 ------ 老板把商品递给顾客,完成交易。
架构图:
用户 → DNS解析 → 单机服务器(应用服务+数据库服务)
↓
本地数据库(用户表+商品表+交易表)

3.1.3 用到的技术 & 服务器配置
- Web 服务器 / 应用容器:Tomcat、Apache(相当于小超市的 "接待台");
- 数据库:MySQL(相当于小超市的 "记账本 + 仓库");
- 服务器配置(参考):4 核 8G 内存 + 500G 机械硬盘(普通台式机配置,成本低)。
3.1.4 优点 & 缺点(对比清晰)
| 优点 | 缺点 |
|---|---|
| 架构最简单:不用考虑分布式、集群,开发速度快,1-2 周就能上线 | 性能瓶颈明显:CPU、内存、磁盘 IO 共用一台服务器,一个资源占满,整个系统就卡壳 |
| 部署 / 运维成本极低:只需要一台服务器,程序员自己就能部署、维护,不用专业运维 | 可用性差:服务器死机(比如断电、硬件故障),整个网站就挂了,用户无法访问 |
| 开发效率高:改代码后直接重启服务器,不用协调多台机器 | 无扩展空间:硬件升级到顶后(比如 8 核 16G),无法承接更多用户,只能重构架构 |
3.1.5 实际问题(用户量增长后,痛点暴露)
当日活涨到 1000,并发到 100 / 秒时,问题会集中爆发:
- CPU 占满:应用服务处理请求 + 数据库计算,CPU 使用率长期 100%------ 用户点击商品后,浏览器转圈 3 秒以上,甚至显示 "无法访问";
- 磁盘 IO 高:数据库频繁读写机械硬盘,查询商品要等 2-3 秒 ------ 顾客问 "这个商品多少钱",老板翻半天账本才回答;
- 内存不够:商品数据和用户数据都存在服务器内存,内存溢出导致服务器崩溃 ------ 超市货架太小,商品堆不下,老板只能暂停营业。
阶段 2:应用数据分离架构 ------ 拆分 "老板和仓库"(日活≤1 万,并发≤500 / 秒)
3.2.1 演进背景
系统验证成功,有了一批忠实用户,日活涨到 1 万,单机服务器的 CPU 和磁盘 IO 互相抢资源(应用服务占 CPU,数据库占 IO),性能越来越差。但团队预算有限,不能大规模升级架构,只能做 "最小改动"------ 把应用和数据库分开部署,资源隔离。
3.2.2 架构详情(用 "稍大的超市" 类比)
就像把超市的 "仓库" 搬到隔壁房间:老板(应用服务)还在原房间接待顾客,仓库(数据库)在隔壁,老板需要货时,喊一声(网络通信)就能拿到 ------ 核心是 "应用和数据库分开,各自用独立的服务器,资源不抢用"。
具体流程(对比单机架构,只变部署,不变逻辑):
- 用户请求仍先到应用服务器(IP:10.102.41.1)------ 顾客走进超市,找到老板;
- 应用服务不再查本地数据库,而是通过网络访问独立的数据库服务器(IP:10.102.41.2)------ 老板喊隔壁仓库管理员拿货、查账本;
- 数据库服务器处理查询 / 写入请求,把结果返回给应用服务 ------ 仓库管理员找到商品、查完账本,告诉老板;
- 应用服务组装数据,返回给用户 ------ 老板把商品递给顾客。
架构图:
用户 → DNS解析 → 应用服务器(10.102.41.1)→ 网络 → 数据库服务器(10.102.41.2)
↓
数据库(用户表+商品表+交易表)

3.2.3 关键改进 & 服务器配置
- 关键改进(核心逻辑) :
- 应用服务器配高 CPU(侧重处理大量请求计算):比如 8 核 16G 内存 ------ 老板手脚麻利,能快速接待顾客;
- 数据库服务器配高内存 + SSD 硬盘(侧重快速读写数据):比如 4 核 32G 内存 + 1TB SSD------ 仓库管理员有大货架(高内存)和快速查找工具(SSD),能快速找到商品。
- 资源隔离:应用服务器死机,重启后不影响数据库数据;数据库升级硬件,不影响应用服务运行 ------ 老板生病请假,仓库正常备货;仓库整理货架,老板正常接待顾客。
- 用到的技术:和单机架构一致,只是部署在两台服务器(不用改代码,成本最低)。
3.2.4 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 成本低:仅增加一台服务器,无需改代码,程序员能快速完成部署 | 应用服务器仍为单点:应用服务器崩了,所有用户请求都无法处理 ------ 老板请假,超市就关门了 |
| 性能提升明显:并发能到 500 / 秒,响应时长从 3 秒缩短到 1 秒内 ------ 顾客不用长时间等待 | 数据库仍为单点:数据库崩了,所有读写都停 ------ 仓库着火,超市无法拿货、记账 |
| 运维简单:两台服务器,程序员还能兼顾维护,不用请专业运维 | 应用服务器无法扩展:用户再涨(比如日活 10 万),单台应用服务器扛不住 ------ 老板一个人接待不了 100 个顾客 |
3.2.5 实际问题(用户量再增长)
当日活涨到 10 万,并发到 1000 / 秒时,应用服务器的 CPU 又占满了 ------ 用户点击商品后,页面加载 3 秒以上,甚至出现 "连接超时";高峰期(比如晚上 8 点),应用服务器直接崩溃,用户无法访问。
阶段 3:应用服务集群架构 ------ 招 "多个服务员"(日活≤10 万,并发≤5000 / 秒)
3.3.1 演进背景
系统成了 "网红小店",单台应用服务器(一个服务员)忙不过来,顾客排队太久。此时有两种扩展方案,团队需要二选一:
| 扩展方案 | 类比(饭店场景) | 优点 | 缺点 |
|---|---|---|---|
| 垂直扩展(Scale Up) | 给服务员换 "更快的手脚"(比如请奥运冠军当服务员) | 无需改代码,直接换高配服务器,简单粗暴 | 成本高(性能 2 倍 → 价格 4 倍以上);有硬件上限(再快的人也接待不了 1000 个顾客) |
| 水平扩展(Scale Out) | 多招几个服务员(3 个普通服务员),再找个 "迎宾员" 分配顾客 | 成本低(普通服务员比奥运冠军便宜);无限扩容(顾客再多,继续加服务员) | 需引入负载均衡(迎宾员),增加系统复杂性;需要解决 "服务员之间的协作问题" |
最终选 水平扩展------ 因为垂直扩展有上限,且价格太贵,水平扩展更适合长期发展。
3.3.2 架构详情(用 "连锁饭店" 类比)
就像连锁饭店:招了 3 个服务员(多台应用服务器),门口站一个迎宾员(负载均衡),顾客进门后,迎宾员把顾客分到不同服务员手里 ------ 核心是 "多服务员干活,迎宾员分配任务,提高接待能力"。
具体流程:
- 用户请求先到 "迎宾员"(负载均衡,比如 Nginx)------ 顾客走进饭店,先找迎宾员;
- 负载均衡按算法把请求分给不同的应用服务器(比如服务器 A、B、C)------ 迎宾员把顾客分到不同服务员;
- 所有应用服务器都通过网络访问同一个数据库服务器 ------ 所有服务员都从同一个仓库拿货、查账本;
- 应用服务器处理完请求,返回结果给用户 ------ 服务员接待完顾客,顾客离店。
架构图:
用户 → DNS解析 → 负载均衡(Nginx)
↓ ↓ ↓
应用服务器A 应用服务器B 应用服务器C
↓ ↓ ↓
数据库服务器

3.3.3 核心:负载均衡算法(迎宾员的 "分配规则")
负载均衡的核心是 "公平、高效地分配请求",三种最常用的算法,用 "分顾客" 的实际例子讲透:
- Round-Robin(轮询):绝对公平
- 规则:依次分配,不偏不倚 ------ 用户 1→服务器 A,用户 2→服务器 B,用户 3→服务器 C,用户 4→服务器 A,循环往复;
- 优点:实现简单,绝对公平,所有服务器压力均匀;
- 场景:所有应用服务器配置相同(比如都是 8 核 16G);
- 实际例子:3 台应用服务器,10 个用户请求的分配结果:1→A、2→B、3→C、4→A、5→B、6→C、7→A、8→B、9→C、10→A。
- Weight-Round-Robin(加权轮询):能者多劳
- 规则:给高配服务器加 "权重",权重越高,接的请求越多 ------ 比如服务器 A 配置高(8 核 32G,权重 2),服务器 B、C 配置低(8 核 16G,权重 1),则 A 接 2 个请求,B、C 各接 1 个;
- 优点:充分利用硬件资源,高配服务器多干活,避免资源浪费;
- 场景:应用服务器配置不同(比如有的是新服务器,有的是旧服务器);
- 实际例子:3 台服务器(A 权重 2,B、C 权重 1),10 个用户请求的分配结果:1→A、2→A、3→B、4→C、5→A、6→A、7→B、8→C、9→A、10→A。
- 一致哈希散列:用户粘性
- 规则:按用户特征(比如 IP 地址)算一个 "唯一编号",同一个用户的所有请求都分给同一个服务器 ------ 比如 IP 为 192.168.1.1 的用户,永远分给服务器 A;
- 优点:用户的购物车、登录状态不会丢失 ------ 比如用户在服务器 A 加入购物车,下次请求到服务器 A,仍能看到购物车商品,不用重新登录;
- 场景:需要 "用户粘性" 的业务(比如专项客服、会员中心、购物车);
- 实际例子:用户 A(IP:192.168.1.1)的所有请求→服务器 A,用户 B(IP:192.168.1.2)的所有请求→服务器 B,无论访问多少次,分配规则不变。
3.3.4 用到的技术 & 服务器配置
- 负载均衡:Nginx(软件,免费开源,中小公司首选)、HAProxy(软件,更专业,支持更多算法)、LVS(底层网络负载均衡,性能强)、F5(硬件,贵,大厂首选);
- 应用服务器:Tomcat/Netty(3 台部署,配置相同:8 核 16G 内存);
- 数据库服务器:4 核 32G 内存 + 1TB SSD(和应用数据分离架构一致)。
3.3.5 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 应用层无限扩容:用户再涨,继续加应用服务器即可,并发能到 5000 / 秒 ------ 顾客再多,加服务员就行 | 数据库仍为单点:所有应用服务器都查同一个数据库,数据库成了新瓶颈 ------ 所有服务员都从同一个仓库拿货,仓库忙不过来 |
| 可用性提升:一台应用服务器崩了,负载均衡会把请求分给其他服务器 ------ 服务员 A 请假,迎宾员把顾客分给 B、C,饭店正常营业 | 会话同步问题:用户登录服务器 A 后,下次请求到服务器 B,B 不认识用户,需要重新登录 ------ 服务员 A 认识顾客,服务员 B 不认识,顾客要重新报身份 |
| 成本低:加普通服务器即可,无需高配 ------ 普通服务员比奥运冠军便宜得多 | 运维复杂度增加:要管理多台应用服务器、配置负载均衡,程序员兼顾不过来,需要专业运维 |
3.3.6 实际问题(用户量再增长)
- 数据库瓶颈:当日活涨到 100 万,并发到 1 万 / 秒时,所有应用服务器都查 / 写同一个数据库,数据库的 CPU、IO、内存全占满 ------ 查询商品要等 5 秒,甚至数据库崩溃;
- 会话同步问题:用户频繁登录,体验极差 ------ 比如用户在地铁上切换网络,请求到不同应用服务器,需要反复登录。
会话同步问题解决方案:用 Redis 存储用户会话 ------ 把用户登录信息(比如用户 ID、昵称、登录状态)存到 Redis,所有应用服务器都从 Redis 读取会话信息。无论请求到哪台服务器,都能从 Redis 识别用户身份,不用重新登录。
阶段 4:读写分离 / 主从分离架构 ------ 拆分 "记账和查账"(日活≤100 万,并发≤1 万 / 秒)
3.4.1 演进背景
应用服务集群解决了应用层的压力,但数据库成了新瓶颈 ------ 数据库不能像应用服务器那样 "随便加",因为数据要一致(比如用户买了商品,库存要减 1,所有服务器都要看到这个变化)。
核心发现:电商系统的 "读请求" 远多于 "写请求"(比例约 100:1)------ 比如 100 次查商品、查库存,只有 1 次下单、改库存。所以可以把 "写请求" 和 "读请求" 分开处理,减轻数据库压力。
3.4.2 架构详情(用 "大超市的收银台" 类比)
就像大超市的收银台:设 1 个 "主收银台"(主库),负责收钱、改价(写操作);设 3 个 "副收银台"(从库),负责查价格、打小票(读操作)。副收银台的账本,每天从主收银台抄一遍 ------ 核心是 "写找主,读找从,分而治之"。
具体流程:
- 用户的 "写请求"(下单、改密码、加购物车):负载均衡→应用服务器→数据库中间件→主数据库(处理写入)------ 顾客付款、改价,只能找主收银台;
- 主数据库把数据同步到所有从数据库 ------ 主收银台写完账本,副收银台抄账本;
- 用户的 "读请求"(查商品、查订单、查库存):负载均衡→应用服务器→数据库中间件→从数据库(处理读取)------ 顾客查价格、打小票,找任意副收银台;
- 从数据库返回结果,应用服务器组装后返回给用户 ------ 副收银台告诉顾客价格,完成查询。
架构图:
用户 → 负载均衡 → 应用服务器集群
↓
数据库中间件(MyCat)
↓ ↓
主数据库(写) 从数据库1/2/3(读)
↓
数据同步(主→从)

3.4.3 核心细节:主从同步 & 数据库中间件
- 主从同步:数据怎么从主库传到从库?
主从同步是读写分离的核心,流程拆解(用 "抄作业" 类比):
- 主库执行完写操作(比如用户下单,库存减 1),生成 "二进制日志(binlog)"------ 班长(主库)写完作业,把作业内容抄到日志本上;
- 从库启动 "IO 线程",连接主库,读取 binlog 日志,写入自己的 "中继日志(relay log)"------ 学习委员(从库)去班长那抄日志,写到自己的笔记本上;
- 从库启动 "SQL 线程",执行中继日志中的命令,同步主库的数据 ------ 学习委员照着笔记本上的内容,完成自己的作业;
- 同步完成后,从库的数据和主库一致 ------ 学习委员的作业和班长的一样。
- 同步延迟:整个过程需要时间(通常毫秒级,极端情况秒级)------ 比如主库 10:00:00 完成写操作,从库 10:00:02 才同步完成,这 2 秒内从库数据是旧的;
- 解决方案:核心业务(如订单详情、支付状态)读主库,非核心业务(如商品列表、分类页面)读从库 ------ 顾客查自己的订单(核心),找主收银台;查商品列表(非核心),找副收银台。
- 数据库中间件(MyCat/TDDL):"读写请求分流器"
数据库中间件的作用是 "帮应用服务器区分读写请求",不用程序员手动写代码判断,降低开发复杂度:
- 读请求:应用服务器执行
select * from product(查商品),中间件自动路由到从库; - 写请求:应用服务器执行
update product set stock=99(改库存),中间件自动路由到主库; - 故障转移:如果某个从库崩了,中间件会自动把请求分给其他从库 ------ 副收银台 A 坏了,顾客自动找副收银台 B。
3.4.4 用到的技术 & 服务器配置
- 数据库中间件:MyCat(开源免费,中小公司首选)、TDDL(阿里开源,大厂常用)、Amoeba、Cobar;
- 数据库集群:1 主 3 从 MySQL 集群 ------ 主库(4 核 32G + 1TB SSD),从库(4 核 16G + 512G SSD);
- 应用服务器集群:5 台 Tomcat(8 核 16G);
- 负载均衡:Nginx(1 台,4 核 8G)。
3.4.5 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 数据库读压力大幅降低:3 个从库分担 99% 的读请求,主库只处理 1% 的写请求 ------3 个副收银台分担查价格,主收银台只收钱,压力大减 | 主库仍为单点:主库崩了,所有写操作都停 ------ 主收银台坏了,顾客无法付款,只能查价格 |
| 性能提升:读请求响应时长从 5 秒缩短到 1 秒,并发能到 1 万 / 秒 ------ 顾客查价格不用等,付款也顺畅 | 数据同步延迟:极端情况下,从库数据和主库不一致 ------ 副收银台没抄完账本,告诉顾客的价格是旧的 |
| 可用性提升:一个从库崩了,中间件会把请求分给其他从库 ------ 副收银台 A 坏了,顾客找 B、C,不影响查询 | 运维复杂度大增:要管理主从同步、监控延迟、处理从库故障,需要专业 DBA(数据库管理员) |
3.4.6 实际问题(用户量再增长)
当日活涨到 500 万,并发到 5 万 / 秒时,新的问题出现:
- 热点数据压力:爆款商品的读请求太多,每秒几万次查同一个商品,即使 3 个从库分担,每个从库也要处理上万次请求,压力仍很大;
- 数据量过大:订单表数据达到 1 亿条,单库磁盘快满了,查询速度变慢 ------ 比如查 "2024 年的订单",要扫描 1 亿条数据,耗时 10 秒。
阶段 5:引入缓存 ------ 冷热数据分离(日活≤500 万,并发≤5 万 / 秒)
3.5.1 演进背景
电商系统中,80% 的读请求都集中在 20% 的 "热数据" 上 ------ 比如爆款商品、热门活动页面、用户登录信息;而 20% 的请求查 "冷数据"(比如小众商品、一年前的订单)。如果把 "热数据" 放在 Redis 缓存中,就能拦截 80% 的读请求,根本不用查数据库,给数据库 "减负"。
3.5.2 架构详情(用 "超市的收银台旁货架" 类比)
就像超市把矿泉水、零食(热数据)放在收银台旁的小货架上,顾客买这些高频商品时,不用去仓库(数据库),直接从货架(缓存)拿 ------ 核心是 "热数据放缓存,冷数据放数据库,减少仓库访问"。
具体流程(分读请求和写请求):
-
读请求流程(查商品、查库存):
-
用户查商品→应用服务器先查 Redis 缓存;
-
如果缓存里有(命中):直接返回数据,不用查数据库 ------ 顾客从收银台旁货架拿矿泉水,不用去仓库;
-
如果缓存里没有(未命中):查从数据库→把数据存到 Redis 缓存→返回给用户 ------ 顾客要的商品货架没有,去仓库拿,同时放一个到货架,下次别人要直接拿。
-
写请求流程(下单、改库存):
-
用户下单→应用服务器先改主数据库(更新库存、创建订单);
-
删 Redis 缓存(或更新缓存)------ 避免缓存和数据库数据不一致;
-
返回下单成功。
架构图:
用户 → 负载均衡 → 应用服务器集群
↓ ↓
Redis缓存集群 数据库中间件
↓ ↓ ↓
(热数据) 主库 从库集群

3.5.3 核心:缓存的 "坑" 与解决方案
缓存能让性能暴增,但也容易踩坑 ------ 每个坑都用 "超市场景" 类比,解决方案直接落地:
- 缓存穿透:查 "不存在的商品",数据库压力大
- 问题描述:顾客问 "有没有火星矿泉水"(不存在的商品),货架(缓存)没有,就一直去仓库(数据库)问 ------ 黑客批量请求不存在的商品 ID,每秒 1 万次,导致数据库 CPU 100%。
- 解决方案 :
- 缓存空值:数据库查不到的商品,在 Redis 缓存一个空值(比如
set product:-1 "" ex 3600),设置 1 小时过期 ------ 货架上贴个纸条 "没有火星矿泉水",1 小时后再检查; - 布隆过滤器:在 Redis 前部署布隆过滤器,把所有存在的商品 ID 存入 ------ 顾客问的商品 ID 不在布隆过滤器里,直接返回 "没有",不用查缓存和数据库,这个我们之前可是讲过的哦
- 缓存空值:数据库查不到的商品,在 Redis 缓存一个空值(比如
- 缓存击穿:热点商品缓存过期,数据库压力暴增
- 问题描述:收银台旁的矿泉水(热点商品)卖完了(缓存过期),瞬间 1 万用户来买,都去仓库问 ------ 爆款商品缓存过期,大量请求同时查数据库,数据库崩溃。
- 解决方案 :
- 热点数据永不过期:给爆款商品的缓存不设置过期时间,定期手动更新 ------ 货架上的矿泉水永远不撤,卖完了手动补货;
- 加互斥锁:用 Redis 的
setnx命令,只有一个线程能获取锁,去数据库查数据,其他线程等待 ------ 只有一个服务员能去仓库拿矿泉水,其他人等服务员补货后,从货架拿; - 缓存预热:提前把热门商品放进缓存(比如活动开始前 1 小时,批量加载数据到 Redis)------ 活动开始前,服务员把矿泉水摆满货架,顾客直接拿。
- 缓存雪崩:大量缓存同时过期,数据库崩溃
- 问题描述:晚上 12 点,货架上的所有商品都过期了(大量缓存同时过期),所有顾客都去仓库问 ------ 比如双十一活动结束后,所有商品缓存同时过期,瞬间 10 万请求查数据库,数据库崩溃。
- 解决方案 :
- 缓存过期时间加随机数:比如有的商品缓存 1 小时,有的 1 小时 10 分,有的 1 小时 20 分,避免同时过期 ------ 货架上的商品保质期错开,不会同时卖完;
- Redis 集群部署:用 Redis 集群(多台服务器),避免单台 Redis 崩了 ------ 多个货架,一个货架空了,还有其他货架;
- 服务降级:缓存崩了,只返回核心商品(比如只显示爆款商品),非核心商品提示 "暂时无法访问"------ 仓库忙不过来,只卖矿泉水、零食,其他商品暂停销售。
- 缓存一致性:缓存和数据库数据不一致
- 问题描述:仓库里的矿泉水价格改了(数据库更新),但货架上的价格没改(缓存没更)------ 顾客看到的价格是旧的,付款时发现价格不对。
- 解决方案 :
- 先删缓存,再更数据库:更新数据库前,先删除缓存,更新后,下次查询会从数据库加载新数据到缓存 ------ 仓库改价格前,先把货架上的矿泉水拿走,改完价格后,再摆上新价格的矿泉水;
- 加重试机制:删缓存可能失败(比如网络问题),用消息队列重试,确保缓存删除成功 ------ 第一次没拿走货架上的矿泉水,再试一次,直到拿走。
3.5.4 用到的技术 & 服务器配置
- 分布式缓存:Redis 集群(3 台服务器,4 核 16G 内存,存储热数据);
- 本地缓存(辅助):Memcached(每个应用服务器本地部署,缓存高频访问的小数据,比如商品分类);
- 其他组件:和读写分离架构一致(应用服务器、数据库集群、负载均衡)。
3.5.5 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 性能暴增:80% 的请求从缓存返回,响应时长从 1 秒缩短到 0.1 秒,并发能到 5 万 / 秒 ------ 顾客查商品瞬间加载,体验极佳 | 缓存复杂度高:要处理穿透、击穿、雪崩等问题,开发和运维成本增加 |
| 数据库压力大减:读请求减少 80%,数据库 CPU 使用率从 100% 降到 20%------ 仓库不用应对大量查询,专注处理写操作 | Redis 成了新单点:Redis 集群崩了,请求会全压到数据库,数据库可能崩溃 |
| 成本低:Redis 用内存,比加数据库服务器便宜得多 ------ 货架比仓库建设成本低 | 数据一致性风险:缓存和数据库可能出现短暂不一致,需要复杂的解决方案 |
3.5.6 实际问题(用户量再增长)
当日活涨到千万级,并发到 10 万 / 秒时,新的瓶颈出现:
- 单库数据量过大:订单表数据达到 10 亿条,单库磁盘达到 5TB,即使分了主从、加了缓存,查询速度还是慢 ------ 比如查 "2024 年 1 月的订单",要扫描 1 亿条数据,耗时 10 秒;
- 跨表查询复杂:比如查 "用户 1001 的所有订单 + 对应的商品信息",需要关联订单表和商品表,单库查询效率低。
阶段 6:垂直分库 + 水平分表 ------ 拆分 "大账本"(日活≤1000 万,并发≤10 万 / 秒)
3.6.1 演进背景
单库的数据量太大,就像一本 "厚到翻不动的账本"------ 要查订单,得翻 10 亿条记录,根本查不动。核心思路是 "把厚账本拆成薄账本":先按业务拆(垂直分库),再按数据量拆(水平分表),让每个库、每个表的数据量都足够小,查询速度变快。
3.6.2 垂直分库:按业务拆 "账本"
- 原理:把一个数据库拆成多个独立的数据库,每个库存一个业务的数据 ------ 比如用户库、商品库、交易库,各自有独立的主从集群,互不干扰。
- 生活类比:把超市的一本大账本,拆成 "顾客账本"(用户库)、"商品账本"(商品库)、"收银账本"(交易库),每个账本由专人管理,不用翻大账本。
- 拆分示例(电商数据库) :
- 原电商库(包含所有表)→ 拆分为 3 个库:
- 用户库:用户表、地址表、登录记录表(管理用户相关数据);
- 商品库:商品表、分类表、库存表(管理商品相关数据);
- 交易库:订单表、支付表、退款表(管理交易相关数据)。
- 原电商库(包含所有表)→ 拆分为 3 个库:
架构图(文字版):
用户 → 负载均衡 → 应用服务器集群
↓ ↓ ↓
用户库集群 商品库集群 交易库集群
(主从) (主从) (主从)

3.6.3 水平分表:把 "厚账本拆成薄账本"
垂直分库后,单个业务库的数据量还是大(比如交易库的订单表有 10 亿条数据),需要进一步 "按规则拆分表",让每个表的数据量控制在 1 亿条以内:
- 拆分规则(两种常用方式)
| 拆分方式 | 原理 | 示例(订单表拆分) | 优点 | 缺点 |
|---|---|---|---|---|
| 按时间拆分 | 按时间维度拆分,比如每月 / 每季度一个表 | 订单_202401、订单_202402、订单_202403(每月一个表) | 查询历史数据方便(直接查对应月份的表);冷热数据分离 | 热点数据集中(比如当前月份的表数据量仍大) |
| 按用户 ID 哈希拆分 | 按用户 ID 取模,分配到不同的表 | 用户 ID%10=0→订单表 0,ID%10=1→订单表 1(共 10 个表) | 数据分布均匀;查询用户订单快(直接计算表名) | 跨用户查询复杂(比如查所有用户的今日订单,要查 10 个表) |
- 生活类比
把 "收银账本"(订单表)拆成 "1 月账本""2 月账本""3 月账本"(按时间拆分),查 1 月的订单只翻 1 月账本,不用翻全年的;或者按顾客 ID 拆分,顾客 ID 尾号 0→账本 0,尾号 1→账本 1,每个账本只有 1/10 的数据,翻起来更快。
- 拆分后的查询示例
- 按时间拆分:查用户 1001 在 2024 年 1 月的订单→直接查询订单_202401 表,过滤用户 ID=1001 的记录;
- 按用户 ID 拆分:查用户 1001 的所有订单→计算 1001%10=1→查询订单表 1,直接获取该用户的所有订单。
3.6.4 核心技术:分库分表中间件
分库分表后,应用服务器不知道数据存在哪个库、哪个表,需要中间件帮忙 "找到数据":
- 作用:解析 SQL 语句,根据拆分规则,路由到对应的库和表;合并跨库 / 跨表的查询结果;
- 常用中间件:MyCat(支持分库分表、读写分离,中小公司首选)、Sharding-JDBC(轻量级,嵌入应用,大厂常用);
- 示例 :应用服务器执行
select * from order where user_id=1001,中间件计算 1001%10=1→路由到交易库的订单表 1,返回结果。
3.6.5 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 数据量分散:单库 / 单表的数据量从 10 亿降到 1 亿,查询速度从 10 秒缩短到 0.5 秒 ------ 薄账本翻起来快 | 跨库查询难:查 "用户 1001 的所有订单 + 商品信息",需要查用户库 + 订单库 + 商品库,应用层拼接数据 ------ 要查顾客的订单和商品,需要翻多个账本,再汇总 |
| 并发能力提升:10 万 / 秒并发能稳定支撑 ------ 多个账本同时处理请求,互不干扰 | 运维复杂度极高:要管理几十个库 / 表,监控数据分布,处理分表后的备份,需要专业 DBA 团队 |
| 可用性提升:一个业务库崩了,不影响其他业务(比如商品库崩了,用户还能查订单)------ 商品账本丢了,顾客还能查订单、付款 | 事务复杂:跨库的事务(比如下单扣库存,涉及订单库和商品库),无法用单机事务,需要分布式事务 |
3.6.6 实际问题(业务再复杂)
当业务从 "卖商品" 扩展到 "直播带货、会员、优惠券、物流",应用服务器的代码越来越复杂 ------ 改一个优惠券的逻辑,可能影响到订单、商品、用户模块,开发效率极低;且团队人数从几人涨到几百人,多人维护一个应用,容易出现代码冲突、版本发布困难。
阶段 7:微服务架构 ------ 拆成 "独立小店"(日活≥1000 万,并发≥10 万 / 秒)
3.7.1 演进背景
系统业务越来越复杂,团队越来越大,"一个应用管所有业务" 的模式已经走不通 ------ 核心思路是 "按业务拆成独立的小应用(微服务),每个微服务独立开发、部署、运维",就像把大超市拆成多个独立的小店,各自运营。
3.7.2 架构详情(用 "商业综合体" 类比)
就像城市里的商业综合体:不再是一个大超市,而是拆成 "服装店""餐饮店""电影院""超市"(微服务),每个店独立运营,有自己的服务员(应用集群)、仓库(数据库)、货架(缓存);综合体门口有 "总服务台"(网关),顾客进门后,总服务台指引到对应的店 ------ 核心是 "业务解耦,独立运作"。
具体架构(拆分成哪些微服务):
- 核心业务微服务 :
- 用户微服务:负责登录、注册、用户信息管理(有自己的应用集群、Redis、用户库);
- 商品微服务:负责商品展示、库存管理、分类管理(有自己的应用集群、Redis、商品库);
- 订单微服务:负责下单、支付、订单查询、退款(有自己的应用集群、Redis、订单库);
- 优惠券微服务:负责优惠券发放、核销、规则管理(有自己的应用集群、Redis、优惠券库);
- 物流微服务:负责物流信息录入、查询、配送状态更新(有自己的应用集群、Redis、物流库)。
- 公共服务(支撑核心微服务) :
- 网关(Gateway/Nginx):所有用户请求先到网关,路由到对应的微服务 ------ 商业综合体的总服务台,指引顾客到对应店铺;
- 服务注册发现(Nacos/Eureka):微服务启动后,把自己的地址注册到注册中心,其他服务通过注册中心找到它 ------ 店铺开业后,把地址告诉总服务台,其他店铺要合作,从总服务台查地址;
- 消息总线(Kafka/RabbitMQ):服务之间异步通信,不用同步等待 ------ 服装店要补货,发消息给供应商,不用一直等供应商回复;
- 安全中心:负责用户鉴权、Token 验证 ------ 商业综合体的保安,验证顾客身份,防止无关人员进入店铺;
- 监控中心:监控每个微服务的 CPU、内存、响应时间,出现问题及时报警 ------ 商业综合体的监控室,盯着每个店铺的运营状态。
架构图(文字版):
用户 → 网关(Gateway)
↓ ↓ ↓ ↓ ↓
用户微服务 商品微服务 订单微服务 优惠券微服务 物流微服务
(应用+Redis+库) (应用+Redis+库) (应用+Redis+库) (应用+Redis+库) (应用+Redis+库)
↓ ↓ ↓ ↓ ↓
消息总线(Kafka)
↓
服务注册发现(Nacos)、安全中心、监控中心

3.7.3 核心优势:解耦与敏捷(为什么要拆成微服务)
- 开发解耦:各做各的,互不干扰
- 用户团队只维护用户微服务,商品团队只维护商品微服务,改代码时不用考虑其他模块 ------ 服装店的店员只负责卖衣服,不用管餐饮店的运营;
- 技术栈可以不同:用户微服务用 Java,商品微服务用 Go,订单微服务用 Python------ 不同店铺可以用不同的工具,不用统一。
- 部署解耦:独立发布,不影响整体
- 商品微服务升级(比如新增 "商品规格" 功能),不用停整个系统,只停商品微服务 ------ 服装店装修,不影响餐饮店、电影院正常营业;
- 发布频率更高:每个微服务可以独立迭代,比如商品微服务每周发布 1 次,订单微服务每月发布 1 次 ------ 服装店可以经常上新,餐饮店可以慢慢优化菜单。
- 扩展解耦:按需扩容,资源不浪费
- 直播带货导致商品微服务压力大,只给商品微服务加服务器,不用给订单微服务加 ------ 服装店顾客多,加店员;餐饮店顾客少,不用加;
- 故障隔离:一个微服务崩了(比如优惠券微服务),不影响核心业务(下单、支付)------ 优惠券店关门,顾客还能买衣服、吃饭。
3.7.4 用到的技术 & 服务器配置
- 网关:Spring Cloud Gateway(开源,支持动态路由)、Nginx(高性能,适合高并发);
- 服务注册发现:Nacos(阿里开源,支持服务注册、配置管理,中小公司首选)、Eureka(Netflix 开源,大厂常用)、Consul;
- 消息总线:Kafka(高吞吐,适合海量消息)、RabbitMQ(易用性强,适合复杂路由)、RocketMQ(阿里开源,兼顾吞吐和易用);
- 微服务框架:Spring Cloud(Java 生态,中小公司首选)、Dubbo(阿里开源,高性能,大厂常用);
- 服务器配置:每个微服务独立部署,应用服务器(8 核 16G)、Redis(4 核 16G)、数据库(4 核 32G + SSD),根据业务压力弹性扩容。
3.7.5 优点 & 缺点
| 优点 | 缺点 |
|---|---|
| 开发效率高:团队分工明确,改代码、发版本互不干扰,能快速响应业务变化 ------ 各店铺独立运营,决策快 | 运维复杂度 "指数级" 增加:要管理上百个微服务、监控链路、处理服务调用失败,需要专业运维团队 |
| 无限扩展:每个微服务都能独立扩容,支撑千万级日活、百万级并发 ------ 商业综合体可以不断加新店铺,接待更多顾客 | 分布式问题多:分布式事务、服务调用超时、链路追踪难,排查问题复杂 ------ 多个店铺协作,出问题后很难找到原因 |
| 容错性强:一个微服务崩了,不影响核心业务 ------ 优惠券店关门,不影响顾客下单、支付 | 学习成本高:程序员要掌握网关、注册中心、消息队列等一堆技术,门槛高 |
阶段 8:尾声 ------ 架构演进的核心原则
分布式系统的演进不是 "一步到位",而是 "按需迭代",没有 "最好的架构",只有 "最适合当前业务的架构":
- 不超前设计:日活 1000 时,不用做微服务,单机架构就够 ------ 小超市不用拆成商业综合体,浪费资源;
- 小步快跑:每次只解决当前最核心的瓶颈(比如先解决应用单点,再解决数据库单点),不用一次重构所有架构;
- 因地制宜:政府系统并发低,但业务复杂,不用追求高并发,重点是业务解耦;电商系统并发高,重点是性能和扩展;
- 留有余地:架构设计时,预留扩展接口(比如应用和数据库分离时,用网络通信,为后续集群做准备),避免后续重构成本过高。
第四部分:分布式系统常见问题
4.1 分布式事务:怎么保证 "下单扣库存" 都成功?
- 问题描述:订单微服务创建订单(状态待支付),然后调用商品微服务扣库存,扣库存失败后,订单已经创建,导致 "订单生成了,库存没扣",可能出现超卖。
- 通俗解决方案:最终一致性 :
- 先下单,后扣库存:订单微服务创建订单(状态 "待扣库存"),发消息给商品微服务扣库存;
- 扣库存成功:商品微服务发消息给订单微服务,订单状态改为 "待支付";
- 扣库存失败:商品微服务发消息给订单微服务,订单状态改为 "取消";
- 消息重试:扣库存失败后,消息队列重试 3 次(间隔 1 秒、3 秒、5 秒),仍失败则取消订单。
- 技术方案:Seata(阿里开源,支持分布式事务)、RocketMQ 事务消息(确保消息可靠发送)。
4.2 服务熔断 / 降级:避免 "一个服务崩了,拖垮所有服务"
4.2.1 服务熔断:"暂时断开故障服务"
- 问题:商品微服务崩了,订单微服务还一直调用它,导致订单微服务线程池占满,也跟着崩 ------ 服装店关门了,顾客还一直敲门,导致店员无法接待其他顾客。
- 解决方案:用 Sentinel/Hystrix 实现熔断 ------ 商品微服务失败次数超过阈值(比如 10 次 / 秒),触发熔断,订单微服务暂时不调用它,直接返回 "库存查询失败,请稍后再试",30 秒后尝试恢复。
4.2.2 服务降级:"关闭非核心功能,保障核心功能"
- 问题:618 高峰期,系统并发达到极限,所有服务都变慢 ------ 商业综合体顾客太多,所有店铺都排队,顾客体验差。
- 解决方案:关闭非核心功能,把资源留给核心功能 ------ 关闭商品评论、物流跟踪等非核心功能,只保留 "下单、支付、查商品" 核心功能,确保用户能正常购物。
4.3 链路追踪:定位 "哪个服务出问题了"
- 问题:用户下单慢,不知道是订单微服务慢,还是商品微服务慢,还是数据库慢 ------ 顾客投诉 "吃饭慢",不知道是后厨慢,还是传菜员慢,还是收银员慢。
- 解决方案:链路追踪 :
- 给每个请求加一个 "全局 ID"(比如 traceId=123456);
- 请求经过的所有服务,都记录 traceId 和耗时 ------ 订单微服务(0.1 秒)→ 商品微服务(1 秒)→ 商品库(0.9 秒);
- 通过链路追踪工具(SkyWalking/Zipkin),可视化展示请求路径和耗时,一眼看出是商品库慢。
- 技术方案:SkyWalking(开源,支持分布式链路追踪、监控)、Zipkin(Netflix 开源,轻量级)。
结语
到这里,这篇横跨 Redis 核心认知与分布式系统架构演进的博客就正式收尾了。从 Redis 作为 "性能加速器" 的核心价值,到分布式系统的基础术语、核心指标,再到从单机架构一步步演进到微服务架构的完整路径,我们用 "超市、饭店、商业综合体" 的生活类比,把复杂的技术概念拆解得通俗易懂,本质上是想传递一个核心逻辑:架构没有银弹,演进没有终点,所有技术选型和架构设计,都是为了解决当前阶段的核心瓶颈。
回望整个架构演进之路,从日活 1000 的单机小作坊,到日活千万的微服务集群,我们能清晰地看到一条 "问题驱动优化" 的主线:用户量增长导致 CPU 瓶颈,就做应用集群;数据库成为单点,就做读写分离;热数据查询压力大,就引入 Redis 缓存;数据量过大查不动,就做分库分表;业务复杂团队协作难,就拆成微服务。每一步演进都不是 "超前设计",而是 "对症下药",这也正是分布式系统架构的核心原则 ------适合当前业务的,才是最好的。
而 Redis,作为这条演进路上的 "关键变量",从架构中期就成为了不可或缺的存在。它用内存存储的极致性能,拦截了 80% 的热数据查询,给数据库 "减负";用丰富的数据结构和附加功能,支撑起缓存、计数器、分布式锁等多种业务场景;更作为分布式系统的 "性能底座",让高并发场景下的低延迟成为可能。可以说,理解 Redis 的核心价值,就能抓住分布式系统性能优化的 "命脉";掌握 Redis 的实际用法,就能在架构设计中找到平衡性能与可用性的 "钥匙"。
当然,这篇博客只是分布式系统的 "入门全景图"。Redis 的具体数据结构怎么用?缓存穿透、击穿、雪崩的实战解决方案如何落地?微服务的分布式事务怎么实现得更优雅?服务熔断降级的具体配置是什么?这些更深入的技术细节,都需要我们在后续的学习中逐一攻克。但请记住,技术的掌握从来不是 "背会多少知识点",而是 "理解背后的逻辑"------ 比如架构演进的 "按需迭代" 思维,分布式系统的 "分而治之" 思路,Redis 缓存的 "冷热分离" 核心,这些思维方式远比单个技术点更重要。
最后,技术学习的本质是 "实践中沉淀"。建议大家在看完这篇博客后,不妨结合自己的项目场景思考:当前项目处于哪个架构阶段?核心瓶颈是什么?如果引入 Redis,能解决什么问题?如果业务增长 10 倍,架构需要做哪些调整?带着问题去学习、去实践,才能真正把知识内化为能力。
Redis 和分布式系统是现代后端开发的 "必修课",也是求职面试中的 "高频考点"。希望这篇博客能成为大家入门的 "敲门砖",帮助大家建立清晰的知识框架,后续无论是深入 Redis 的底层原理,还是钻研分布式系统的高级技术(如分布式锁、一致性算法),都能有明确的方向。技术之路漫漫,循序渐进,吃透本质,方能行稳致远。期待大家在实践中不断探索,把这些技术真正用起来,构建出高性能、高可用、可扩展的分布式系统,我们下次博客再见~