Redis理解性总结

4 阅读17分钟

一、先从整体上看:Redis 在后端系统里到底扮演什么角色

如果只用一句最通俗的话来概括 Redis,那么可以这样说:Redis 是一个高性能的内存键值存储系统,同时也是一个内存数据结构服务。

第一,Redis 的数据主要放在 内存 里。
这意味着它访问速度非常快,因为内存比磁盘快得多。但这也意味着它不是一个“无限存储”的地方,内存贵,而且容量有限,所以 Redis 从设计上就不适合存放所有数据,它更适合存放那些“最值得快”的数据。

第二,Redis 是 key-value 型的。
也就是通常通过一个 key 去找到对应的 value。和 MySQL 那种“表、行、列、复杂 SQL、事务、多表关联”的模式不一样,Redis 更强调“快速、直接、高频”的读写访问。

第三,Redis 不只是“存字符串的缓存工具”。
它其实支持很多数据结构,比如 String、Hash、List、Set、ZSet 等,这使它不仅能存数据,还能方便地做计数器、排行榜、去重、限流、分布式锁等功能。所以更准确地说,Redis 既是缓存层,也是高性能数据结构工具箱。

从整个后端系统的视角看,Redis 的角色通常不是替代 MySQL,而是和 MySQL 分工协作:

  • MySQL 负责核心数据的长期、稳定、结构化存储
  • Redis 负责热点数据加速、临时状态存储、部分高并发能力支撑

可以理解为:MySQL 负责“存得住”,Redis 负责“跑得快”。

二、Redis 为什么会成为后端高频组件

Redis 之所以在后端开发里这么常见,是因为现代系统普遍都有这样几类需求:

  • 请求量很大,希望访问足够快
  • 热点数据很多,希望不要每次都查数据库
  • 有些状态数据变化频繁,适合放在内存里处理
  • 需要一些轻量但高性能的能力,比如计数、排序、去重、锁、限流

如果这些事情全交给 MySQL,也不是完全做不了,但代价会比较高。因为 MySQL 更擅长的是结构化存储、事务、一致性和复杂查询,不擅长承担所有高频简单读写的压力。

于是,Redis 就成了后端系统里非常自然的一层:

  • 对热点数据做缓存
  • 把高频读请求挡在前面
  • 降低 MySQL 压力
  • 提供一些关系型数据库不太擅长的高性能数据处理能力

所以 Redis 的价值,本质上是:加速

三、Redis 为什么快

原因一

它把数据主要放在内存里。

内存比磁盘快很多,所以当 Redis 读写数据时,不像磁盘型数据库那样需要频繁处理慢速磁盘 IO。这是 Redis 高性能的基础。

但如果只说“因为它在内存里”,其实还不够完整。Redis 快,不只是因为数据在内存中,还因为它整个系统设计都在尽量减少额外成本。

原因二

Redis 的操作模型很简单。

Redis 的很多操作本质上是:

  • 根据 key 直接取 value
  • 对某个数做自增
  • 对集合做增删查
  • 对排行榜按 score 排序

它不像 MySQL 那样,经常要走 SQL 解析、执行计划、索引选择、事务判断这些更重的路径。所以 Redis 不只是“取数据快”,而是“做事也比较直接”。

原因三

Redis 提供了多种高效的数据结构。

比如:

  • String 适合简单值和计数
  • Hash 适合对象字段
  • Set 适合去重
  • ZSet 适合排序和排行榜

它不是把所有问题都塞到一个通用容器里,而是根据不同业务提供了适合的数据结构,所以很多场景天然就能高效处理。

原因四

Redis 的核心命令执行路径采用了比较简洁的线程模型。

常见的说法是 Redis 单线程,但更准确地说,Redis 的核心命令执行路径通常是单线程串行处理的。这样做的好处是减少了锁竞争、线程切换和并发同步带来的额外成本。对于 Redis 这种“单次操作短、逻辑直接、内存访问快”的系统来说,这种设计反而很高效。

原因五

Redis 的网络事件处理也比较高效。

它可以在轻量的模型下处理大量连接,而不是每来一个请求就创建复杂线程模型去处理,这也减少了系统运行成本。

总结

Redis 快,不是因为某一个神奇点,而是因为它把“数据位置、操作模型、数据结构、执行路径、网络处理”这些环节都尽量做得更短、更轻、更直接。

四、Redis 的常见数据类型

很多人学 Redis 的数据类型时,容易变成背命令。但真正重要的不是命令,而是:看到一种业务需求时,你能不能想到对应的数据结构。

Redis 最常见的几种数据类型:

String 最基础也最通用的类型。

它适合存单个值、数字、JSON 字符串、序列化对象,也很适合做计数器,比如阅读数、点赞数、访问次数。很多缓存场景第一反应都可以先想 String。

Hash 更适合存对象。

比如用户信息、商品基础信息、配置信息等。如果一个对象有多个字段,而且你经常想单独读写其中某一个字段,那么 Hash 往往比把整个对象序列化成 String 更灵活。

List 适合维护有顺序、可重复的一组数据。

它常见于简单消息队列、最新消息列表、最近浏览记录等场景。它的核心特点不是去重,也不是排序分值,而是“有先后顺序”。

Set 适合“无序且不重复”的数据。

比如点赞用户集合、参加活动的用户集合、标签集合等。它特别适合去重、成员判断和集合运算。

ZSet 适合排序任务。

它是在 Set 的基础上,给每个元素再配一个 score,然后按 score 排序。所以它特别适合做排行榜、热度榜、活跃榜、优先级排序等场景。

所以学 Redis 数据结构的关键不是死记定义,而是形成一种条件反射:

  • 存单值、计数,用 String
  • 存对象字段,用 Hash
  • 要顺序列表,用 List
  • 要去重和成员判断,用 Set
  • 要排名和排序,用 ZSet

五、Redis 最核心的应用场景:缓存,以及它和 MySQL 的配合关系

Redis 在后端系统里最经典的身份,仍然是:缓存

缓存的本质,可以理解成一句话:把未来可能还会被重复访问的数据,提前放到一个更快的位置。

后端里之所以需要缓存,是因为大量业务请求都具有“热点访问”的特点。比如热门商品、热门文章、首页推荐、用户资料、热搜榜等,它们在短时间内会被很多用户反复读取。如果每次都直接查 MySQL,就会给数据库带来很大的压力。

所以 Redis 和 MySQL 的典型配合关系是:

  • MySQL 作为正式数据底座,存放核心业务数据
  • Redis 作为前置高速层,缓存热点数据副本

最经典的读取流程是:

  1. 请求先查 Redis
  2. 如果 Redis 里有,直接返回,这叫缓存命中
  3. 如果 Redis 里没有,再去查 MySQL,这叫缓存未命中
  4. MySQL 查到后,把结果回填到 Redis
  5. 后续请求再优先走 Redis

这套模式的核心价值在于:

  • 降低 MySQL 压力
  • 提高接口响应速度
  • 提升高并发场景下的系统承载能力

但你也必须意识到,缓存并不是白来的。因为一旦你把 MySQL 的一份数据又在 Redis 里存了一份副本,就会出现一个新的核心问题:Redis 和 MySQL 的数据,什么时候可能不一致?这就是缓存带来的工程复杂度。

所以 Redis 做缓存,其实是在用副本换性能,但也要承担副本一致性的管理成本。

六、缓存穿透、缓存击穿、缓存雪崩

这一组问题很高频,主要是是在考你有没有“缓存不是永远可靠的”这种系统意识。

这三者本质上都和一个问题有关:缓存层失去了原本对数据库的保护作用。

但三者失效的方式不同。

缓存穿透

请求的数据本来就不存在,所以 Redis 里没有,MySQL 里也没有。这样的话,请求每次都会绕过缓存直接打到数据库。如果这种请求很多,就会给数据库带来无谓压力。它的关键点是:查的是根本不存在的数据。

常见解决思路是缓存空值、布隆过滤器、参数校验等。

缓存击穿

某一个非常热点的 key,在某一时刻突然失效了,于是大量并发请求同时去查 MySQL。这通常发生在一个热点 key 过期的瞬间。它的关键点是:一个特别热的 key 突然没了。

常见解决思路是热点 key 不过期、互斥锁或分布式锁控制缓存重建、逻辑过期等。

缓存雪崩

大量 key 在同一时间一起失效,或者 Redis 整体不可用了,于是大批请求同时冲向数据库。它的关键点是:不是一个点破了,而是一大片一起出问题。

常见解决思路包括过期时间加随机值、缓存预热、Redis 高可用、应用层限流降级等。

总结

一句话区分三者:穿透是查不到,击穿是一个热点突然失效,雪崩是一大批缓存同时出问题。这三道题背后真正考察的是:你是否知道缓存系统也会出故障,以及出故障后数据库会承受什么后果。

七、Redis 的持久化,到底是在平衡什么

很多人一开始会觉得 Redis 是内存数据库,那数据不是应该都在内存里吗,为什么还要持久化?其实一点都不矛盾。Redis 把数据放在内存里,是为了快;而 Redis 做持久化,是为了在快的基础上尽量减少数据丢失风险。因为内存有一个天然特点:它是易失性的。

Redis 进程一挂、机器一断电、系统一重启,内存里的数据就可能消失。所以 Redis 需要持久化,把内存中的数据以某种方式保存到磁盘上,以便重启后恢复。

Redis 的两种主流持久化方式是:RDB 和 AOF

RDB

可以理解成“快照式持久化”。 它会在某个时间点,把当前 Redis 内存里的整体数据状态保存成一个快照文件。所以它更像是“定期拍一张全景照片”。它的优点是文件紧凑、适合备份、恢复通常比较直接;缺点是如果刚拍完快照后 Redis 就挂了,那么这之后的数据可能会丢失。

AOF 

可以理解成“操作日志式持久化”。 它不是保存某一刻的整体状态,而是把写操作按顺序记录下来。这样 Redis 重启时可以通过重新执行这些写命令来恢复数据。它更像“流水账”。它的优点通常是数据丢失窗口更小;缺点是文件可能越来越大,恢复时也可能要重放很多操作。

可以把两者理解成:

  • RDB 像存档快照
  • AOF 像操作日志

它们在性能、恢复速度、数据安全性之间做不同侧重点的平衡。很多工程场景里甚至会结合使用两者,而不是只用其中一个。

八、过期删除策略和内存淘汰策略

过期删除策略:

解决的问题是:已经设置过期时间的 key,到期了之后怎么处理。

Redis 支持给 key 设置 TTL,这是它很适合做缓存的重要原因之一。但 key 到期,不代表 Redis 一定会“秒删”。因为如果它要为每个 key 都维护一个精确到点就删除的定时任务,成本会很高。

所以 Redis 更现实的做法是组合处理:

  1. 惰性删除:访问某个 key 时,才顺手检查它是否过期,如果过期了就删除。
  2. 定期删除:Redis 后台会周期性抽查一部分设置了过期时间的 key,把已经过期的删掉。

这两者结合起来的意义在于:

  • 惰性删除省 CPU
  • 定期删除减少长期无人访问的过期 key 占用内存

内存淘汰策略:

解决的问题是:如果 Redis 内存真的不够用了,该牺牲谁。

注意,这时候有些 key 可能还没过期,但 Redis 还是装不下了。那么它就必须根据策略做选择:

  • 是直接拒绝写入
  • 还是删除一部分旧数据腾空间
  • 如果删除,删哪些

常见的理解思路有几类:

  • 不淘汰,直接报错
  • 只从设置过期时间的 key 中淘汰
  • 从所有 key 中淘汰
  • 按最近最少使用、最不经常使用或随机方式挑选

怎么区分这两个概念:过期删除看的是时间规则,内存淘汰看的是空间压力。一个是“该失效的数据怎么清”,另一个是“内存不够时不得不删谁”。

九、Redis 分布式锁

Redis 分布式锁和缓存是两种完全不同的使用思路。缓存是在讲性能,而分布式锁是在讲:多个服务实例同时处理某件事时,如何避免它们互相冲突。

在单机程序里,我们可以用本地锁控制多个线程;但在分布式系统里,请求可能落到不同机器、不同实例上,本地锁就管不住了。所以这时候需要一个所有实例都能看到的共享状态,来协调谁能执行、谁要等待。

Redis 之所以适合做分布式锁,是因为它满足几个关键条件:

  • 所有服务实例都能访问它
  • 性能高
  • 支持原子操作
  • 支持设置过期时间

Redis 分布式锁最基本的思路是:

  • 某个锁对应一个 key
  • 只有 key 不存在时,才能设置成功
  • 设置成功就表示拿到锁
  • 同时还要设置过期时间,防止持锁者崩溃后锁永远不释放

但真正难的地方不在“加锁”,而在异常情况下怎么保证正确。

最经典的坑有两个:

  1. 误删别人的锁

    如果服务 A 持有的锁超时过期了,服务 B 重新拿到了这把锁,这时 A 才执行完业务并去删除 key,就可能把 B 的锁误删掉。所以成熟实现不会只存一个简单值,而是会存一个唯一标识。释放锁时必须确认“现在这把锁还是不是我的”。

  2. 锁过期了,但业务还没执行完

    如果 TTL 太短,而业务执行时间太长,那么锁可能提前过期,其他请求就会再次拿到锁,导致同一段逻辑被并发执行。所以工程上常会考虑合理 TTL 或锁续期机制。

因此,Redis 分布式锁的真正理解应该是:它不是简单 set 一个 key,而是一套需要同时考虑加锁原子性、锁归属、自动过期、释放安全和异常场景的互斥机制。

十、Redis 的高可用:主从复制、哨兵、集群

单机 Redis 的问题主要有:

  • 单点故障
  • 容量有限
  • 读压力有限
  • 一旦维护或重启风险很高

所以 Redis 在线上系统中,需要从“一个点”升级为“一套更抗风险的系统”。

主从复制

它的核心是让主节点把数据同步给一个或多个从节点。这样做的价值是:

  • 数据有副本,降低单点风险
  • 可以由从节点分担读请求

所以主从复制偏向解决的是:副本备份和读扩展。但主从复制还不够,因为如果主节点挂了,谁来发现?谁来决定新的主节点是谁?谁来让客户端切换?答案是:哨兵

哨兵

哨兵 本身不是存数据的,它更像监控者和管理者。
它负责:

  • 监控主从节点状态
  • 判断主节点是否故障
  • 在主节点故障后完成自动故障转移

所以哨兵解决的是:主节点挂了之后,谁来组织自动切换。它是建立在主从复制之上的管理机制,不是平行替代关系。

再往后,如果系统继续变大,问题就不只是“主节点挂了怎么办”,而是:

  • 一台机器内存装不下了
  • 一个主节点写压力太大了

这时候就要考虑:集群。

集群

集群的核心思想是数据分片。也就是把不同数据分散到多个 Redis 节点上存储和处理,而不是所有数据都压在一个主节点上。这样就能实现:

  • 容量扩展
  • 性能扩展
  • 避免单机瓶颈

总结:

  • 主从复制:复制副本
  • 哨兵:管理和切换
  • 集群:分片和扩展

十一、完整主线

到这里,我们可以把 Redis 这一整部分重新用一条主线串起来。

在真实后端系统里,MySQL 很重要,但它不是专门用来处理所有高频、低延迟、热点数据访问的。于是 Redis 作为一个高性能内存系统,被放到 MySQL 前面或旁边,用来承担缓存、计数、排行、锁、临时状态存储等工作。

Redis 之所以能承担这些工作,是因为它快。而这个“快”来自于它把数据放在内存中、采用了简单直接的 key-value 操作模型、提供了高效的数据结构,并通过较轻的执行路径减少了额外开销。

当 Redis 进入实际业务后,它最典型的角色是缓存。它和 MySQL 配合,形成“先查 Redis、再查 MySQL、查到后回填 Redis”的经典模式。这种模式能明显降低数据库压力,但同时也引入了缓存穿透、击穿、雪崩,以及缓存与数据库一致性等问题。

再往后,为了让 Redis 不只是快,还能更稳,系统会考虑持久化,让内存数据尽量能在宕机后恢复;会考虑过期删除和内存淘汰,让有限的内存资源能被更合理地管理;还会利用 Redis 做分布式锁,解决分布式系统中的互斥问题。

最后,当 Redis 不再只是一个小组件,而是一个线上核心基础设施时,还需要进一步考虑高可用和扩展能力,于是就有了主从复制、哨兵和集群。

所以,Redis 这一整部分不是几道零散题,而是一条非常完整的系统设计链路:先解决快,再解决稳,再解决大。

十二、总结

Redis 在后端系统里,最核心的价值是为系统提供一层高性能的内存能力。它通过把热点数据和高频操作从磁盘型数据库中分流出来,大幅提升了系统的响应速度和并发承载能力。
同时,由于它支持多种数据结构,所以它不只是一个缓存组件,也常常承担计数、排行、去重、分布式锁等角色。但 Redis 并不是一个“越用越好”的万能工具,因为它的快来自内存,而内存是昂贵且有限的;它的缓存能力能换来性能提升,但也会引入一致性问题;它能做锁和高可用,但这些能力都有工程边界和设计成本。
所以真正学懂 Redis,是要知道:Redis 是在现代后端系统中,用来平衡速度、资源、可靠性和复杂度的一个关键组件。