目录
[一、Redis 简介:为什么它如此重要?](#一、Redis 简介:为什么它如此重要?)
[1.1 什么是 Redis?](#1.1 什么是 Redis?)
[1.2 为什么大家都爱用 Redis?](#1.2 为什么大家都爱用 Redis?)
[1.2.1 快得离谱](#1.2.1 快得离谱)
[1.2.2 不仅仅是 String](#1.2.2 不仅仅是 String)
[1.2.3 多面手](#1.2.3 多面手)
[二、Redis 系统化学习路线(从入门到深入)](#二、Redis 系统化学习路线(从入门到深入))
[2.1 环境搭建](#2.1 环境搭建)
[2.2 五大基础数据类型](#2.2 五大基础数据类型)
[2.2.1 String(字符串):最基础的万能贴纸](#2.2.1 String(字符串):最基础的万能贴纸)
[2.2.2 Hash(哈希):专属的档案袋](#2.2.2 Hash(哈希):专属的档案袋)
[2.2.3 List(列表):排队的长龙](#2.2.3 List(列表):排队的长龙)
[2.2.4 Set(集合):朋友圈的"圈子"](#2.2.4 Set(集合):朋友圈的"圈子")
[2.2.5 ZSet(Sorted Set / 有序集合):金牌排行榜](#2.2.5 ZSet(Sorted Set / 有序集合):金牌排行榜)
[2.3 通用命令](#2.3 通用命令)
[2.4 第一阶段小结](#2.4 第一阶段小结)
[3.1 持久化机制(重点)](#3.1 持久化机制(重点))
[3.1.1 RDB(Redis Database):给内存拍一张"全景快照"](#3.1.1 RDB(Redis Database):给内存拍一张"全景快照")
[3.1.2 AOF(Append Only File):事无巨细的"流水账本"](#3.1.2 AOF(Append Only File):事无巨细的"流水账本")
[3.1.3 RDB 与 AOF 核心对比](#3.1.3 RDB 与 AOF 核心对比)
[3.1.4 终极杀手锏:RDB + AOF 混合持久化](#3.1.4 终极杀手锏:RDB + AOF 混合持久化)
[3.2 内存管理与淘汰策略](#3.2 内存管理与淘汰策略)
[3.2.1 过期(Expiration)与淘汰(Eviction)的区别](#3.2.1 过期(Expiration)与淘汰(Eviction)的区别)
[3.2.2 核心算法:LRU vs LFU](#3.2.2 核心算法:LRU vs LFU)
[3.2.3 Redis 的 8 种内存淘汰策略](#3.2.3 Redis 的 8 种内存淘汰策略)
[3.2.4 实战:我该怎么选?](#3.2.4 实战:我该怎么选?)
[3.3 事务与 Pipeline](#3.3 事务与 Pipeline)
[3.3.1 Pipeline(流水线):极致的"快递打包"艺术](#3.3.1 Pipeline(流水线):极致的"快递打包"艺术)
[3.3.2 Redis 事务(MULTI / EXEC):排队打饭的"一锤子买卖"](#3.3.2 Redis 事务(MULTI / EXEC):排队打饭的"一锤子买卖")
[3.3.3 为什么说 Redis 事务"不支持强一致性的回滚"?](#3.3.3 为什么说 Redis 事务"不支持强一致性的回滚"?)
[3.3.4 终极护盾:WATCH(乐观锁)](#3.3.4 终极护盾:WATCH(乐观锁))
[3.3.5 总结对比:该用哪个?](#3.3.5 总结对比:该用哪个?)
[4.1 主从复制(Replication)](#4.1 主从复制(Replication))
[4.2 哨兵模式(Sentinel)](#4.2 哨兵模式(Sentinel))
[4.3 分片集群(Cluster)](#4.3 分片集群(Cluster))
[4.4 架构演进总结表](#4.4 架构演进总结表)
[5.1 缓存三大经典问题及解决方案](#5.1 缓存三大经典问题及解决方案)
[5.1.1 缓存穿透(Cache Penetration):查无此人的"夺命连环 Call"](#5.1.1 缓存穿透(Cache Penetration):查无此人的"夺命连环 Call")
[5.1.2 缓存击穿(Cache Breakdown):单点爆破的"巨星陨落"](#5.1.2 缓存击穿(Cache Breakdown):单点爆破的"巨星陨落")
[5.1.3 缓存雪崩(Cache Avalanche):集体大罢工的"末日灾难"](#5.1.3 缓存雪崩(Cache Avalanche):集体大罢工的"末日灾难")
[5.1.4 核心总结一张表](#5.1.4 核心总结一张表)
[5.2 Lua 脚本:真正的"绝对防御"](#5.2 Lua 脚本:真正的"绝对防御")
[5.2.1 为什么原生事务搞不定"秒杀"?(痛点回顾)](#5.2.1 为什么原生事务搞不定"秒杀"?(痛点回顾))
[5.2.2 Lua 脚本是什么?](#5.2.2 Lua 脚本是什么?)
[5.2.3 实战:一段完美的秒杀扣库存代码](#5.2.3 实战:一段完美的秒杀扣库存代码)
[5.2.4 现实世界的忠告:Lua 是把双刃剑](#5.2.4 现实世界的忠告:Lua 是把双刃剑)
[5.3 分布式锁:从单机思维跨越到分布式架构](#5.3 分布式锁:从单机思维跨越到分布式架构)
[5.3.1 什么是分布式锁?(一个抢厕所的比喻)](#5.3.1 什么是分布式锁?(一个抢厕所的比喻))
[5.3.2 Redis 原生分布式锁的"进化史"](#5.3.2 Redis 原生分布式锁的"进化史")
[5.3.3 Redisson 与它的"看门狗"(Watchdog)魔法](#5.3.3 Redisson 与它的"看门狗"(Watchdog)魔法)
[5.3.4 小结:分布式锁的三大铁律](#5.3.4 小结:分布式锁的三大铁律)
[6.1 第一面:缓存架构场景题(防不住就背锅)](#6.1 第一面:缓存架构场景题(防不住就背锅))
[6.2 第二面:底层机制原理题(懂机制才能救火)](#6.2 第二面:底层机制原理题(懂机制才能救火))
[6.3 第三面:分布式锁高阶实战题(写错就发错钱)](#6.3 第三面:分布式锁高阶实战题(写错就发错钱))
[7.1 完整知识图谱回顾](#7.1 完整知识图谱回顾)
[7.2 学习建议](#7.2 学习建议)
[7.3 进阶方向](#7.3 进阶方向)
Redis学习路线:从入门到精通完全指南
本文基于系统化学习Redis的完整路径,从基础概念到高阶架构,从单机部署到分布式集群,为你呈现一份详尽的Redis学习指南。无论你是刚接触Redis的新手,还是希望深入底层原理的进阶开发者,这篇文章都将帮助你建立完整的Redis知识体系。
一、Redis 简介:为什么它如此重要?
1.1 什么是 Redis?
Redis(Remote Dictionary Server) 是一个开源的、基于内存的键值对(Key-Value)数据结构存储系统。你可以把它想象成一个极其庞大且超级快的"字典"。通常的数据库(如 MySQL)是把数据存放在硬盘上的,而 Redis 把数据全都放在内存里。
Redis 是目前后端开发中最不可或缺的技术之一,无论你是做后端开发、系统架构还是应对性能优化,它都是一项"杀手锏"级别的技能。
1.2 为什么大家都爱用 Redis?
Redis 之所以如此受欢迎,主要有以下几个核心优势:
1.2.1 快得离谱
因为数据都在内存中,它的读写速度极快,单机轻松能达到每秒十万级别的并发读写。这种性能是传统磁盘数据库难以企及的。
1.2.2 不仅仅是 String
传统的缓存可能只能存字符串,但 Redis 支持非常丰富的数据结构,比如列表(List)、集合(Set)、哈希表(Hash)、有序集合(Sorted Set)等。这些数据结构让 Redis 能够应对各种复杂的业务场景。
1.2.3 多面手
它不仅能当缓存用(最常见的场景),还能当数据库、消息队列(Pub/Sub)、分布式锁等。这种多功能性使得 Redis 成为技术栈中不可或缺的一环。
二、Redis 系统化学习路线(从入门到深入)
为了让你不迷路,我们将 Redis 的学习分为四个阶段。我们可以一步一步来打通关:
第一阶段:初窥门径(基础与使用)
这个阶段的目标是:知道怎么把 Redis 跑起来,并且能熟练使用它最核心的"五种武器"。
2.1 环境搭建
在本地(Windows/Mac/Linux 或 Docker)安装并启动 Redis,连接 Redis 客户端(如 redis-cli 或可视化工具如 Another Redis Desktop Manager)。
2.2 五大基础数据类型
掌握了这五大基础数据类型,你就能应对日常开发中 80% 以上的 Redis 使用场景了。为了让你更容易理解,我们把 Redis 想象成一个"万能百宝箱"。
2.2.1 String(字符串):最基础的万能贴纸
这是 Redis 中最简单的数据类型。你可以把它想象成一张便利贴,上面写着一个名字(Key)和对应的一段话或数字(Value)。虽然叫"字符串",但它其实也可以存数字,甚至是一张图片的二进制数据。
生活化场景:文章阅读量计数器。每次有人点开文章,阅读量就加 1;或者手机验证码,发送后要求 5 分钟内有效。
命令演示:
java
# 场景 1:缓存一个验证码,并设置 60 秒后过期(EX:seconds)
SET user:1001:code "849201" EX 60
# 获取这个验证码
GET user:1001:code
# 返回:"849201"
# 场景 2:文章阅读量点赞计数
SET article:99:views 0
# 每当有人阅读,就让它自增 1
INCR article:99:views
# 返回:1
INCR article:99:views
# 返回:2
2.2.2 Hash(哈希):专属的档案袋
Hash 特别像一个档案袋或者编程语言里的对象(Object/JSON)。一个大 Key 对应着一个档案袋,里面可以装多个属性(字段 Field)和对应的值(Value)。
生活化场景:存储用户的个人资料(比如姓名、年龄、粉丝数)。如果用 String 存,你可能要把整个用户信息打包成一个长字符串;但用 Hash,你可以单独修改某一个属性,比如只修改他的粉丝数,而不影响其他信息。
命令演示:
java
# 把用户张三的信息存入档案袋(Key 为 user:1001)
HSET user:1001 name "ZhangSan" age 25 fans 100
# 单独获取张三的名字
HGET user:1001 name
# 返回:"ZhangSan"
# 张三涨粉了,给他的粉丝数加 1
HINCRBY user:1001 fans 1
# 返回:101
# 一次性查看张三的所有档案信息
HGETALL user:1001
# 返回:name, ZhangSan, age, 25, fans, 101
2.2.3 List(列表):排队的长龙
List 就是一个按顺序排列的字符串队伍。你可以从队伍的最前面(左边 Left)或者最后面(右边 Right)加入或减人。
生活化场景:排队系统或者社交媒体的最新动态(Timeline)。比如你关注的博主发了新微博,就把新微博塞到你的列表最前面,你一刷新就能看到最新的。
命令演示:
java
# 场景:记录公众号发布的最新文章 ID
# 左侧推入(LPUSH),相当于最新的文章排在最前面
LPUSH my_timeline "article_003"
LPUSH my_timeline "article_004"
LPUSH my_timeline "article_005"
# 查看最近发布的 2 篇文章(0 是第一个,1 是第二个)
LRANGE my_timeline 0 1
# 返回:"article_005", "article_004"
# 弹出最老的一篇文章(从右侧拿走并删除 RPOP)
RPOP my_timeline
# 返回:"article_003"
2.2.4 Set(集合):朋友圈的"圈子"
Set 是一个无序且不重复的元素集合。你往里面塞十个一样的东西,它也只会保留一个。而且它天生擅长做"交集、并集、差集"的数学运算。
生活化场景:抽奖系统(保证一个人只能中一次奖)、文章标签,或者最经典的"共同好友"(把你好友的 Set 和我的好友 Set 取交集)。
命令演示:
java
# 给文章打标签,重复添加 "tech" 也只会存一个
SADD article:100:tags "tech" "coding" "redis" "tech"
# 查看这篇文章的所有标签
SMEMBERS article:100:tags
# 返回:"coding", "tech", "redis"(注意:每次取出的顺序可能不同)
# 场景:共同好友
SADD user:A:friends "Tom" "Jerry" "Spike"
SADD user:B:friends "Tom" "Spike" "Tyke"
# 找出 A 和 B 的共同好友(交集 SINTER)
SINTER user:A:friends user:B:friends
# 返回:"Tom", "Spike"
2.2.5 ZSet(Sorted Set / 有序集合):金牌排行榜
ZSet 就像是 Set 的升级版,它不仅要求元素不能重复,还会给每个元素绑定一个分数(Score),并根据这个分数自动进行排序。
生活化场景:游戏积分排行榜、微博热搜榜、直播间打赏贡献榜。有了 ZSet,老板再让你做排行榜,简直就是手到擒来。
命令演示:
java
# 场景:游戏玩家分数排行榜,ZADD 后面跟的是 "分数 玩家"
ZADD game:leaderboard 1500 "PlayerA"
ZADD game:leaderboard 2100 "PlayerB"
ZADD game:leaderboard 1800 "PlayerC"
# 玩家 A 打赢了一局,加了 400 分
ZINCRBY game:leaderboard 400 "PlayerA"
# PlayerA 现在的分数变成 1900
# 查看排行榜前两名!(ZREVRANGE 是从大到小排,0 1 代表第一名和第二名)
ZREVRANGE game:leaderboard 0 1 WITHSCORES
# 返回:
# 1) "PlayerB"
# 2) "2100"
# 3) "PlayerA"
# 4) "1900"
2.3 通用命令
学会管理键值,比如 EXPIRE(设置过期时间)、DEL(删除)、KEYS(查找)等。
2.4 第一阶段小结
这就是 Redis 最基础也是最强大的"五大神器":
|----------|------------|
| 数据类型 | 核心用途 |
| String | 简单存取 / 计数 |
| Hash | 存对象 / 资料档案 |
| List | 队列 / 最新列表 |
| Set | 去重 / 共同好友 |
| ZSet | 排行榜优先选择 |
第三阶段:登堂入室(核心进阶功能)
掌握了基础用法后,需要了解 Redis 是如何保证数据不丢失以及如何处理复杂任务的。
3.1 持久化机制(重点)
Redis 是内存数据库,断电就没?不是的。它有 RDB(快照)和 AOF(追加文件)两种方式把数据保存到硬盘上。
3.1.1 RDB(Redis Database):给内存拍一张"全景快照"
你可以把 RDB 想象成照相机。每隔一段时间,Redis 就会给当前内存里所有的数据拍一张"快照",然后把这张照片保存成一个二进制文件(通常叫 dump.rdb)放在硬盘上。
它是怎么工作的? Redis 可以根据你的配置自动触发(比如"如果 5 分钟内有 100 个 Key 被修改了,就拍一次快照")。拍照时,Redis 主进程会克隆(Fork)出一个子进程,由子进程默默地把数据写到硬盘上,主进程继续飞速处理用户的请求,两不耽误。
优点:
- 恢复速度极快!因为它是紧凑的二进制文件,相当于直接把完整状态搬回内存,非常适合用来做定期备份和灾难恢复。
缺点:
- 容易丢一段数据。假设你设置了每 5 分钟拍一次快照,如果 Redis 在第 4 分钟的时候崩溃了,那这 4 分钟内新写入的数据就彻底丢失了。
3.1.2 AOF(Append Only File):事无巨细的"流水账本"
如果你数据的安全性要求极高,不能容忍丢失这几分钟的数据,那就要靠 AOF 了。你可以把 AOF 想象成一个记账本。
它是怎么工作的? 只要开启了 AOF,Redis 每执行一条会修改数据的命令(比如 SET、INCR),就会把这条命令的文本直接追加记录到 AOF 文件(appendonly.aof)的末尾。当 Redis 重启时,它只需要把这个账本从头到尾重新执行一遍,就能完全恢复数据。
优点:
- 数据极其安全。通常配置为"每秒同步一次",哪怕断电,最多也就丢失 1 秒钟的数据。
缺点:
- 文件体积膨胀得很快(毕竟连你把一个值加 1 再减 1 都会记录两条命令记录)。而且因为文件大、记录的全是命令,重启时一条条重新执行的恢复速度,远比不上直接加载 RDB 快照。
3.1.3 RDB 与 AOF 核心对比
为了让你看得更清晰,我们用一张表格来做个总结:
|--------|------------------|-----------------|
| 特性 | RDB(快照模式) | AOF(日志模式) |
| 工作原理 | 保存某个时间点的完整数据状态 | 记录每一条修改数据的命令 |
| 文件体积 | 小(紧凑的二进制) | 大(纯文本的命令日志) |
| 恢复速度 | 快(直接加载到内存) | 慢(需要一条条重新执行) |
| 数据安全性 | 较低(会丢失两次快照之间的数据) | 极高(最多丢失 1 秒的数据) |
| 系统资源消耗 | 拍照瞬间 CPU/内存开销大 | 持续的小规模磁盘 I/O 开销 |
3.1.4 终极杀手锏:RDB + AOF 混合持久化
聪明的你可能会问:"既然 RDB 恢复快,AOF 数据全,我能不能两个都要?"
答案是:必须能! 而且这也是目前的生产环境标配。
从 Redis 4.0 开始,官方推出了混合持久化。简单来说,它会在 AOF 文件重写的时候,把当前内存的完整状态先用 RDB 的格式写在文件开头,然后再把这之后产生的新增命令用 AOF 的格式追加在后面。这样一来,重启 Redis 时,先飞速加载前半段的 RDB 快照,再把后半段的 AOF 零星命令补齐。完美实现了"恢复快"与"不丢数据"的统一!
3.2 内存管理与淘汰策略
内存满了怎么办?了解 Redis 的键过期机制以及 8 种内存淘汰策略(如 LRU、LFU)。
3.2.1 过期(Expiration)与淘汰(Eviction)的区别
在聊淘汰策略之前,需要先理清一个很多人在面试和实际开发中容易混淆的概念:
过期(Expiration):这是你主动设置的。比如你规定一个验证码 5 分钟后失效(TTL)。时间一到,Redis 就会通过"惰性删除"(等你来查的时候发现过期了再删)或"定期删除"(Redis 后台时不时扫一圈,删掉一部分过期的)来清理它们。
淘汰(Eviction):这是被动触发的。当 Redis 的内存使用量达到了你配置的上限(maxmemory),哪怕所有数据都没过期,为了能装下新的数据,Redis 也必须狠心踢掉一些老数据。
3.2.2 核心算法:LRU vs LFU
要理解淘汰策略,最关键的是搞懂 Redis 用来评判"谁该被踢"的两种核心算法。
LRU(Least Recently Used - 最近最少使用):
-
判断标准:看的是"时间"。谁最久没有被访问过,就踢谁。
-
生活化比喻:就像整理衣柜,那件你整整三年都没穿过的衣服,最先被扔掉。哪怕你三年前天天穿它,只要最近没穿,它就得走人。
LFU(Least Frequently Used - 最不经常使用)(Redis 4.0 引入):
-
判断标准:看的是"频率"。在一段时间内,谁被访问的次数最少,就踢谁。
-
生活化比喻:还是整理衣柜。有一件衣服你昨天刚穿过一次(最近用过),但过去一年你总共也就穿了这一次;而另一件衣服你过去一年穿了 100 次。LFU 会选择扔掉那件只穿过一次的衣服,留下真正的高频"爆款"。
3.2.3 Redis 的 8 种内存淘汰策略
Redis 极其灵活,它把"从哪里挑数据(范围)"和"用什么算法挑(规则)"组合起来,一共提供了 8 种策略供你选择:
- 佛系策略(默认设置)
-
noeviction(不淘汰):内存满了?抱歉,我不踢任何人。如果有新的写入请求,我直接报错返回。 -
适用场景:当你把 Redis 当作绝对不能丢数据的纯数据库来用时。
- 从"所有数据"中挑选(allkeys- 系列)
这是最常用的场景,当你把 Redis 当作纯缓存时(通常不设置过期时间,全靠容量淘汰)。
-
allkeys-lru:把所有数据中最久没用过的踢掉。(最经典、最常用的缓存策略) -
allkeys-lfu:把所有数据中访问频率最低的踢掉。(适合需要精准保留"热点数据"的场景) -
allkeys-random:闭着眼睛在所有数据里随机踢一个。(极少使用,除非你的数据访问概率完全一样)
- 只从"设置了过期时间的数据"中挑选(volatile- 系列)
如果你既把 Redis 当缓存,又把它当数据库存了一些绝对不能丢的永久数据。那么你可以限制 Redis 只能去踢那些本来就带有寿命(TTL)的数据。
-
volatile-lru:在设置了过期时间的数据中,踢掉最久没用过的。 -
volatile-lfu:在设置了过期时间的数据中,踢掉访问频率最低的。 -
volatile-random:在设置了过期时间的数据中,随机踢。 -
volatile-ttl:在设置了过期时间的数据中,谁最快要过期了,就提前把它踢掉。
3.2.4 实战:我该怎么选?
不要被这 8 个名词吓到,在实际生产中,选择逻辑其实很简单:
如果你把 Redis 当作纯缓存,数据丢了可以去 MySQL 里重新查:
-
首选
allkeys-lru。绝大多数公司的默认选择,逻辑简单,效率高。 -
如果你的业务有非常明显的"头部热点"(比如微博热搜,只有极少数词条被疯狂访问),改用
allkeys-lfu效果会更好。
如果你的 Redis 里既有缓存,又有重要的业务数据(比如用户 Session、分布式锁,没设过期时间):
- 只能选
volatile-lru或volatile-lfu。这样 Redis 就只会在那些"早晚要死"的缓存数据里动刀子,绝对不会误删你的核心业务数据。
3.3 事务与 Pipeline
Redis 如何处理批量命令?虽然不支持像关系型数据库那样强一致性的回滚,但有自己的一套事务和流水线(Pipeline)机制来提升批量执行效率。
3.3.1 Pipeline(流水线):极致的"快递打包"艺术
痛点:Redis 处理命令的速度极快(微秒级),但网络传输是非常慢的。如果你要执行 1000 次 SET 命令,普通的做法是:发 1 条命令 → 等待 Redis 响应 → 再发第 2 条。这中间来回的网络延迟(RTT, Round Trip Time)积累起来,极其浪费时间。这就好比你搬 1000 块砖,每次只拿一块跑一趟。
这是什么? Pipeline 就像是一辆小推车。它允许客户端把这 1000 条命令打包,一次性发给 Redis 服务器;Redis 执行完后,把 1000 个结果也打包,一次性返回给客户端。
核心特点:
-
极度提升性能:省去了大量无谓的网络等待时间,批量操作的效率会有几十倍甚至上百倍的提升。
-
纯客户端技术:Pipeline 其实主要是客户端(比如 Java 的 Jedis/Lettuce,Python 的 redis-py)提供的一种优化手段,Redis 服务端只是配合接收而已。
-
注意(没有原子性):Pipeline 不管顺序,也不管中途有没有被别人插队。如果在这 1000 条命令执行期间,另一个用户也发来了一条命令,Redis 可能会在中间去执行那个用户的命令。
3.3.2 Redis 事务(MULTI / EXEC):排队打饭的"一锤子买卖"
如果你不仅需要批量执行,还需要这些命令连贯执行,中间绝对不能被别人插队,那就要用 Redis 事务了。
它主要依靠几个核心命令:
-
MULTI(开始事务):告诉 Redis,"我要开始点单了,接下来的命令先别执行,帮我记在小本本(队列)上"。
-
入队操作:你发送的一系列命令(如
SET、INCR),Redis 会统一回复QUEUED(已入队)。 -
EXEC(执行事务):告诉 Redis,"我点完了,按顺序给我一次性上菜!"。Redis 会锁定这个队列,一口气把它们全部执行完,期间任何其他客户端的命令都不能插队。
-
DISCARD(放弃事务):如果点单点到一半后悔了,发送
DISCARD,Redis 会清空刚才排队的命令,当作无事发生。
3.3.3 为什么说 Redis 事务"不支持强一致性的回滚"?
这是面试最高频的考点,也是颠覆很多人传统数据库认知的点。
在 MySQL 里,一个事务执行到一半报错了,前面成功的数据会自动回滚(Rollback),恢复到执行前的状态。但 Redis 是不回滚的!
Redis 的事务处理错误分为两种情况:
语法错误(排队时就发现):连坐,全部作废
如果你在打字时敲错了命令(比如把 SET 打成了 SSET),Redis 在入队(QUEUED)阶段就会报错。这时候如果你强行执行 EXEC,Redis 会直接拒绝,整个事务队列里所有的命令都不会执行。
运行错误(执行时才发现):尽力而为,谁错谁不管,对的继续执行
如果你语法没错,但是逻辑错了。比如你让一个正常的文字字符串去自增(对 "abc" 执行 INCR),在入队时 Redis 发现不了。等到 EXEC 真正执行时,到了这条命令会报错,但是!Redis 会忽略这个错误,继续执行队列里后面的其他命令。 前面已经执行成功的命令,也绝对不会回滚撤销。
为什么 Redis 这么"无情"? 官方给出的解释非常霸气且现实:
-
保持极速:回滚机制需要记录大量的历史状态,这极其消耗系统性能和内存,这与 Redis "简单快速"的底层设计哲学背道而驰。
-
错误只产生在开发阶段:运行时的逻辑错误(比如拿字符串去加减),通常是程序员写代码时的 Bug,这种 Bug 不应该带到生产环境中去用复杂的"回滚"来擦屁股。
3.3.4 终极护盾:WATCH(乐观锁)
有时候我们需要在事务执行前,确保某个数据没有被别人动过(比如秒杀扣库存,必须先确认库存还够不够)。这时候就需要用到 WATCH 命令。
用法:在 MULTI 之前,先执行 WATCH key(盯住这个 Key)。
效果:如果在执行 EXEC 之前,有其他客户端修改了这个被 WATCH 的 Key,那么这个事务在执行 EXEC 时就会直接失败(返回 null),相当于告诉你:"数据被别人抢先改了,你的操作作废了,请重试"。
这就叫乐观锁(CAS - Check And Set),非常轻量且高效。
3.3.5 总结对比:该用哪个?
|----------|-------------------|--------------------------------|
| 特性 | Pipeline(流水线) | Transaction(事务 MULTI/EXEC) |
| 核心目的 | 减少网络延迟,提高吞吐量 | 保证一组命令串行执行,不被插队 |
| 原子性(隔离性) | 无(会被其他客户端命令打断) | 有(执行期间绝对隔离,不被插队) |
| 错误处理 | 报错的失败,其他的继续 | 语法错全盘作废;运行错跳过,其余继续 |
| 是否回滚 | 否 | 否 |
第四阶段:融会贯通(高并发与高可用架构)
单机 Redis 扛不住了怎么办?这个阶段是系统架构师的必修课。
4.1 主从复制(Replication)
痛点:单台机器的读取能力到了极限(比如一秒钟几十万次读请求),如果让一台机器同时管读和写,它会累死。
这是什么? 我们引入"读写分离"的概念。设置一台核心机器作为主节点(Master / 老板),专门负责处理写请求(增删改)。然后给它配几个从节点(Slave / 员工),专门负责处理读请求。
怎么工作的? 老板(Master)每次把数据写到自己的账本上后,都会立刻复印一份(同步数据)发给所有的员工(Slave)。用户来查询数据时,直接找员工就行了。
优点:完美解决了"读请求"过多的问题,分摊了压力。
致命缺点:如果老板(Master)突然生病住院(宕机)了怎么办?员工们面面相觑,公司无法再接收任何写入请求,整个系统处于半瘫痪状态。直到程序员半夜被叫醒,手动去把某个员工提拔为新老板。
4.2 哨兵模式(Sentinel)
痛点:主从模式下,老板挂了需要人工干预,这在半夜发生绝对是灾难。我们需要系统能自动选出新老板。
这是什么? 为了解决单点故障,Redis 引入了"哨兵"(Sentinel)。你可以把哨兵想象成公司的"保安队"或者"董事会"。它们不负责存数据,只负责 24 小时盯着老板和员工。
怎么工作的?
-
监控:多个哨兵每秒钟都会给老板发送心跳包(问老板:"你还活着吗?")。
-
确认阵亡:如果一个哨兵发现老板没理它,它会怀疑老板挂了(主观下线)。接着它会去问其他哨兵,如果大多数哨兵都说"确实联系不上老板了",那就正式宣布老板阵亡(客观下线)。
-
自动选举(重点):董事会(哨兵们)立刻开会投票,从现有的优秀员工(Slave)中,根据谁的数据最新、网络最好,自动提拔他为新的老板(New Master)。
-
通知:哨兵把新老板上任的消息告诉所有人,并将原来的老板降级。等老老板病好(重启)回来,也只能乖乖当新老板的员工。
优点:实现了真正的高可用(HA)。就算拔掉主节点的网线,系统也能在几秒到十几秒内自动恢复,完全不需要人工干预。
致命缺点:不管你怎么选老板,始终只有一个老板在负责写数据,并且所有数据都必须装在这个老板的内存里。如果你的公司数据膨胀到了 1000GB,单台机器的内存根本塞不下怎么办?
4.3 分片集群(Cluster)
痛点:单台机器的内存容量有限(一般建议 Redis 单实例内存不超过 10-20GB),且单台机器的"写入并发"也到了极限。我们需要"横向扩容"。
这是什么? Redis Cluster 是 Redis 官方提供的终极分布式解决方案。既然一个老板管不过来,我们就设立多个老板(多 Master)!这就好比从一家单体公司,变成了拥有多个地区子公司的跨国集团。
怎么工作的?(哈希槽 Hash Slot 原理)
-
瓜分天下:Redis 集群引入了 16384 个哈希槽(Hash Slot) 的概念。假设我们有 3 个主节点(3 个老板),系统会把这 16384 个槽位平分给他们。
-
老板 A 负责槽位 0 - 5460
-
老板 B 负责槽位 5461 - 10922
-
老板 C 负责槽位 10923 - 16383
-
-
数据归属:当你想要存一个键值对(比如
SET user:1001 "张三")时,Redis 会对这个 Key(user:1001)进行算法计算(CRC16),算出一个数字,然后再对 16384 取模,得出的结果一定在 0~16383 之间。 -
精准定位:假设算出来的结果是 6000,系统一看,6000 属于老板 B 的管辖范围,就会把这条数据精准地存到老板 B 的机器上。
高可用保障:当然,每个老板(Master)背后依然会跟着几个员工(Slave)。如果老板 B 挂了,老板 B 的员工会自动顶上,完全不影响老板 A 和老板 C 的工作。
优点:完美解决了海量数据存储(内存不够加机器就行)和高并发写的瓶颈。这才是支撑大厂千万级并发的终极形态!
4.4 架构演进总结表
|----------|----------------|----------------------|
| 架构形态 | 核心解决的问题 | 适用场景 |
| 单机版 | 基础使用,快速读写 | 本地开发、微型项目 |
| 主从复制 | 读写分离,分摊读压力 | 读多写少,且允许人工恢复的场景 |
| 哨兵模式 | 自动故障转移(高可用) | 中型项目,数据量在一台机器内存承受范围内 |
| 分片集群 | 海量数据存储 + 超高并发写 | 大型互联网公司、双十一、秒杀、大促 |
第五阶段:深不可测(底层原理与生产实战)
这一阶段属于高阶面试必考题和解决实际生产事故的能力。
5.1 缓存三大经典问题及解决方案
这"缓存三剑客"(缓存穿透、缓存击穿、缓存雪崩)绝对是后端开发的必修课。不仅面试官几乎必问,而且在真实的双十一、秒杀等高并发场景中,如果没有防住它们,你的数据库(比如 MySQL)可能会瞬间被流量打崩,导致整个系统瘫痪。
5.1.1 缓存穿透(Cache Penetration):查无此人的"夺命连环 Call"
这是什么? 正常情况下,用户的请求先找 Redis,找不到再去查 MySQL,查到了再写回 Redis。但是,如果有人(比如黑客)故意大量请求一个根本不存在的数据(比如 ID 为 -1 的用户,或者一个早就下架的商品)。结果就是:Redis 里肯定没有 → 只能去查 MySQL → MySQL 里也没有 → 没法写回 Redis。这样一来,Redis 形同虚设,所有的压力都直接穿透到了脆弱的数据库上。
怎么防住它?(解决方案)
-
缓存空对象(简单粗暴):就算 MySQL 里没查到,我也在 Redis 里存一个
Key = -1,Value = null,并设置一个较短的过期时间(比如 1 分钟)。下次他再查 -1,Redis 直接返回 null,保住了 MySQL。 -
布隆过滤器(Bloom Filter)(高端局必备):在请求到达 Redis 之前,先加一道"超级安检门"。布隆过滤器是一种极其节省内存的数据结构,它可以极快地判断"某个数据大概率存在,或者绝对不存在"。如果安检门说这个 ID 绝对不存在,直接拦截请求,连 Redis 都不用去。
5.1.2 缓存击穿(Cache Breakdown):单点爆破的"巨星陨落"
这是什么? 注意它和"穿透"的区别。击穿针对的是"热点 Key"(比如微博上突然爆出一个超级大瓜,千万人在同时刷这一个词条)。这个热点 Key 一直在 Redis 里扛着成千上万的并发。但是,就在这个 Key 过期的那一瞬间,刚好有 1 万个并发请求打过来。这时候 Redis 里没数据了,这 1 万个请求发现缓存没命中,会同时冲向 MySQL 去查数据并试图重建缓存。MySQL 瞬间被这 1 万个相同的并发请求"击穿"而宕机。
怎么防住它?(解决方案)
-
互斥锁(Mutex Lock / 分布式锁):发现缓存失效时,不要让 1 万个请求都去查数据库。谁先跑到,谁就拿到一把"锁"。拿到锁的 1 个请求去查 MySQL 并重建 Redis 缓存。剩下 9999 个请求就在外面等着(休眠重试),等第一个人把缓存建好了,大家直接读缓存即可。
-
逻辑过期(永不过期):对于这种超级热点的数据,我们在 Redis 里根本不设置真实的过期时间(TTL),而是在它的 Value 里多存一个"过期时间"字段(比如
{"data": "热搜内容", "expire_time": "2026-03-21 15:00"})。每次读取时,程序自己判断有没有过期。如果过期了,直接把老数据返回给用户(牺牲一点点数据一致性),并在后台悄悄开一个线程去 MySQL 拉取新数据更新缓存。
5.1.3 缓存雪崩(Cache Avalanche):集体大罢工的"末日灾难"
这是什么? 击穿是"一个"热点 Key 过期,而雪崩是"一大批" Key 在同一时间集体过期,或者干脆是 Redis 服务器直接宕机了。这时候,海量的请求发现 Redis 里空空如也,全部像雪崩一样压向数据库,MySQL 连悲鸣都来不及就直接挂了。
怎么防住它?(解决方案)
-
TTL 加随机值(防集体过期):在给一大批缓存(比如首页推荐商品)设置过期时间时,不要全部设置为绝对的 1 小时。而是
1 小时 + 随机的 1~5 分钟。把失效时间打散,避免它们在同一秒集体大罢工。 -
Redis 高可用集群(防宕机):如果是 Redis 挂了导致的雪崩,那就必须搭建主从复制、哨兵模式或 Cluster 集群,保证哪怕坏了一台机器,Redis 也能继续提供服务。
-
服务降级与限流(最后的底线):如果雪崩真的发生了,在业务代码(比如微服务网关)里做限流。比如一秒钟只放 2000 个请求进来,多余的直接返回"系统繁忙,请稍后再试",宁愿牺牲部分用户体验,也要保住核心数据库不死。
5.1.4 核心总结一张表
|----------|---------------|-----------------|---------------------|
| 经典事故 | 核心原因 | 针对目标 | 主流解决方案 |
| 缓存穿透 | 请求根本不存在的数据 | 恶意攻击 / 爬虫狂刷 | 缓存空值、布隆过滤器 |
| 缓存击穿 | 单个热点数据突然过期 | 爆款商品 / 突发热搜 | 互斥锁、逻辑过期 |
| 缓存雪崩 | 大量数据同时过期 / 宕机 | 首页缓存批量失效 / 节点故障 | 过期时间加随机值、高可用架构、限流降级 |
5.2 Lua 脚本:真正的"绝对防御"
5.2.1 为什么原生事务搞不定"秒杀"?(痛点回顾)
想象一个极其经典的秒杀场景:仓库里只有 1 部 iPhone(库存 = 1),但有 1000 个人同时点下了购买按钮。
如果不用 Lua,你可能会这么写代码逻辑:
-
查库存:
GET iphone_stock(发现库存是 1) -
判断逻辑:如果库存 > 0,允许购买。
-
扣库存:
DECR iphone_stock(变成 0)
灾难发生了(超卖):因为这三步是分开执行的。在这 1000 个人并发请求时,极大概率会有 10 个人同时执行了第一步,他们看到的库存都是 1。然后程序判断都允许购买,最后 10 个人都执行了 DECR,库存变成了 -9。老板要赔惨了!
前面提到的 WATCH(乐观锁)虽然能防止别人插队,但在秒杀这种 1000 人抢 1 个商品的极端并发下,999 个人都会因为数据被别人修改而频繁报错重试,这会导致服务器压力巨大,甚至雪崩。
5.2.2 Lua 脚本是什么?
Lua 是一种极其轻量级的脚本语言。Redis 内置了 Lua 解析器,允许客户端把一段包含复杂逻辑的 Lua 代码直接发送给 Redis 服务端执行。
为什么它能实现真正的原子性? Redis 处理命令的核心逻辑是单线程的。当 Redis 开始执行一段 Lua 脚本时,它会把这整个脚本视为"一个巨大且不可分割的超级命令"。在脚本执行完毕之前,任何其他客户端发送的命令都必须在门外排队等着。绝对不可能出现"查完库存还没来得及扣,别人就插队进来了"的情况。
5.2.3 实战:一段完美的秒杀扣库存代码
使用 Lua 脚本,我们可以把"查库存 → 判断 → 扣库存"这三步,打包成一个绝对原子的操作。
这是一段经典的扣库存 Lua 脚本:
java
-- KEYS[1] 代表商品的库存 Key(比如 "iphone_stock")
-- ARGV[1] 代表这次想要购买的数量(比如 1)
-- 1. 先查出当前库存
local current_stock = tonumber(redis.call('GET', KEYS[1]))
-- 2. 如果库存查不到,或者库存已经为 0,直接返回 0(代表失败)
if current_stock == nil or current_stock == 0 then
return 0
end
-- 3. 判断库存够不够扣
if current_stock >= tonumber(ARGV[1]) then
-- 4. 如果够扣,执行扣减动作
redis.call('DECRBY', KEYS[1], ARGV[1])
return 1 -- 返回 1 代表扣减成功
else
-- 5. 如果不够扣,返回 0 代表失败
return 0
end
怎么使用它? 你只需要在 Java、Python 或 Go 的代码中,将这段文本传给 Redis 的 EVAL 命令去执行即可。Redis 会在一瞬间把这段逻辑跑完,要么成功返回 1,要么失败返回 0,干脆利落,绝不超卖!
5.2.4 现实世界的忠告:Lua 是把双刃剑
虽然 Lua 脚本极其强大,但在真实的生产环境中,作为一名资深开发者,必须给你提个醒:
绝对不要在 Lua 脚本里写耗时的逻辑! 刚才说了,Lua 脚本执行时,会阻塞其他所有的 Redis 命令。如果你在脚本里写了一个复杂的循环,或者脚本执行时间超过了哪怕几毫秒,整个 Redis 就会处于"假死"状态。所有依赖 Redis 的其他业务都会被卡住,这在生产环境中是致命的事故。
最佳实践:脚本要极其精简,只处理必须保证原子性的极短逻辑(比如上面的加减判断),千万别把它当成重型计算引擎来用。
5.3 分布式锁:从单机思维跨越到分布式架构
5.3.1 什么是分布式锁?(一个抢厕所的比喻)
你可以把分布式系统想象成一个有几十个部门(微服务实例)的大公司,但公司只有一把公共厕所的钥匙。
-
抢锁:谁先拿到这把钥匙(在 Redis 里写入一个特定的 Key),谁就能进去办事(执行业务逻辑)。
-
互斥:在他把钥匙还回来(删除 Key)之前,其他人就算把门敲烂,也只能在外面排队等着。
5.3.2 Redis 原生分布式锁的"进化史"
最初,大家是手写 Redis 命令来实现分布式锁的,但这里面踩过无数的坑。
初代版本:SETNX(Set if Not eXists)
这是 Redis 实现锁的最核心命令。意思是:如果这个 Key 不存在,我才能设置成功(返回 1,代表加锁成功);如果已经存在,我就设置失败(返回 0,代表别人锁了)。
java
# 机器 A 尝试加锁
SETNX lock:iphone 1 # 返回 1,拿到锁了!
# 机器 B 尝试加锁
SETNX lock:iphone 1 # 返回 0,有人在用,拿锁失败!
致命缺陷(死锁):如果机器 A 刚拿到锁,突然宕机(死机)了,没来得及执行删除锁的命令(DEL)。这把锁就永远留在了 Redis 里,其他机器再也拿不到锁,整个业务彻底卡死。
进化版本:加上过期时间(TTL)
为了防止死锁,我们必须给锁加一个"自动销毁"的时间。即使机器 A 宕机了,时间一到,Redis 也会自动把锁删掉。
java
# 把加锁和设置过期时间合并成一条原子命令(极其重要!)
SET lock:iphone "机器A的专属ID" NX PX 10000
# NX:不存在才设置
# PX 10000:10秒后自动过期
新的缺陷(锁被误删):假设机器 A 的业务逻辑很复杂,执行了 15 秒。但在第 10 秒的时候,锁已经自动过期了!此时,机器 B 趁机拿到了锁开始执行逻辑。到了第 15 秒,机器 A 执行完了,它去 Redis 里执行 DEL 命令,结果一不小心把机器 B 刚加的锁给删了!整个系统又乱套了。
5.3.3 Redisson 与它的"看门狗"(Watchdog)魔法
为了解决"业务没执行完,锁却提前过期了"这个世界级难题,大厂们通常不会自己手写原生 Redis 锁,而是直接引入企业级开源框架------Redisson。
Redisson 最牛的核心机制,就是一个叫做"看门狗(Watchdog)"的后台线程。
看门狗是怎么工作的?
-
自动续期:当你用 Redisson 加锁成功后,它不仅会设置一个默认的过期时间(比如 30 秒),还会默默在后台启动一只"看门狗"线程。
-
定时巡逻:这只看门狗每隔一段时间(通常是过期时间的三分之一,即 10 秒),就会去检查一下:"主人的业务代码还在运行吗?"
-
无限续杯:如果业务还在运行,看门狗就会自动向 Redis 发送一条命令,把锁的过期时间重新延长回 30 秒。只要你的业务没执行完,看门狗就会一直帮你"续杯",绝对不会出现锁提前失效的问题。
-
安全释放:当业务正常执行完毕,程序主动释放锁,看门狗也就光荣下班了。
-
防宕机死锁:万一拿到锁的机器突然宕机了,看门狗线程也会随之死亡,不再续期。30 秒后,锁自然过期,其他机器就能正常抢锁,完美避免了死锁!
除此之外,Redisson 的释放锁逻辑,底层用的正是我们上一节学过的 Lua 脚本。它通过 Lua 脚本原子性地判断:"这把锁到底是不是我加的?如果是,我才删除。"这就彻底解决了"误删别人锁"的问题。
5.3.4 小结:分布式锁的三大铁律
经过上面的推演,一个完美的分布式锁必须具备三个条件:
-
互斥性:任何时刻只能有一个客户端持有锁(依靠
SET NX)。 -
防死锁:客户端宕机也能自动释放(依靠过期时间 TTL)。
-
安全性:加锁和解锁必须是同一个人,且不能提前失效(依靠 Lua 脚本 + Redisson 看门狗)。
六、大厂面试实战模拟
6.1 第一面:缓存架构场景题(防不住就背锅)
场景:今晚双十一零点,我们有一个全网预热很久的超级爆款商品(热点 Key)。不巧的是,这个 Key 的过期时间刚好在 00:00:01 到期了。就在这一瞬间,10 万个用户的查询并发直接打过来,发现 Redis 里没数据。
问题:
-
这种现象在行业内叫什么?
-
如果这 10 万个请求同时冲向 MySQL,数据库肯定秒挂。你会用什么具体的技术手段和代码逻辑来拦截这 10 万个请求,只让 1 个请求去查数据库?
标准答案:
-
现象名称:这叫缓存击穿(Cache Breakdown)。特指"单个热点 Key"在过期瞬间,遭遇海量并发请求,导致请求穿透到数据库。
-
解决方案(互斥锁 / 分布式锁):遇到这种情况,绝对不能让 10 万个请求一起去查数据库。我会用互斥锁来控制并发,具体代码逻辑如下:
-
第一步(查缓存):10 万个请求同时查 Redis,发现没数据。
-
第二步(抢锁):10 万个请求同时尝试在 Redis 里加一把锁(比如用
SETNX或者 Redisson 的tryLock)。 -
第三步(只有 1 个幸运儿):Redis 单线程的特性保证了这 10 万个请求中,只有 1 个请求能抢到锁。
-
第四步(拿锁者建缓存):抢到锁的这 1 个请求,去查 MySQL 数据库,查到数据后写回 Redis 缓存,最后释放这把锁。
-
第五步(剩下 99999 人等待):没抢到锁的请求,让它们休眠一小会儿(比如 50 毫秒),然后重新执行第一步。此时它们再去查缓存,就会发现刚刚那 1 个人已经把数据放进 Redis 了,直接读取缓存即可。完美保住了 MySQL!
-
6.2 第二面:底层机制原理题(懂机制才能救火)
场景:昨天凌晨,咱们机房的某台核心 Redis 服务器突然断电宕机了。你作为负责人,虽然开启了 AOF 保证了数据几乎没丢,但因为 AOF 文件已经膨胀到了 50GB,Redis 重启时一条条回放命令,花了整整 20 分钟才恢复服务,老板非常生气!
问题:我不允许降低数据的安全性(不能单纯切回容易丢数据的 RDB),但我要求你必须让这台 Redis 在几十秒内极速重启并恢复所有数据。你会怎么向我抛出你的优化方案?
标准答案:
核心方案:开启 Redis 4.0 引入的杀手锏------RDB + AOF 混合持久化。
原理解析:单纯的 AOF 文件全是文本命令,重放确实慢;单纯的 RDB 是快照,虽然快但容易丢数据。混合持久化将两者完美结合:
-
当开启混合持久化后,Redis 在进行 AOF 重写(压缩文件体积)时,会把当前内存里的全量数据,以 RDB 快照(紧凑的二进制格式)的形式写在 AOF 文件的开头。
-
在 RDB 快照写入期间,新产生的零星修改命令,依然以 AOF(文本格式)的形式追加在文件末尾。
最终效果:当 Redis 宕机重启时,它会先飞速加载文件前半部分的 RDB 二进制数据,瞬间恢复 99% 的数据;然后再执行后半部分那一丁点 AOF 命令,补齐剩下的 1% 数据。既保证了像 AOF 一样不丢数据,又实现了像 RDB 一样的极速重启。
6.3 第三面:分布式锁高阶实战题(写错就发错钱)
场景:你的业务系统部署了 50 台机器,你用 Redis 的 SET key value EX 10 NX 写了一个分布式锁,给锁加了 10 秒的超时时间,防止机器宕机导致死锁。但是现在线上出了个大 Bug:某台机器抢到锁后,因为网络严重卡顿,业务代码执行了 15 秒。也就是说,在第 10 秒的时候,锁已经自动失效了,第二台机器趁虚而入抢到了锁。更要命的是,第一台机器在第 15 秒执行完业务去释放锁时,把第二台机器的锁给误删了!
问题:别跟我说"把过期时间设置成 30 秒"这种治标不治本的话。我要你从底层逻辑上彻底解决"锁提前过期"和"误删别人锁"这两个致命缺陷,说出你的终极方案!
标准答案:
这道题直击分布式锁的最痛点。我的终极方案是引入类似 Redisson 框架的底层逻辑,分两步彻底解决:
- 解决"误删别人锁":唯一标识 + Lua 脚本
-
加锁时:不能简单地写
SETNX lock 1,而是要把 Value 设置成当前机器和线程的唯一标识(比如UUID + ThreadID)。 -
解锁时:必须使用 Lua 脚本。解锁分两步:先判断 Redis 里的 Value 是不是我自己的标识,如果是,才执行
DEL删除。因为 Lua 脚本在 Redis 中是原子执行的,所以"判断"和"删除"中间绝不会被别人插队,彻底杜绝了误删别人的锁。
java
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
- 解决"锁提前过期":Watchdog(看门狗)机制
-
我不会写死一个极长的过期时间(比如 300 秒),这不合理。
-
我会设置一个相对较短的默认过期时间(比如 30 秒),同时在后台启动一个"看门狗"守护线程。
-
这个看门狗会每隔 10 秒(过期时间的 1/3)去检查一下:这把锁还在不在?当前的业务逻辑执行完了吗?
-
如果业务还没执行完,看门狗就会自动向 Redis 发起命令,把这把锁的过期时间重新"续杯"回 30 秒。只要业务不死,锁就永远不过期;一旦机器意外宕机,看门狗也跟着死了,锁在 30 秒后自然释放,绝生死锁。
七、总结与展望
7.1 完整知识图谱回顾
恭喜你!从基础数据结构、持久化、淘汰策略、缓存三大坑,再到最高阶的集群架构和分布式锁,你的 Redis 核心知识图谱已经彻底点亮了!
让我们回顾一下完整的知识架构:
第一阶段:基础入门
-
五大基础数据类型:String、Hash、List、Set、ZSet
-
通用命令:EXPIRE、DEL、KEYS 等
第二阶段:核心进阶
-
持久化机制:RDB、AOF、混合持久化
-
内存淘汰策略:8 种策略(LRU、LFU 等)
-
事务与 Pipeline:MULTI/EXEC、WATCH、Pipeline
第三阶段:高可用架构
-
主从复制(Replication)
-
哨兵模式(Sentinel)
-
分片集群(Cluster)
第四阶段:生产实战
-
缓存三大问题:穿透、击穿、雪崩
-
Lua 脚本实现原子操作
-
分布式锁与 Redisson
7.2 学习建议
-
循序渐进:不要试图一次性掌握所有内容。建议按照四个阶段逐步学习,每个阶段都要配合实践项目来巩固。
-
动手实践:Redis 是一个实践性很强的技术。建议在学习过程中搭建本地环境,亲自执行各种命令,观察效果。
-
深入源码:当你掌握了基本使用后,可以尝试阅读 Redis 的源码,深入理解其底层实现原理。
-
关注社区:Redis 社区非常活跃,关注官方博客和 GitHub 仓库,及时了解新特性和最佳实践。
7.3 进阶方向
掌握了 Redis 之后,你还可以继续深入学习以下相关技术:
-
MySQL:索引原理、锁、事务
-
消息队列:Kafka、RabbitMQ
-
分布式系统:一致性算法、分布式事务
-
云原生:Docker、Kubernetes
八、结语
Redis 作为现代后端开发的核心组件,其重要性不言而喻。从简单的缓存工具到复杂的分布式系统基石,Redis 的发展历程体现了技术的不断演进。
通过本文的系统化学习,相信你已经建立了完整的 Redis 知识体系。记住,技术学习是一个持续的过程,保持好奇心和实践精神,你一定能在技术的道路上走得更远。
祝你学习愉快,早日成为 Redis 高手!
本文内容基于系统化 Redis 学习路线整理,涵盖了从入门到精通的完整知识体系。如有任何问题或建议,欢迎留言交流。
