Redis 为什么快

  1. 纯内存操作,避免磁盘 IO
  2. 使用了 IO 多路复用机制,无须等待一个慢连接的操作,可以高效的处理多个网络连接
  3. 单线程模型,避免了频繁的上下文切换

Redis 持久性

  1. AOF
    AOF 同步策略:
    1. always: 每执行一条命令就同步到磁盘,数据安全性最高,但性能较差。
    2. everysec: 每秒同步一次,在性能和数据安全性之间取得平衡。
    3. no: 由操作系统决定何时写入磁盘.
  2. RDB
    Redis 快照
    特点:
    1. 文件小,RDB 文件是压缩的二进制文件
    2. 恢复速度快,恢复数据时只需要加载一个文件

影响 Redis 性能的点

  1. 集合的全量查询和聚合操作(可考虑使用 scan 分批读取数据,在客户端操作)
  2. bigkey 删除,大量空间的释放会在内存重新分配时耗时
  3. 清空数据库,flushdb flushall 等,可考虑使用(flushdb async)来异步清空
  4. AOF 日志同步写
  5. 从库加载 RDB 文件
  6. 大量数据的写入会导致 hash 冲突,redis 使用的链式 hash 会导致操作变慢,为避免这个问题,使用了渐进式 hash

针对 big 可以问题的解决方案

如何避免

  1. 拆分 bigkey,将一个大的 key 拆分成多个小的 key
  2. 选择合理的数据结构
  3. 水平分片,将数据分配到多个 redis 实例

删除

  1. 使用 unlink 异步删除
  2. 渐进式删除,每次分批删除一部分,可以使用 scan,hscan,zscan 等

redis6.0 为什么引入多线程,不是已经有了 IO 多路复用吗

Redis 6.0 引入多线程的原因主要在于优化网络 IO 性能,而不是替代多路 IO 复用机制。简要来说:

1️. 多路 IO 复用(如 epoll)仍然承担着管理客户端连接和事件分发的核心工作,确保单线程模型带来的简单性和原子性;

2️. 多线程被引入后,用于并行处理网络数据的读写(如请求数据的读取与响应数据的发送),从而减少了数据在单线程处理时的瓶颈,尤其在处理大 value 或高并发大量数据传输时提升了吞吐量;

3️. 总体上:命令解析和执行依旧保持单线程来维护数据一致性,而多线程仅用于网络数据 IO 的辅助处理,二者协同工作,实现了性能和稳定性的平衡。

网络 I/O 并行化:

多个 I/O 线程: Redis 6.0 将网络请求的处理分配给多个 I/O 线程,每个线程负责处理一部分连接。
并行处理: 这样,多个客户端的请求可以并行处理,提高了网络 I/O 的吞吐量。
减少阻塞: 一个慢速的请求不会阻塞其他请求,提高了系统的整体响应速度。

Redis 循序渐进

为了防止单个实例宕机,引入主从。为了防止主库宕机无法提供服务,引入哨兵机制来实现主从切换。
为了防止哨兵宕机和误判,引入了哨兵集群。

为了在数据量过大时单机实例无法容纳或者性能下降的问题,引入切片集群,将数据分散到多个实例上。

Redis 变慢问题排查

  1. 是否阻塞性操作,key *命令,或同步删除 bigkey
  2. 是否开启了 AOF 日志并同步写
  3. 查看是否发生内存 swap,是否数据量太大导致了 swap,可以考虑增加物理内存

https://freegeektime.com/100056701/287819/

缓存淘汰策略

Redis7.0 的默认缓存淘汰策略是noeviction, 这意味着当 Redis 的内存使用量达到设置的最大值时,新的写入操作将会失败,而不是去主动淘汰旧的数据。

可通过命令设置其他的淘汰策略,如 LRU

config set maxmemory-policy volatile-lru

缓存更新策略

  1. Cache-Aside: 先更新数据库再删除缓存
  2. Read Through: 应用先查询缓存,如果缓存中没有数据,就查询数据库并写入缓存。如果缓存有数据就直接返回。
  3. Write Through: 应用先更新数据库,再更新缓存。缺点:缓存更新失败会导致数据一致性问题。可加入重试机制。
  4. Write Behind: 异步写回。应用先更新缓存,异步将更新操作写入消息队列,消费者从消息队列取更新操作写入数据库
  5. Write Around: 写绕过。写操作直接更新数据库。读操作先从缓存取,如果没有查询数据库并更新缓存。缺点:缓存更新滞后,导致数据一致性问题。

参考

Redis 核心技术与实战

Redis 多线程网络模型全面揭秘