Skip to content

Redis是什么?

Redis是一个基于内存的、单线程驱动的、可持久化的数据结构服务器。

Redis在微服务中的常见使用场景:

  • 缓存:加速数据查询,扛住读流量。
  • 分布式锁:用Redission 解决超卖、重复执行。
  • 排行榜/计数器:Sorted Set做实时排名,String做原子计数。
  • 轻量消息队列:List当简单队列,Stream当可靠消费队列。
  • 特征存储:AI场景下存向量、用户画像标签。

Redis为什么快?

  • 完全基于内存:没有磁盘IO瓶颈,读写都在纳秒级。
  • 单线程执行命令
    • 在Redis 6.0前,所有命令都在主线程串行执行,没有上下文切换、锁竞争等问题。瓶颈本身不在CPU,而在网络IO。
    • 在Redis 6.0后,引入多线程优化读写网络IO,但还是用单线程来执行命令。
  • IO多路复用:一种同步非阻塞的IO模型,允许单线程通过一个系统调用,同时监控多个文件描述符,当其中某些描述符就绪,内核会返回就绪列表,应用程序再逐个处理,而不会阻塞在某个未就绪的连接上。(好比一个柜员同时监控多位客户的状态,哪位客户准备好了,柜员就去处理。虽然是一个柜员,但柜员一直在工作)

Redis的数据结构

String

  • 数据结构:SDS(Simple Dynamic String)
    • SDS优点:二进制安全,O(1)获取长度、预分配空间减少内存重分配、惰性释放、杜绝缓冲区溢出。
  • 使用场景:缓存对象、计数器、分布式锁等。

List

  • 数据结构:双向链表,有序、可重复。支持左右压入弹出。
  • 使用场景:消息队列、最新列表、时间线。

Hash

  • 数据结构:键值对集合
  • 使用场景:存储用户属性、购物车。

Set

  • 数据结构:无序、不可重复的集合。
  • 使用场景:标签系统、共同好友、抽奖去重。

Sorted Set

  • 数据结构:有序集合,每个成员关联一个score,按score排序,成员唯一。
  • 使用场景:排行榜、延迟队列、带权重的实时队列。

Bitmaps

  • 数据结构:操作位数组。
  • 使用场景:签到、用户画像。

HyperLogLog

  • 数据结构:概率算法
  • 使用场景:基数统计。

Redis的数据过期策略

  • 惰性删除:数据被访问时,检查是否需要清理。
  • 定期删除:定时执行,随机抽取部分key检查是否需要清理。

Redis的数据淘汰策略

当内存满时,通过淘汰策略释放内存:

  • noeviction:拒绝写入。
  • allkeys-lru:所有key中,淘汰最近最少使用的。
  • volatile-lru:设置了过期的key中,淘汰最近最少使用的。
  • allkeys-lfu:所有key中,淘汰最不经常使用的。
  • volatile-lfu:设置了过期的key中,淘汰最不经常使用的。
  • volatile-ttl:设置了过期的key中,淘汰最接近过期时间的。
  • allkeys-random:所有key中,随机淘汰。
  • volatile-random:设置了过期的key中,随机淘汰。

Redis的数据持久化方式

  • RDB(Redis Database Backup):定时快照,二进制紧凑,恢复快,但可能丢失最后一次快照之后的数据。
    • 刷盘方式:fork子线程,将内存快照写入操作系统的页缓存,然后显式调用fsync()进行刷盘,同步到磁盘上。
  • AOF(Append Only File):顺序追加记录每个写命令,可通过重放AOF命令来恢复数据。
    • always:每条命令立即刷盘,由主线程执行。
    • everysec:每秒刷一次,由后台线程执行。
    • no:不主动刷盘,由OS决定。
  • 混合持久化:只在AOF重写时发生,子线程将当前内存数据用RDB形式写入AOF的文件开头,后续文件采用AOF追加写。
┌────────────────────┐
 │   RDB 二进制数据    │  ← 全量快照(重启时快速加载)
├────────────────────┤
│   增量 AOF 文本     │  ← 快照时刻之后的写命令
└────────────────────┘

Redis&数据库常见问题

缓存雪崩

  • 定义:某一时刻,大量缓存同时失效或不可用,导致大量请求直接打到数据库,使数据库压力骤增甚至崩溃。
  • 原因:大量缓存设置了相同的过期时间、缓存服务器宕机
  • 解决方式:
    • 缓存过期时间增加随机值:对设置的缓存过期时间增加一定的随机值,避免大量缓存同时失效。
    • 多级缓存:增加本地缓存,本地缓存没有时再查询分布式缓存。
    • 限流降级:在缓存失效时,限制对后端系统的请求速率,并提供可降级能力。

缓存穿透

  • 定义:查询一个缓存中不存在的数据,导致每次请求都查询数据库,使数据库压力变大。
  • 原因:用户请求的数据在缓存和数据库都不存在。
  • 解决方式:
    • 缓存空结果:对于查询结果为空的数据,也进行缓存,设置一个较短的过期时间。
    • 布隆过滤器:在缓存前增加布隆过滤器,快速判断请求是否可能存在,从而减少对数据库的压力。
    • 参数校验:对请求参数进行校验,过滤无效请求。

缓存击穿

  • 定义:某个热点数据在缓存过期的瞬间,大量请求访问该数据,导致请求直接打到数据库。
  • 原因:热点数据过期时,大量请求并发访问。
  • 解决方式:
    • 热点数据永不过期:对于热点数据设置为永不过期,通过后台异步更新缓存。
    • 提前更新缓存:在缓存即将过期时,提前触发缓存更新,确保缓存中的数据始终有效。
    • 互斥锁:在缓存失效时,通过加分布式锁的方式,只允许一个请求区加载数据并更新缓存。

Redis集群

主从复制:

  • 特点:读写分离
  • 数据分片:无
  • 故障转移:无
  • 适用场景:少量读扩展

哨兵模式:

  • 特点:监控节点状态、故障通知、自动故障转移。
  • 数据分片:无
  • 故障转移:有,当主节点故障时,哨兵会从 从节点 中选举新的主节点。
  • 适用场景:中小规模、高可用

集群模式:

  • 特点:水平扩展、自动分片、无中心架构。
  • 数据分片:有,默认16384个Slot,每个主节点负责一部分Slot。
  • 故障转移:有,当主节点故障时,自动从 从节点 选举新的主节点。
  • 适用场景:大规模分布式应用

Redis事务

Redis 事务提供了一种一次性、顺序性、排他性地执行多个命令的机制。它通过三个核心命令实现:

  • MULTI:开启事务。
  • EXEC:执行事务队列中的所有命令。
  • DISCARD:取消事务。
  • WATCH:乐观锁,监视一个或多个键,如果这些键在事务执行前被改动,则事务中断。

本质:命令的批处理 + 执行期间的隔离保证,但不会回滚。基本上被lua脚本替代。