Redis4 - 高可用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/njys1/article/details/82795884
  • 复制
  • 复制优化
  • sentinel
  • cluster

复制

    info replication 检测复制关系
    master_replied 标记主实例
    master_repl_offset 是复制流中的一个偏移量标记、会随着主实例上的数据事件的发生而增长

    完全同步:
    将所有数据复制到rdb文件、然后发送给从实例、
    从实例接收到rdb文件后、会先将内存的数据清空、然后回访rdb数据
    从实例的复制过程是异步的、不会阻塞服务器处理客户端的请求

    部分重新同步:
    redis4.0之后的版本、master_replid和offset会存储在rdb文件中、
    从实例被优雅的关闭和重启后、redis可以从rdb文件中重新加载它们的值、进行部分重同步

    从实例被提升为新主后、新主会记录旧主的这两个值、实现部分重同步

复制优化

    1. 在redis主实例与从实例不能同步的时候、主实例上的一段内存(一个环形缓冲区)会跟踪最近写入的所有命令、实际上是一个固定长度的列表(也即:replication backlog、默认1MB)

    2. 在发出slaveof命令后、从实例使用最新的一个offset和最近一个master的id向新主实例发送
    部分重新同步请求、新主会检测请求中的master_replid是否与自己的master_replid一致、
    然后会检测请求中的offset是否可以从backlog缓冲中获取、可以的话、意味着backlog中包含连接
    断开期间的所有命令、可以进行部分同步

    3. 否则、说明在连接断开期间收到的写入命令数量超过了backlog的容量、部分同步请求会被拒绝、同时启动完全同步

    4. repl-backlog-ttl 默认3600
       若所有的从实例与主实例断开连接、过多久释放backlog的内存

    5. 从网络传输的角度看、还可以使用 repl-disable-tcp-nodelay 来减少带宽使用
       设为yes、redis会尝试将小数据包合并、但是也会造成数据延迟、约40ms

    6. repl-diskless-sync yes可以不使用rdb文件存储、直接将rdb的内容发送给从实例
        这个参数目前是实验阶段、不稳定、需要小心使用~~

    7. redis的键过期是由主实例来驱动的、当主实例中的键过期时、会向所有的从实例发送del命令、
    在同步期间、del命令也会被放到复制客户端缓冲区中

sentinel

    故障迁移过程:
    1. 一个哨兵发现主实例不可用、
      每个哨兵会定期向主实例、从实例及其他哨兵发送ping命令、若超时、认为服务不可用(主观下线)
      标记主实例下线的哨兵会向其它哨兵发送请求、要求他们检查主实例的状态、只有超过一定值的哨兵(哨兵数/2+1)认为
      主实例下线、才会发生故障转移、

      执行故障转移是由leader哨兵来进行的

    2. 如何进行leader选举呢 ?
       一个哨兵标记主实例主观下线后、投票开始、哨兵会开始从其它哨兵那里征集选票、另一个哨兵接到拉票请求时、若还未投票、则响应请求、 若哨兵从其它哨兵处得到足够数量的选票、则会成为leader

    3. sentinel管理
       sentinel get-master-addr-by-name <master-name> 获取当前主实例的信息
       sentinel masters 获取所有被监控实例的状态
       sentinel slaves <master-name> 获取一个主实例的所有从实例
       sentinel set 更新哨兵配置
       eg. sentinel set mymaster notification-script mymaster /redis/script/sentinel_events_notify.sh
       然后再 bash 脚本里边实现想要的功能、当然可以是其它任意类型的脚本

       另外还可以配置redis sentinel在故障迁移发生时自动执行的脚本、
       eg. 我们可能希望在故障迁移时禁用主实例上的 RDB 持久化选项、在从实例上启用、
       当主实例发生故障时被降为从实例、这个从实例的配置不能被哨兵更新、因此、除非我们手动更新该从实例上的rdb功能、否则它一直会是启用状态

       eg. sentinel set mymaster notification-script mymaster /redis/script/rdb_control.sh
       在脚本里实现配置修改的功能

       脚本执行成功返回0、若返回值为1、则脚本会被重试10次、
       若一个脚本60s内未执行完、会被sigkill信号结束掉、并重试10次
       若脚本的返回值为1 、则不会重试

       切换新主、是通过向选定的新主发送slave of none命令来实现的
       如何选定?日志最新的slave、也就是尽量的保障数据的完整性

cluster

    1. redis集群运行时、每个节点会打开两个TCP套接字、
       第一个套接字是用于客户端连接的标准redis通信协议、
       第二个是 第一个 + 10000(硬编码) 
       #define CLUSTER_PORT_INCR 10000 /*Cluster port = baseport + PORT_INCR */
       被用作实例间信息交换的通信总线、所以、监听端口大于 55535 的redis集群节点是不能启动的

    2. cluster meet命令可以让redis示例发现彼此
    3. 总的可以分配的数据槽的数量为 16384
       #define CLUSTER_SLOTS 16384
        分配时不可超过该值、否则会报错:
        ERR Invalid or out of range slot
        cluster.c:4022: addReplyError(c,"Invalid or out of range slot");

        若遇到已分配过的槽、也会报错: ERR Slot {{id}} is already busy
        cluster.c:4180 - 4183
        if (!del && server.cluster->slots[slot]) {
                addReplyErrorFormat(c,"Slot %d is already busy", slot);
                zfree(slots);
                return;
            }

    4. cluster nodes可以查看主从复制的状态、或者直接使用cluster info


    集群管理:

    获取集群状态:cluster info
    eg. redis-cli -h 127.0.0.1 -p 63790 -c cluster info

    获取集群中节点状态:cluster nodes
    eg. redis-cli -h 127.0.0.1 -p 63790 -c cluster nodes

    添加主从实例:cluster meet
    eg. redis-cli -h 127.0.0.1 -p 63790 -c cluster meet

    若添加一个节点的时候、提示该节点已有一些数据存在火灾节点配置文件已存在、
    [ERR] Node .. is not empty. Either the node is already knows ...

猜你喜欢

转载自blog.csdn.net/njys1/article/details/82795884