欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

Redis持久化与集群演变
(last modified May 14, 2023, 7:52 PM )
by
侧边栏壁纸
  • 累计撰写 178 篇文章
  • 累计创建 62 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Redis持久化与集群演变

橙序员
2023-05-14 / 0 评论 / 0 点赞 / 293 阅读 / 2,562 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

REDIS持久化有三种方式:RDB持久化、AOF持久化和混合持久化。RDB持久化是Redis 5.0之前默认的持久化方式,通过配置快照规则来触发持久化操作。其优点是可以最大化Redis性能,但缺点是一旦Redis异常退出会丢失最后一次快照以后更改的数据。AOF持久化是通过将每条更改数据的命令写入AOF文件来实现,可以通过配置规则来决定写入时机,但会降低Redis性能。AOF重写是对AOF文件进行压缩,去除重复操作,减小文件体积。如何选择RDB和AOF取决于业务需求,如果数据不能丢失则需要使用RDB+AOF方式持久化,如果只是缓存服务器则只需要配置RDB混合持久化。Redis 5.0之后默认采用混合持久化方式。

REDIS持久化

reids持久化有三种方式

  1. RDB持久化
  2. AOF持久化
  3. 混合持久化

RDB持久化(数据快照)

RDB持久化redis 5.0之前默认的持久化方式,在配置文件中配置快照规则save <time:s> <nums:change_keys>则表示在多少秒内至少多少个键被更改才触发持久化。

RDB持久化过程:

  1. 由Redis主进程调用系统中的 fork 函数复制一份子进程的副本
  2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时(RDB)文件。
  3. 当子进程写入完所有数据后会用新生成的RDB文件替换旧的 RDB 文件,至此,一次快照操作完成。

RDB的缺点:一旦Redis异常退出,则会丢失最后一次快照以后更改的数据

RDB的优点:由于RDB文件的生成是由子进程操作的,所以可以最大化redis性能。但是数据量较大时,耗时变长的fork会造成服务器暂停处理客户端的请求。

AOF持久化(命令快照)

Redis默认没有开启AOF(append only file)方式的持久化。在配置文件中可以通过配置appendonly yes开启AOF持久化。开启AOF持久化后,每执行一条会更改 Redis 中的数据的命令, Redis就会将该命令写入硬盘中的 AOF文件硬盘缓存,这一过程显然会降低 Redis 的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高AOF的性能。

而由硬盘缓存写入AOF文件(类比记事本编辑文档),则可以通过配置规则appendfsync决定写入时机,分别为always-每次写入都会同步,everysec-每秒写入,no-操作系统自动写入(会丢失)

AOF重写原理:Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写。重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。例如对一个key的值重复操作时,只保留最新一次操作或合并后的操作即可。

如何选择RDB和AOF?

如果业务场景将Redis用作内存数据库使用,数据不能丢失,则需要使用RDB+AOF方式持久化,如果业务只用做缓存服务器,则只需要配置RDB

混合持久化(数据+命令快照)

redis 5.0之后默认的持久化方式。RDB可能会导致一定时间内的数据丢失,而AOF文件较大则会影响 Redis 的启动速度,为了能同时拥有RDB和AOF的优点,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前 的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能降低数据丢失的风险。

集群演变

数据存储这类应用,需要考虑的问题有两方面:如何防止服务宕机和如何进行服务扩容

数据容灾-哨兵

在防止Redis节点宕机和数据丢失方面,Redis通过主从复制保证了集群备份,并且通过哨兵机制进行主从切换,保证服务的高可用。

主从复制

通过在redis从库上配置slaveof ip portreplicaof ip port, 便能开启主从复制。是否全量同步的判断为:

  1. 只要从机第一次连接上主机是全量同步。
  2. 断线重连时如果从库的runid一致,则为增量同步,否则为全量同步
  3. 其他场景都为增量同步

全量同步时,会首先同步快照,再同步主节点缓冲区的写操作命令,最后进行增量同步

增量同步时,主节点没执行一个写命令就会发送给从节点,由从节点接收执行

哨兵机制

正常场景下主节点宕机后,我们需要将修改从库配置将从库切换为主库,然后再主库启动后,把启动后的主库修改配置更新为从库。所以我们可以通过一个服务来动态监听主库和从库的状态,来完成主库宕机时的主从切换。

哨兵的工作流程如下:

  1. 定时请求主从节点,监控redis节点状态
  2. 当请求主节点时未得到及时响应,则认为主观下线。此时会查询其他哨兵对主节点的状态判断
  3. 如果认为主节点下线的个数超过选举个数(哨兵个数/2+1),则认为主节点客观下线
  4. 从哨兵中选举leader执行故障转移,选择主节点(主节点选择依照节点优先级,复制偏移量最大,最小runid依次判断)并更新节点配置。
  5. 更新其他从节点配置,使其为新主的从

流程示意图如下:

image-20230514181420362

需要注意的是哨兵sentinel为redis提供的工具,正常会和我们的redis部署在同一机器上。所以我们在部署redis时会经常选择一主两从或多从的方式。一主一从会在宕机后无法选择出哨兵节点而无法执行故障转移

数据扩容-集群

为了解决redis水平扩容的问题,redis提供了集群部署方式,集群的特征如下:

  • 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  • 节点的失败是通过集群中超过半数的节点检测失效时才生效.
  • 客户端与redis节点直连,不需要中间代理。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  • redis-cluster把所有的物理节点映射到[0-16383]slot中的不同区间上,cluster负责维护node<->slot<->value

集群投票

首先判断节点是否失效:集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉

然后判断集群是否失效:如果集群中任意master挂掉,且当前master没有slave,则集群进入fail状态。也可以理解成集群的[0- 16383]slot映射不完全时进入fail状态。 如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。

数据路由

客户端与Redis节点直连,不需要中间Proxy层,直接连接任意一个Master节点根据公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应 的节点进行操作

主从切换

当集群中节点通过错误检测机制发现某个节点处于fail状态时,会执行主从切换。Redis 还提供了手动切换的方法,即通过执行cluster failover命令。

自动切换时流程如下

  1. 从节点先更新自己的状态,将声明自己为主节点。并且将从节点从主节点中移除
  2. 由于从节点需要切换为主节点,所以将S的同步数据相关信息清除(即不再从主节点同步锁数据)
  3. 将主节点提供服务的slot都声明到从节点中
  4. 发送一个PONG包,通知集群中其他节点更新状态

手动切换时流程为:

  1. 该从节点首先向主节点发送一个mfstart包。通知主节点从节点开始进行手动切换
  2. 主节点会阻塞所有客户端指令的执行。之后主节点在周期函数clusterCron中发送ping 包时会在包头部分做特殊标记
  3. 当从节点收到主节点的ping包并且检测到特殊标记之后,会从包头中获取主节点的复制偏移量
  4. 从节点在周期函数clusterCron中检测当前处理的复制偏移量与主节点复制偏移量是否相等,当相等时开始执行切换流程
  5. 切换完成后,主节点会讲阻塞的所有客户端命令通过发送+MOVED 指令重定向到新的主节点

副本漂移

副本漂移的场景出现在集群中的某个主节点无从节点时,会从其他主节点上取多余的从节点作为该主节点的从节点。

其在定时巡检的周期函数中会做如下判断

  • 是否存在单点的主节点,即主节点没有任何一台可用的从节点

  • 是否存在有两台及以上可用从节点的主节点

如果以上两个条件都满足,从有最多可用从节点中选择一台从节点执行副本漂移。选择标准为按节点名称从小到大,选择最靠前的一台从节点执行漂移。

节点迁移

节点添加:为redis集群添加节点时分为三步:

  1. 添加主节点
  2. 为节点分配slot
  3. 添加从节点

节点删除:为redis集群删除节点时分为三步:

  1. 删除从节点
  2. 清空主节点的slot
  3. 删除主节点
0

评论区