【Redis】高可用:主从、哨兵、切片集群

高可用

主从复制

Why?

单点故障无法提供服务,硬盘故障数据丢失。

How?

数据备份,并且保证一致性:主从复制

  • 读写分离:写入主,读取从

建立过程:

  1. 建立链接、协商同步;

    1. 发送:psync:主服务器runID、offset
    2. 回复:FULLRESYNC:主服务器的 runID、主服务器目前的复制进度 offset
  2. 主服务器同步数据给从服务器;

    1. 主 bgsave 生成 RDB 文件,发送给从服务器。
    2. 从收到 RDB 文件后,会先清空当前的数据,然后载入 RDB 文件
  3. 主服务器发送新写操作命令给从服务器。

    1. 主将 replication buffer 缓冲区写操作命令发送给从
    2. 从执行主的命令,的数据就一致了

命令传播

Why?

后期主数据的变更需要及时同步到从

How?

双方之间就会维护一个长 TCP 连接。

后续主通过这个连接发送命令给从。

分摊主服务器的压力

Why?

每次从加入都要bgsave,fork创建子进程、传递RDB文件消耗资源

How?

主服务器生成 RDB 和传输 RDB 的压力可以分摊到充当经理角色的从服务器:

  • 在「从服务器」上执行下面这条命令,使其作为目标服务器的从服务器:

    • replicaof <目标服务器的IP> 6379
    • 目标服务器是「从服务器」,该目标服务器就会成为「经理」的角色

增量复制

Why?

主从TCP连接网络问题断开后,数据不一致。回复连接如何恢复一致性?

How?

  • Redis 2.8 之前:重新进行一次全量复制,性能消耗大
  • Redis 2.8 后:增量复制,只把网络断开期间主接收到的写操作命令,同步给从。

步骤:

  • 从发送 psync 命令给主,offset 参数不是 -1;

  • 主返回 CONTINUE 告诉从增量复制同步数据;

  • 主服务将主从断线期间,所执行的写命令发送给从,从执行这些命令。

  • repl_backlog_buffe:环形缓冲区,1M

  • replication offset:标记缓冲区的同步进度

    • master_repl_offset:主写到的位置
    • slave_repl_offset:从读到的位置。

主的写入速度远超于从读取速度,缓冲区的数据会被覆盖,只能再采用全量同步。

  • 为了避免主频繁全量同步,调大 repl_backlog_buffer 缓冲区大小

    • repl-backlog-size 10mb

高频问题

怎么判断 Redis 某个节点是否正常工作?

通过互相的 ping-pong 心态检测机制,如果有一半以上的节点去 ping 一个节点的时候没有 pong 回应,集群就会认为这个节点挂掉了,会断开与这个节点的连接。

  • 主默认每 10 秒对从发送 ping,repl-ping-slave-period 控制发送频率。

  • 从每 1 秒发送 replconf ack{offset} 命令,给主上报自身当前的复制偏移量,目的是为了:

    • 实时监测主从节点网络状态;
    • 上报自身复制偏移量检查复制数据是否丢失, 如丢失, 再从主复制缓冲区中拉取丢失数据。

过期key如何处理?

主模拟一条del命令发送给从

Redis 是同步复制还是异步复制?

主每次收到写命令之后,先写到内部的缓冲区,然后异步发送给从节点。

主从复制中两个 Buffer(replication buffer 、repl backlog buffer)有什么区别?

  • repl backlog buffer:增量复制阶段,一主只分配一个;

    • 满了覆盖起始位置数据
  • replication buffer:全量复制阶段和增量复制阶段都会出现

    • 主会给每个新连接的从,分配一个;
    • 满了,连接断开删除缓存,从重新连接,重新全量复制。

如何应对主从数据不一致?

Why?

  • 主从间的命令复制是异步的,无法实现强一致性

How?

  • 尽量保证主从节点间的网络连接状况良好,避免主从节点在不同的机房。

  • 可以开发一个外部程序来监控主从节点间的复制进度。

    • INFO replication 命令查看主接收写命令的进度信息(master_repl_offset)和从复制写命令的进度信息(slave_repl_offset)
    • 可以开发一个监控程序,先 INFO replication ,master_repl_offset – slave_repl_offset 得到从和主间的复制进度差值。
    • 如果某个从的进度差值大于预设的阈值,让从失效防止客户端读取。为了避免出现客户端和所有从都不能连接的情况,需要把复制进度差值的阈值设置得大一些。

主从切换如何减少数据丢失?

主从切换数据丢失的情况:

  • 异步复制同步丢失

    • min-slaves-max-lag:一旦所有从节点数据复制和同步的延迟都超过这个值,主拒绝服务。防止主宕机导致丢失过多数据。
    • 客户端发现 master 不可写后,降级措施,将数据暂时写入本地缓存和磁盘中,等 master 恢复后重新写入,也可以将数据写入 kafka 消息队列。
  • 集群产生脑裂数据丢失

    • 脑裂:主网络异常,哨兵找不到,新选了主,形成双主。

    • 主网络恢复只能变成从,重新全量同步新主,原来的新数据丢失

减少脑裂的数据丢的方案

  • 当主发现从下线的数量太多,或网络延迟太大,禁止写操作

    • min-slaves-to-write x:主必须要有至少 x 个从节点连接
    • min-slaves-max-lag x:主从数据复制和同步的延迟不能超过 x 秒

主从如何做到故障自动切换?

  • 需要人工处理
  • 哨兵

哨兵

Why?

主节点出问题,人工切换太沙雕了。

How?

Redis 2.8 版本提供的哨兵(Sentinel)机制:实现主从节点故障转移。监测、选主、通知。

监控

哨兵每1s对主发PING,没有在down-after-milliseconds内收到主的响应,主被判断下线。

  • 主观下线:哨兵网络问题观察不到主,但主其实没问题
  • 客观下线:主确实有问题

Why?

为避免单哨兵导致主观下线的错误判断,需要多个(>=3)哨兵对主进行监控

How?

一个哨兵发现主下线,所有哨兵进行投票,超过quorum个赞同就确定主下客观线。

  • 三个哨兵quorum设置为2(1/2+1)

哨兵leader选举

Why?

由哪个哨兵进行主从故障转移?

How?

  • 候选者:发现主下线的哨兵
  • 投票:每个哨兵只投一票,候选者可投自己
  • 归票:半数以上的赞成票 and 大于等于哨兵配置文件中的 quorum 值

如果未满足条件

故障转移

过程:

  1. 从里挑选出一个转换为主。

    1. 去除网络不好的从:down-after-milliseconds断链超过10次

    2. 选主:优先级排序,优先级相同按复制进度排序、再相同以ID小优先

      • slave-priority:从的优先级,高配置节点可以优先级高
      • slave_repl_offset:复制进度
    3. 向这个选出来的从发送 SLAVEOF no one 命令,转换为主。哨兵 leader 每秒向被升级的从发送 INFO 命令判断当前是否升级完成。

  2. 所有从修改复制目标为复制「新主节点」;

    1. 新主升级完成,哨兵leader向所有从发送 SLAVEOF 命令转移新主
  3. 将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;

    1. 哨兵向 +switch-master 频道发布新主节点的 IP 地址和端口的消息,客户端用新主的 IP 地址和端口通信
    2. 哨兵提供的消息订阅频道:
  4. 继续监视旧主,当重新上线时,设置新主的从;

哨兵集群

哨兵节点之间通过 Redis 的发布者/订阅者机制来相互通信

  • 主节点:sentinel:hello 频道

    • 哨兵把自己IP端口发送到__sentinel__:hello,其他订阅的哨兵就可以感知,并与之建立连接
  • 哨兵通过向主发送INFO得知从节点,并建立连接

切片集群

Why?

数据量太大,单机内存不够用。

How?

Redis Cluster:

  1. 数据到哈希槽映射(16384 个哈希槽)

    1. 键值对的 key,按照 CRC16 算法计算一个 16 bit 值。
    2. 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。
  2. 哈希槽到实例映射

    1. 平均分配: cluster create 命令创建 Redis 集群时,自动把所有哈希槽平均分布到集群节点上。

    2. 手动分配: cluster meet 命令手动建立节点间的连接,组成集群,再使用 cluster addslots 命令,指定每个节点上的哈希槽个数。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY5mvQgT' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片