likes
comments
collection
share

一文搞懂Redis的核心原理

作者站长头像
站长
· 阅读数 20

redis是一个开源高性能KV数据库,在各大互联网公司都有广泛的使用,常常被用来做业务缓存、排行榜、粉丝列表、关注列表等业务场景。本文想用较为通俗的语言,对其设计的核心原理进行讲解

Redis工作流程浅析

Redis是单线程的处理数据(Redis6.0之后引入了多线程,但仅仅对于网络数据的收发使用多线程,数据的处理仍旧是单线程)。基于epoll模式监听多个fd,实现IO多路复用。当fd数据就绪时,通过epoll_wait函数检测,并进行相应的数据处理。

一文搞懂Redis的核心原理 redis的核心处理流程可以简单的概括为下面几步

  1. 注册事件监听及回调函数;
  2. 循环等待获取事件并处理;
  3. 调用回调函数,处理数据逻辑;
  4. 回写数据给 Client;

核心技术

事件循环

一文搞懂Redis的核心原理

1. 文件事件

处理连接的创建与销毁,通过IO多路复用接受连接请求,接收数据,并回写数据到客户端

2. 事件处理

进入eventloop阶段,等待请求数据到达,并请求数据的处理,操作数据的增删改查

3. 定时事件

通过非精确定时的方式,检查是否有到期的定时事件,并处理定时事件,常见的定时事件包括以下几种

  • 更新服务器统计信息,如内存占用、命中率等
  • 数据库后台操作,过期key清理、数据库rehash等
  • 关闭、清理失效的客户端连接
  • 检查是否需要RDB dump,AOF重写
  • 主节点,对从节点定期同步
  • 集群模式,集群定期同步信息和连接测试

4. beforeSleep

在进入下一轮eventloop之前需要进行一些必要的检查操作,我们称之为beforeSleep,具体可能包含以下几种:

  • cluster集群状态检查
  • 处理被block住的的客户端
  • 将AOF buffer持久化到AOF文件

一些建议

因为redis的事件处理流程是单线程的,尽量避免大key等阻塞事件处理,从而影响redis服务端工作效率

数据过期&内存淘汰

数据过期

当某个key到达TTL时间后,该key过期失效

  1. 惰性删除:每次读、写数据时,需要首先判断数据是否过期,若数据过期,则进行删除

  2. 定期删除:每隔一定的时间,redis随机取出部分的key,进行过期判断,若数据过期,则进行删除

实现

  1. redis的TTL并不是精确的过期,定时删除,不会判断所有的key,而是随机取部分key
  2. 该过程发生在定时事件阶段,该过程为阻塞事件

一些建议

尽量打散数据的过期时间,避免大量数据同时过期,从而影响事件循环的效率。

# 可以通过INFO命令查询到expire相关的状态
# Stats
expired_keys:1636641 #过期key总数
expired_stale_perc:0.43 #过期的key比率,抽样数据中的 过期key数量/样本key数量
expired_time_cap_reached_count:0 #过期数据处理超时计数,过期数据处理不能无限阻塞,阻塞超过一定时间后会释放,并且该计数+1
expire_cycle_cpu_milliseconds:747444 #阻塞CPU时间

内存淘汰机制

redis的内存淘汰机制有以下几种类型:

  1. noeviction: 当内存不足时,新写入操作会报错;即不淘汰内存
  2. allkeys-lru:当内存不足时,移除最近最少使用的key
  3. allkeys-random:当内存不足时,随机移除某个 key
  4. volatile-lru:当内存不足时,在设置了过期时间的键空间中,移除最近最少使用的key
  5. volatile-random:当内存不足时,在设置了过期时间的键空间中,随机移除某个key
  6. volatile-ttl:当内存不足时,在设置了过期时间的键空间中,更早过期时间的key优先移除

实现

  1. 内存淘汰不是精准的淘汰,而是随机抽样部分数据,对抽样的数据进行淘汰
  2. 在每次写入操作前进行判断
  3. 该过程为阻塞请求

一些建议

关注redis统计信息中的逐出QPS,如果过高会影响正常的请求

# 可以通过INFO命令查询到evicted相关的状态
# Stats
evicted_keys:0 #逐出key计数

持久化

RDB持久化(全量持久化,线上不常用)

  1. save命令,同步持久化,阻塞主进程
  2. bgsave命令,fork子进程进行持久化,fork进程瞬间阻塞主进程
  3. 持久化为压缩的二进制文件

AOF持久化(增量持久化,线上常用,可恢复数据时间粒度一般较小)

  1. AOF持久化保存数据操作命令
  2. 先写AOF缓存,beforeSleep阶段将缓存写入AOF文件
  3. 达到阈值触发AOF文件重写,将多条命令合并,写入数据最终状态,重新生成AOF文件

主从复制

redis支持主从复制(一主一从/一主多从),从节点通过sync或者pysync进行数据同步,实现数据的最终一致性

sync全量同步

  1. 从节点发送sync命令
  2. 主节点会执行bgsave导出rdb快照,并同时开始缓存增量数据
  3. 发送rdb文件到从节点
  4. 发送该过程中缓存的增量数据,实现数据的全量同步 一文搞懂Redis的核心原理

psync全量/增量同步

  1. 若psync命令为psync ? -1,即偏移量为-1,则执行全量同步,执行过程与sync命令一致
  2. 若offset太老,数据超出了积压队列的缓存数据(积压队列一般大小为1M),则执行全量同步
  3. 否则执行增量同步,根据offset发送积压队列中的缓存数据,并同步该过程中新缓存的数据 一文搞懂Redis的核心原理

集群

redis集群基于gossip协议实现集群间通讯,集群中节点两两连接,实现集群信息的传播。若redis集群中节点数量过多,会导致集群内部通讯数据过多,难以达成一致,从而引起集群状态异常或阻塞正常请求

一文搞懂Redis的核心原理