Redis④ —— 高可用

1. 主从复制

  • 一主多从模式,采用读写分离的方式
  • 主服务器可以进行读写操作,当发生写操作时自动将写操作同步给从服务器,而从服务器一般是只读,并接受主服务器同步过来写操作命令,然后执行这条命令。
  • 主从服务器之间的命令复制是异步进行的

1.1 第一次同步

  • 建立连接、协商同步
    • 主服务器会把所有的数据都同步给从服务器(全量复制)。
  • 主服务器同步数据给从服务器
    • 主服务器会执行 bgsave 命令来生成 RDB 文件,然后把文件发送给从服务器
    • 从服务器收到 RDB 文件后,会先清空当前的数据,然后载入 RDB 文件(异步)
    • 为了保证主从服务器的数据一致性,主服务器在下面这三个时间间隙中将收到的写操作命令,写入到 replication buffer 缓冲区里
      • 主服务器生成 RDB 文件期间;
      • 主服务器发送 RDB 文件给从服务器期间;
      • 从服务器加载 RDB 文件期间;
  • 主服务器发送新写操作命令给从服务器
    • 主服务器将 replication buffer 缓冲区里所记录的写操作命令发送给从服务器,从服务器执行来自主服务器 replication buffer 缓冲区里发来的命令,这时主从服务器的数据就一致了

1.2 命令传播

  • 主从服务器在完成第一次同步后,双方之间就会维护一个 TCP 连接。
  • 连接是长连接的,目的是避免频繁的 TCP 连接和断开带来的性能开销

1.3 分摊主服务器的压力

  • 从服务器可以有自己的从服务器,可以把拥有从服务器的从服务器当作经理角色,它不仅可以接收主服务器的同步数据,自己也可以同时作为主服务器的形式将数据同步给从服务器
  • 通过这种方式,主服务器生成 RDB 和传输 RDB 的压力可以分摊到充当经理角色的从服务器

1.3.1 增量复制

  • 网络断开又恢复后,从主从服务器会采用增量复制的方式继续同步,也就是只会把网络断开期间主服务器接收到的写操作命令,同步给从服务器。
  • 主服务器怎么知道要将哪些增量数据发送给从服务器呢
    • repl_backlog_buffer ,是一个「环形」缓冲区,用于主从服务器断连后,从中找到差异的数据;
    • replication offset ,标记上面那个缓冲区的同步进度,主从服务器都有各自的偏移量,主服务器使用 master_repl_offset 来记录自己「 」到的位置,从服务器使用 slave_repl_offset 来记录自己「」到的位置。
  • 如果判断出从服务器要读取的数据还在 repl_backlog_buffer 缓冲区里,那么主服务器将采用增量同步的方式;
  • 相反,如果判断出从服务器要读取的数据已经不存在 repl_backlog_buffer 缓冲区里,那么主服务器将采用全量同步的方式。

2. 哨兵机制

  • 实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端
  • 哨兵其实是一个运行在特殊模式下的 Redis 进程,相当于是"观察者节点",观察的对象是主从节点。
  • 主要负责三件事情:监控、选主、通知
  • 哨兵节点通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,相互连接,然后组成哨兵集群,同时哨兵又通过 INFO 命令,在主节点里获得了所有从节点连接信息,于是就能和从节点建立连接,并进行监控了。
  • 流程:
    • 判断主节点下线
      • 某个哨兵判定主节点下线(主观下线)后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。当赞成数到达预定值后,标记为客观下线
    • 选出哨兵leader
      • 拿到半数以上的赞成票
      • 拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值
    • 哨兵leader进行主从故障转移
      • 在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
        • 过滤掉已经离线的从节点
        • 过滤掉历史网络连接状态不好的从节点
        • 将剩下的从节点,进行三轮考察:优先级、复制进度、ID 号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点
      • 让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」
      • 将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端
      • 继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点

3. 切片集群模式

  • 当 Redis 缓存数据量大到一台服务器无法缓存时,就需要使用 Redis 切片集群方案,它将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高 Redis 服务的读写性能。
  • 采用哈希槽(Hash Slot),来处理数据和节点之间的映射关系。一个切片集群共有 16384 个哈希槽 ,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中
    • 根据键值对的 key,按照 CRC16 算法 计算一个 16 bit 的值
    • 再用 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽
  • 哈希槽怎么被映射到具体的 Redis 节点上的呢
    • 平均分配: 在使用 cluster create 命令创建 Redis 集群时,Redis 会自动把所有哈希槽平均分布到集群节点上。比如集群中有 9 个节点,则每个节点上槽的个数为 16384/9 个。
    • 手动分配: 可以使用 cluster meet 命令手动建立节点间的连接,组成集群,再使用 cluster addslots 命令,指定每个节点上的哈希槽个数。
      • 在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作

4. 集群脑裂

4.1 什么是脑裂?

  • 由于网络问题,主节点与从节点失联,但是主节点与客户端网络正常,客户端仍然向主节点写数据,但是此时主节点无法同步数据给从节点。哨兵模式选举新的leader作为主节点,这时集群有两个主节点了。

4.2 为什么集群脑裂会导致数据丢失?

  • 网络好了之后,哨兵会把原来的主节点降级为从节点,然后从节点会向新的主节点请求数据同步。
  • 第一次同步是全量同步,该从节点会清除自己本地的数据,然后再全量同步。这样会导致客户端之前写入的数据都丢失了

4.3 如何解决

  • 当主节点发现从节点下线或者通信超时的总数量小于阈值时,那么禁止主节点进行写数据,直接把错误返回给客户端。
  • 等到新主库上线时,就只有新主库能接收和处理客户端请求,此时,新写的数据会被直接写到新主库中。而原主库会被哨兵降为从库,即使它的数据被清空了,也不会有新数据丢失。
相关推荐
远歌已逝30 分钟前
维护在线重做日志(二)
数据库·oracle
qq_433099402 小时前
Ubuntu20.04从零安装IsaacSim/IsaacLab
数据库
Dlwyz2 小时前
redis-击穿、穿透、雪崩
数据库·redis·缓存
工业甲酰苯胺4 小时前
Redis性能优化的18招
数据库·redis·性能优化
没书读了5 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
i道i5 小时前
MySQL win安装 和 pymysql使用示例
数据库·mysql
小怪兽ysl5 小时前
【PostgreSQL使用pg_filedump工具解析数据文件以恢复数据】
数据库·postgresql
wqq_9922502776 小时前
springboot基于微信小程序的食堂预约点餐系统
数据库·微信小程序·小程序
爱上口袋的天空6 小时前
09 - Clickhouse的SQL操作
数据库·sql·clickhouse
Oak Zhang6 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存