目录
[一、Redis:不止是 "内存缓存",是分布式系统的 "基础组件"](#一、Redis:不止是 “内存缓存”,是分布式系统的 “基础组件”)
[1. Redis 的底层逻辑:为什么它能扛住 10 万 + QPS?](#1. Redis 的底层逻辑:为什么它能扛住 10 万 + QPS?)
[2. Redis 的 "必踩坑":缓存三大问题 + 解决方案](#2. Redis 的 “必踩坑”:缓存三大问题 + 解决方案)
[3. Redis 集群:从 "单点" 到 "高可用" 的演进](#3. Redis 集群:从 “单点” 到 “高可用” 的演进)
[二、分布式架构:从 "单机" 到 "多节点" 的核心逻辑](#二、分布式架构:从 “单机” 到 “多节点” 的核心逻辑)
[1. 架构拆分的两种思路:垂直 vs 水平](#1. 架构拆分的两种思路:垂直 vs 水平)
[2. 分布式架构的 "三大核心问题"](#2. 分布式架构的 “三大核心问题”)
[3. 架构演进的 "分层逻辑":从 "乱搭" 到 "有序"](#3. 架构演进的 “分层逻辑”:从 “乱搭” 到 “有序”)
[三、架构设计的 "细节":从图到实践的思考](#三、架构设计的 “细节”:从图到实践的思考)
[1. 为什么不用 Redis 做消息队列?](#1. 为什么不用 Redis 做消息队列?)
[2. 分布式系统的 "可用性指标" 怎么定?](#2. 分布式系统的 “可用性指标” 怎么定?)
[最后:技术学习的 "底层逻辑"](#最后:技术学习的 “底层逻辑”)
近花了两周时间,把 Redis 核心原理、分布式系统设计、架构演进的实践细节重新梳理了一遍 ------ 从单机缓存到多节点集群,从理论到项目踩坑,很多知识点越挖越觉得 "底层逻辑相通"。这篇把整理的核心内容拆成模块分享,建议收藏慢慢看~
一、Redis:不止是 "内存缓存",是分布式系统的 "基础组件"
刚开始用 Redis 时,我只把它当 "能持久化的 HashMap",直到在项目里遇到高并发穿透、主从同步延迟、集群脑裂这些问题,才意识到它是分布式架构的 "基础设施"------ 每一个特性背后都是对 "性能、可用性、一致性" 的权衡。
1. Redis 的底层逻辑:为什么它能扛住 10 万 + QPS?
Redis 的高性能不是 "天生的",而是架构设计 + 数据结构的双重优化:
- 单线程模型:避免多线程上下文切换的开销,但这里的 "单线程" 仅指 "处理请求的主线程",持久化、集群同步等操作是异步线程执行的;
- 高效数据结构 :
- 字符串:采用 "简单动态字符串(SDS)",预分配空间减少内存碎片,支持二进制安全;
- 哈希:小数据用 "压缩列表"(连续内存 + 紧凑编码),大数据自动转 "哈希表";
- 有序集合:用 "跳表 + 哈希表" 实现 ------ 跳表保证 O (logN) 的增删查,哈希表保证 O (1) 的成员存在性判断。
- IO 模型:基于 Linux 的 IO 多路复用(epoll),单线程就能处理万级并发连接。
2. Redis 的 "必踩坑":缓存三大问题 + 解决方案
在电商项目中,我曾因为没处理好缓存问题,导致 DB 被打垮过一次 ------ 这三个场景是分布式系统的 "通用坑",必须提前设防:
| 问题类型 | 场景描述 | 解决方案 |
|---|---|---|
| 缓存穿透 | 请求不存在的 Key,缓存未命中,流量直接打穿到 DB(比如恶意攻击查不存在的用户 ID) | 1. 布隆过滤器:提前过滤不存在的 Key;2. 空值缓存:不存在的 Key 缓存空值(设置短过期时间) |
| 缓存击穿 | 热点 Key 突然过期,瞬间大量请求打向 DB(比如秒杀商品的库存 Key 过期) | 1. 互斥锁:请求 DB 时加锁,同一时间只有一个请求回源;2. 热点 Key 永不过期:业务层标记为 "不自动过期" |
| 缓存雪崩 | 大量 Key 在同一时间过期,DB 压力骤增(比如凌晨 1 点统一设置的过期 Key 集体失效) | 1. 过期时间随机化:给每个 Key 的过期时间加 5~10 分钟的随机值;2. 分层缓存:本地缓存 + 分布式缓存结合 |
3. Redis 集群:从 "单点" 到 "高可用" 的演进
项目初期用单机 Redis,一次服务器断电直接导致缓存全丢,之后才升级成集群 ------Redis 的集群方案是 "分片 + 主从" 的组合,核心是数据分片 + 自动故障转移:
- 分片逻辑 :采用 "哈希槽(Hash Slot)" 机制,把 16384 个槽分配给不同节点,Key 通过
CRC16(key) % 16384映射到对应槽; - 主从同步:每个主节点至少对应 1 个从节点,主节点故障时,从节点会通过 "Raft 算法" 选举新主;
- 踩坑点 :集群模式下不支持跨槽的事务操作,必须把相关 Key 用
{prefix}做哈希标签,强制落到同一个槽。
二、分布式架构:从 "单机" 到 "多节点" 的核心逻辑
当项目用户量从 "万级" 涨到 "百万级",单机架构的瓶颈会集中爆发:CPU 跑满、内存不够、DB 连接池耗尽...... 这时候必须用分布式架构 "拆" 开压力,但拆分的同时也会引入新问题。
1. 架构拆分的两种思路:垂直 vs 水平
拆分是分布式的第一步,两种方式各有适用场景:
- 垂直拆分 :按业务模块拆分(比如把 "用户系统、订单系统、支付系统" 分成独立服务)
- 优势:业务边界清晰,便于维护和扩容;
- 问题:部分模块会成为 "热点"(比如支付系统的并发远高于用户系统)。
- 水平拆分 :按数据维度拆分(比如用户 ID 取模,把用户数据分散到 10 个数据库)
- 优势:解决单库数据量过大的问题,性能线性扩容;
- 问题:跨分片查询复杂(比如查 "所有地区的订单" 需要聚合多个分片的数据)。
2. 分布式架构的 "三大核心问题"
拆分后,系统会从 "单节点的强一致性" 变成 "多节点的最终一致性",这三个问题是绕不开的:
- 数据一致性 :多节点之间的数据如何同步?(比如订单支付成功后,用户余额和订单状态必须同时更新)
- 方案:用 MQ 做异步通知(最终一致性),或用 TCC/2PC 做分布式事务(强一致性,但性能低)。
- 服务可用性 :某个节点故障如何不影响整体系统?(比如订单系统的一个节点挂了,用户仍能下单)
- 方案:服务注册与发现(比如 Nacos/Eureka)+ 负载均衡(比如 Ribbon/NGINX)。
- 分布式锁 :多节点如何保证 "同一资源同一时间只有一个操作"?(比如秒杀商品的库存扣减)
- 方案:用 Redis 的
SETNX(但要注意过期时间 + 续命),或 ZooKeeper 的临时节点。
- 方案:用 Redis 的
3. 架构演进的 "分层逻辑":从 "乱搭" 到 "有序"
整理笔记时,我画了一张从 "单机" 到 "分布式" 的架构演进图,核心是 "分层":
- 网关层:做请求路由、限流、鉴权(比如用 NGINX+Lua 拦截恶意请求);
- 应用层:按业务拆分成微服务(比如用户服务、订单服务);
- 中间件层:缓存(Redis)、消息队列(Kafka)、搜索引擎(Elasticsearch);
- 数据层:分库分表的数据库(比如 MySQL+Sharding-JDBC)。
三、架构设计的 "细节":从图到实践的思考
笔记里的架构图不是 "画着好看",每一个组件的选择都是对 "成本、性能、复杂度" 的权衡 ------ 举两个例子:
1. 为什么不用 Redis 做消息队列?
项目初期为了省成本,用 Redis 的 List 做过消息队列,但压测时发现:
- 缺点:不支持消息确认(ACK)、没有死信队列、消息堆积后性能下降;
- 结论:小流量场景可以用,但中高并发必须换专门的 MQ(比如 Kafka/RabbitMQ)。
2. 分布式系统的 "可用性指标" 怎么定?
很多人说 "要做 4 个 9 的可用性",但实际要结合业务:
- 4 个 9:99.99%,年故障时间≤52 分钟(适合支付、交易等核心系统);
- 3 个 9:99.9%,年故障时间≤8.76 小时(适合非核心的用户系统);
- 注意:可用性越高,架构复杂度和成本越高 ------ 不要盲目追求 "高可用"。
最后:技术学习的 "底层逻辑"
整理这些内容时,我最大的感悟是:技术不是 "堆组件",而是 "解决问题的工具"------ 从 Redis 到分布式架构,每一个方案都是为了应对 "性能不够、可用性不足、扩展性不够" 的问题。