美文网首页数据库
15. Redis 哨兵

15. Redis 哨兵

作者: 随便写写咯 | 来源:发表于2021-03-08 02:53 被阅读0次

    10. Redis哨兵(高可用)

    10.1 redis集群介绍

    主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis高可用无法实现自故障转移(将slave提升为master),需要手动改环境配置才能切换到slave redis服务器,另外也无法横向扩展Redis服务的并行写入性能,当单台Redis服务器性能无法满足业务写入需求的时候就必须需要一种方式解决以上的两个核心问题,即:1.master和slave角色的无缝切换,让业务无感知从而不影响业务使用 2.可以横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。

    Redis 集群实现方式:

    客户端分片
    代理分片
    Redis Cluster
    

    10.2 哨兵工作原理

    10.2.1 哨兵架构和故障转移

    哨兵节点和redis节点是独立的关系,一套哨兵, 可以监控多个redis主从架构, 通过master-name来区分

    类似于MySQL的MHA

    一般一套哨兵监控一套redis主从, 并且哨兵和redis节点配置在同一台服务器上, 不会单独用多个独立的服务器专门跑哨兵节点

    图片.png

    redis哨兵配合客户端应用程序

    应用程序连接哨兵节点, 通过哨兵节点获取存活的主,从节点信息, 进而发起连接

    图片.png

    故障转移

    图片.png

    Sentinel 进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现
    Master和Slave服务器的切换,保证系统的高可用,其已经被集成在redis2.6+的版本中,Redis的哨兵模式到了2.8
    版本之后就稳定了下来。一般在生产环境也建议使用Redis的2.8版本的以后版本.

    哨兵(Sentinel) 是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,一套哨兵系统可以管理多套主从复制, 靠mastername区分开. 这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。

    每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(可配置的)内未得到回应,则暂时认为对方已离线,也就是所谓的”主观认为宕机” ,主观是每个成员都具有的独自的而且可能相同也可能不同的意识,英文名称:Subjective Down,简称SDOWN。

    有主观宕机,对应的就有客观宕机。当“哨兵群”中的多数Sentinel进程在对Master主服务器做出SDOWN 的判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”,客观是不依赖于某种意识而已经实际存在的一切事物,英文名称是:Objectively Down, 简称 ODOWN。

    通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)

    Sentinel 机制可以解决master和slave角色的自动切换问题,但单个Master 的性能瓶颈问题无法解决,类似于MySQL的MHA

    实现主从自动故障转移, 但是还是一个主节点, 无法实现多个主节点同时写入
    

    为了节约资源, 可以把哨兵节点和redis节点部署在同一台服务器上

    哨兵模式下, 客户端要和哨兵节点连接, 通过哨兵节点来获取redis集群中哪个是主节点哪个是从节点. 当主节点故障时, 由哨兵节点协商提升从节点为主节点, 客户端无需做调整. 但哨兵只是配置中心, 并不是代理, 也就是客户端虽然连接哨兵, 但是其只为了获取存活的主节点和从节点信息, 之后还是向对应的节点发起连接

    redis哨兵节点和普通redis没有区别, 要实现读写分离, 需要依赖于客户的程序

    主节点确认故障后, 哨兵节点会内部选出一个节点执行操作, 由其提升从节点为主节点

    哨兵中的哨兵节点个数, 应该大于等于3且最好为奇数, 这样投票才不会出现平票

    redis3.0版本前, 一般使用哨兵模式. 3.0后推出了cluster功能, 支持更大规模的生产环境

    10.2.2 哨兵中三个定时任务

    1. 每10秒, 每个哨兵对master和slave执行info命令, 用于发现集群中节点, 确定主从关系
    
    2. 每2秒, 每个哨兵通过master节点的channel交换信息(发布者/订阅者模式), 通过sentinel_:hello频道交互对节点的"看法"和自身信息
    
    3. 每一秒每个哨兵对其他哨兵和所有redis节点执行ping操作, 探测存活
    

    10.3 实现哨兵

    实验环境: 三台redis服务器, 实现主从. 同时每台redis跑一个哨兵节点为了节省资源

    图片.png

    主: 10.0.0.82; 哨兵
    从1: 10.0.0.83; 哨兵
    从2: 10.0.0.84; 哨兵

    10.3.1 从0搭建主从

    10.0.0.82 master节点

    bind 0.0.0.0
    requirepass redis
    masterauth redis  # 搭建主从时, 主节点就要配置masterauth, 因为一旦它宕机, 并且恢复后, 就需要和新的主节点进行同步, 如果这里没有配置, 那么其宕机恢复后是无法加入到主从架构的
    
    [00:27:29 root@master ~]#redis-cli -a redis info replication
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=10.0.0.83,port=6379,state=online,offset=168,lag=0
    slave1:ip=10.0.0.84,port=6379,state=online,offset=168,lag=0
    master_replid:d9f80eaacd824a6f6e9620154acb661cb713e40e
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:168
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:168
    

    10.0.0.83 slave-1

    bind 0.0.0.0
    requirepass redis
    masterauth redis
    replicaof 10.0.0.82 6379
    
    [00:27:28 root@slave-1 ~]#redis-cli -a redis info replication
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    # Replication
    role:slave
    master_host:10.0.0.82
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:2
    master_sync_in_progress:0
    slave_repl_offset:168
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:d9f80eaacd824a6f6e9620154acb661cb713e40e
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:168
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:168
    

    10.0.0.84 slave-2

    bind 0.0.0.0
    requirepass redis
    masterauth redis
    replicaof 10.0.0.82 6379
    
    [00:27:28 root@slave-2 ~]#redis-cli -a redis info replication
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    # Replication
    role:slave
    master_host:10.0.0.82
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:2
    master_sync_in_progress:0
    slave_repl_offset:168
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:d9f80eaacd824a6f6e9620154acb661cb713e40e
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:168
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:127
    repl_backlog_histlen:42
    

    10.3.2 哨兵搭建:

    1. 软件安装

    redis哨兵也是来自于redis包, 因此如果在单独的服务器上搭建哨兵, 需要单独安装redis. 本案例是redis和哨兵在同一台服务器, 因此无需再安装redis

    1. 编辑配置文件

    配置文件说明:

    /etc/redis-sentinel.conf
    
    [root@master ~]# grep "^[^#]" /etc/redis-sentinel.conf 
    bind 0.0.0.0
    port 26379  #哨兵默认监听端口号26379
    daemonize no
    pidfile /var/run/redis-sentinel.pid
    logfile ""
    dir /tmp  #工作目录
    sentinel monitor mymaster 127.0.0.1 6379 2     #mymaster就是每个主从复制的名称, 用来区分多组主从架构, 需要修改mymaster和master节点的ip地址
    #指定当前mymaster集群中master服务器的地址和端接口
    #2为法定人数限制(quorom). 既有几个sentinel认为master down了就进行故障转移, 一般此值是所有sentinel节点(一般总数>=3的奇数; 如:3,5,7等)的一半以上的整数值; 比如: 总数是3, 即3/2=1.5, 取整为2, 是master的ODOWN客观下线的依据
    sentinel auth-pass mymaster 123456 #mymaster集群中master的密码, 注意此行要在上面行的下面书写
    sentinel down-after-milliseconds mymaster 30000 #(SDOWN)判断mymaster集群中所有节点的主观下线时间, 单位: 毫秒, 默认30000=30秒, 建议3000=3秒 
    sentinel parallel-syncs mymaster 1 #发生故障转移后, 同时向新的master同步数据的slave数量.  数字越小总同步时间越长, 但可以减轻新master的负载压力
    sentinel failover-timeout mymaster 180000 #所有slaves指向新的master所需的超时时间, 单位:毫秒
    sentinel deny-scripts-reconfig yes #禁止修改脚本
    logfile /var/log/redis/sentinel.log
    

    修改sentinel配置文件

    bind 0.0.0.0
    sentinel monitor mymaster 10.0.0.82 6379 2
    sentinel auth-pass mymaster redis
    sentinel down-after-milliseconds mymaster 3000 #修改SD的下线时间为3秒, 默认的30秒过长
    

    每个哨兵节点的配置文件都是统一的, 因此只需要修改一个节点然后复制到其他节点即可

    [root@master ~]# scp /etc/redis-sentinel.conf 10.0.0.83:/etc
    [root@master ~]# scp /etc/redis-sentinel.conf 10.0.0.84:/etc
    

    service文件

    /usr/lib/systemd/system/redis-sentinel.service
    
    1. 启动哨兵服务. 一定要先修改哨兵配置文件, 然后再启动哨兵服务. 因为启动哨兵服务后, 哨兵配置文件会增加很多信息, 比如myid(用来在哨兵节点中标识某个节点), 所以要确保每个哨兵节点专属信息都是不一样的.
    systemctl enable --now redis-sentinel
    
    [01:01:13 root@master ~]#grep -E ^[a-zA-Z] /etc/redis-sentinel.conf
    port 26379
    daemonize no
    pidfile "/var/run/redis-sentinel.pid"
    logfile "/var/log/redis/sentinel.log"
    dir "/tmp"
    sentinel myid bb1518fa88dcfc481ed510d94e3ba28c54e864d2 # 哨兵节点全部启动后, 要确保每个节点的myid不同
    sentinel deny-scripts-reconfig yes
    sentinel monitor mymaster 10.0.0.82 6379 2
    sentinel down-after-milliseconds mymaster 3000
    sentinel auth-pass mymaster redis
    sentinel config-epoch mymaster 0
    protected-mode no
    supervised systemd
    sentinel leader-epoch mymaster 0
    sentinel known-replica mymaster 10.0.0.84 6379  # 这两行是哨兵获取的mymaster主从架构中的从节点信息
    sentinel known-replica mymaster 10.0.0.83 6379
    sentinel known-sentinel mymaster 10.0.0.83 26379 eb357a630f40ff86a6f11cefc8860283e269dd25 # 这两行是这个哨兵节点获悉的其余哨兵节点的信息, 因为在每个哨兵配置文件中都指向了它所管理的主从架构的名字和主节点ip/port, 因此每个哨兵都可以发现其余哨兵节点
    sentinel known-sentinel mymaster 10.0.0.84 26379 564e45cf8b5e5060cc2ed4fee5f14a24966b1fc1
    sentinel current-epoch 0
    
    [root@master ~]# ss -ntl
    State              Recv-Q             Send-Q                           Local Address:Port                            Peer Address:Port             
    LISTEN             0                  128                                    0.0.0.0:26379                                0.0.0.0:*                
    LISTEN             0                  128                                    0.0.0.0:6379                                 0.0.0.0:*                
    LISTEN             0                  128                                    0.0.0.0:22                                   0.0.0.0:*                
    LISTEN             0                  128                                       [::]:26379                                   [::]:*                
    LISTEN             0                  128                                       [::]:22                                      [::]:*  
    

    哨兵日志

    [01:05:19 root@master ~]#cat  /var/log/redis/sentinel.log 
    1900:X 08 Mar 2021 01:01:09.909 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    1900:X 08 Mar 2021 01:01:09.909 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=1900, just started
    1900:X 08 Mar 2021 01:01:09.909 # Configuration loaded
    1900:X 08 Mar 2021 01:01:09.909 * supervised by systemd, will signal readiness
    1900:X 08 Mar 2021 01:01:09.936 * Running mode=sentinel, port=26379.
    1900:X 08 Mar 2021 01:01:09.936 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    1900:X 08 Mar 2021 01:01:09.939 # Sentinel ID is bb1518fa88dcfc481ed510d94e3ba28c54e864d2
    1900:X 08 Mar 2021 01:01:09.939 # +monitor master mymaster 10.0.0.82 6379 quorum 2
    1900:X 08 Mar 2021 01:01:09.941 * +slave slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:01:09.951 * +slave slave 10.0.0.84:6379 10.0.0.84 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:01:11.941 * +sentinel sentinel eb357a630f40ff86a6f11cefc8860283e269dd25 10.0.0.83 26379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:01:11.943 * +sentinel sentinel 564e45cf8b5e5060cc2ed4fee5f14a24966b1fc1 10.0.0.84 26379 @ mymaster 10.0.0.82 6379
    

    初次启动sentinel时由于时间差的问题, 可能会出现SD, 可以忽略, sentinel一般只要不是OD就没问题

    通过redis-cli连接sentinel查看信息, 需要连接到26379端口. 而且每个哨兵看到的信息都是一样的

    [01:12:31 root@master ~]#redis-cli -p 26379
    127.0.0.1:26379> info sentinel
    # Sentinel
    sentinel_masters:1 # 
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=10.0.0.82:6379,slaves=2,sentinels=3
    
    [01:01:24 root@slave-1 ~]#redis-cli -p 26379
    127.0.0.1:26379> info sentinel
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=10.0.0.82:6379,slaves=2,sentinels=3
    
    [01:13:38 root@slave-2 ~]#redis-cli -p 26379
    127.0.0.1:26379> info sentinel
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=10.0.0.82:6379,slaves=2,sentinels=3
    

    redis哨兵无法使用keys,select等命令, 因为不是redis数据服务

    127.0.0.1:26379> keys *
    (error) ERR unknown command `keys`, with args beginning with: `*`, 
    127.0.0.1:26379> select 1
    (error) ERR unknown command `select`, with args beginning with: `1`, 
    

    10.3.3 模拟主节点故障切换

    1. 停止主节点 redis服务, 观察各哨兵节点日志文件
    [root@master ~]# systemctl stop redis
    

    在redis主节点查看哨兵日志

    [01:20:15 root@master ~]#tail -f /var/log/redis/sentinel.log
    
    1900:X 08 Mar 2021 01:20:50.087 # +sdown master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.160 # +odown master mymaster 10.0.0.82 6379 #quorum 2/2
    1900:X 08 Mar 2021 01:20:50.160 # +new-epoch 1
    1900:X 08 Mar 2021 01:20:50.160 # +try-failover master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.162 # +vote-for-leader bb1518fa88dcfc481ed510d94e3ba28c54e864d2 1
    1900:X 08 Mar 2021 01:20:50.196 # 564e45cf8b5e5060cc2ed4fee5f14a24966b1fc1 voted for bb1518fa88dcfc481ed510d94e3ba28c54e864d2 1
    1900:X 08 Mar 2021 01:20:50.198 # eb357a630f40ff86a6f11cefc8860283e269dd25 voted for bb1518fa88dcfc481ed510d94e3ba28c54e864d2 1
    1900:X 08 Mar 2021 01:20:50.223 # +elected-leader master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.223 # +failover-state-select-slave master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.279 # +selected-slave slave 10.0.0.84:6379 10.0.0.84 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.279 * +failover-state-send-slaveof-noone slave 10.0.0.84:6379 10.0.0.84 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:50.339 * +failover-state-wait-promotion slave 10.0.0.84:6379 10.0.0.84 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:51.200 # +promoted-slave slave 10.0.0.84:6379 10.0.0.84 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:51.200 # +failover-state-reconf-slaves master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:51.264 * +slave-reconf-sent slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:52.207 * +slave-reconf-inprog slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:52.207 * +slave-reconf-done slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:52.261 # +failover-end master mymaster 10.0.0.82 6379
    1900:X 08 Mar 2021 01:20:52.261 # +switch-master mymaster 10.0.0.82 6379 10.0.0.84 6379 # 主节点完成切换, 新的主节点为10.0.0.84
    1900:X 08 Mar 2021 01:20:52.262 * +slave slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.84 6379 # 将10.0.0.83指向新的主节点10.0.0.84
    1900:X 08 Mar 2021 01:20:52.262 * +slave slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379 # 宕机的主节点也会被修改, 指向新的主节点
    1900:X 08 Mar 2021 01:20:55.266 # +sdown slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379 # 由于主节点还处于宕机状态, 因此还会出现sdown
    

    在redis从节点查看哨兵日志

    [01:24:14 root@slave-1 ~]#tail -f /var/log/redis/sentinel.log
    1891:X 08 Mar 2021 01:20:49.431 # +sdown master mymaster 10.0.0.82 6379
    1891:X 08 Mar 2021 01:20:49.543 # +new-epoch 1
    1891:X 08 Mar 2021 01:20:49.548 # +vote-for-leader bb1518fa88dcfc481ed510d94e3ba28c54e864d2 1
    1891:X 08 Mar 2021 01:20:50.559 # +odown master mymaster 10.0.0.82 6379 #quorum 3/2
    1891:X 08 Mar 2021 01:20:50.559 # Next failover delay: I will not start a failover before Mon Mar  8 01:26:49 2021
    1891:X 08 Mar 2021 01:20:50.626 # +config-update-from sentinel bb1518fa88dcfc481ed510d94e3ba28c54e864d2 10.0.0.82 26379 @ mymaster 10.0.0.82 6379
    1891:X 08 Mar 2021 01:20:50.627 # +switch-master mymaster 10.0.0.82 6379 10.0.0.84 6379
    1891:X 08 Mar 2021 01:20:50.627 * +slave slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.84 6379
    1891:X 08 Mar 2021 01:20:50.627 * +slave slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379
    1891:X 08 Mar 2021 01:20:53.678 # +sdown slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379
    
    [01:24:17 root@slave-2 ~]#tail -f /var/log/redis/sentinel.log
    1889:X 08 Mar 2021 01:20:49.492 # +sdown master mymaster 10.0.0.82 6379
    1889:X 08 Mar 2021 01:20:49.552 # +new-epoch 1
    1889:X 08 Mar 2021 01:20:49.562 # +vote-for-leader bb1518fa88dcfc481ed510d94e3ba28c54e864d2 1
    1889:X 08 Mar 2021 01:20:49.576 # +odown master mymaster 10.0.0.82 6379 #quorum 3/2
    1889:X 08 Mar 2021 01:20:49.576 # Next failover delay: I will not start a failover before Mon Mar  8 01:26:50 2021
    1889:X 08 Mar 2021 01:20:50.632 # +config-update-from sentinel bb1518fa88dcfc481ed510d94e3ba28c54e864d2 10.0.0.82 26379 @ mymaster 10.0.0.82 6379
    1889:X 08 Mar 2021 01:20:50.632 # +switch-master mymaster 10.0.0.82 6379 10.0.0.84 6379
    1889:X 08 Mar 2021 01:20:50.632 * +slave slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.84 6379
    1889:X 08 Mar 2021 01:20:50.632 * +slave slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379
    1889:X 08 Mar 2021 01:20:53.679 # +sdown slave 10.0.0.82:6379 10.0.0.82 6379 @ mymaster 10.0.0.84 6379
    
    1. 查看各节点replication信息, 以及redis配置文件

    10.0.0.82

    # 宕机的原主节点服务处于停止状态, 无法查看
    [root@master ~]# redis-cli -a redis
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    Could not connect to Redis at 127.0.0.1:6379: Connection refused
    
    

    10.0.0.83 slave-1

    [01:29:30 root@slave-1 ~]#redis-cli -a redis
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    127.0.0.1:6379> info replication
    # Replication
    role:slave
    master_host:10.0.0.84  # 主节点已经指向了新的10.0.0.84
    master_port:6379
    master_link_status:up  # 状态是up的
    master_last_io_seconds_ago:1
    master_sync_in_progress:0
    slave_repl_offset:341599
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:819ff842c904343d0b0702f81bfda242e56e8164
    master_replid2:b78e3f5790d472bb7ff3a48d358df241055f9247
    master_repl_offset:341599
    second_repl_offset:233756
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:341599
    

    10.0.0.84 新的master

    [01:29:45 root@slave-2 ~]#redis-cli -a redis
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    127.0.0.1:6379> info replication
    # Replication
    role:master  # 新的主节点已经变成了master节点
    connected_slaves:1 # 当前只有slave-1, 因为原主节点还没有修复
    slave0:ip=10.0.0.83,port=6379,state=online,offset=340388,lag=0
    master_replid:819ff842c904343d0b0702f81bfda242e56e8164
    master_replid2:b78e3f5790d472bb7ff3a48d358df241055f9247
    master_repl_offset:340521
    second_repl_offset:233756
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:340521
    
    1. 查看各节点配置文件是否被修改

    故障切换前:

    原主节点10.0.0.82没有指定replicaof
    所有从节点的replicaof都是指向的原主节点,10.0.0.82

    第一次故障切换后:

    新提升的从节点10.0.0.84的配置文件中, replicaof项会被删除(如果是手动添加了一行, 那么就把这行删除, 留下默认的被注释掉的配置, 如果是直接修改的被注释掉的行, 那么这行就会被删除), 这里因为配置relicaof时, 重新写了一行, 所以切换后只有默认被注释掉的那行

    图片.png

    其余从节点(10.0.0.83)的配置文件中, replicaof会被修改为指向新的主节点ip, 10.0.0.84

    slave-1 10.0.0.83
    [01:35:25 root@slave-1 ~]#grep "replicaof 10.0.0"  /etc/redis.conf 
    replicaof 10.0.0.84 6379
    

    修复后的故障原主节点(10.0.0.82), 重启服务后, 会变成新的主节点的从节点, 并且在配置文件中的最后一行, 追加replicaof指向新的主节点的ip

    图片.png

    每个哨兵节点会对所有的其余哨兵节点和主从节点都定期做ping, 每隔一秒探测可活, 如果从节点宕机, 哨兵只会进行主观sdown,并不会进行客观down处理, 需要配合监控对从节点进行监控并且修复从节点宕机故障

    1891:X 08 Mar 2021 01:42:43.013 # +sdown slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.84 6379 # 手动停止10.0.0.83从节点redis服务
    1891:X 08 Mar 2021 01:43:16.123 * +reboot slave 10.0.0.83:6379 10.0.0.83 6379 @ mymaster 10.0.0.84 6379 # 手动启动redis后
    

    如果主从本身搭建有问题, 比如密码不对, bind没有修改地址等原因, 那么提升了新的主节点后, 配置错误的从节点是不会自动切换指向新的主节点的, 只能手动先修改其redis配置文件, 然后手动修改配置文件指向新的主节点 ,然后重启redis服务

    之后再发生故障:

    停止新的主节点10.0.0.84的redis服务
    systemctl stop redis
    
    可以看到新的主节点变成了10.0.0.83
    1889:X 08 Mar 2021 01:57:21.013 # +switch-master mymaster 10.0.0.84 6379 10.0.0.83 6379
    

    新的主节点10.0.0.83的配置文件中, replicaof项会被删除
    10.0.0.82从节点的配置文件中, replicaof会被修改为指向新的主节点ip

    图片.png

    修复后的故障主节点,10.0.0.84, 重启服务后, 会变成新的主节点的从节点, 并且在配置文件中, 加一行replicaof指向新的主节点的ip

    图片.png

    故障切换时, 除了会自动修改redis配置文件, sentinel的配置文件也会被修改

    以slave-2-10.0.0.84为例
    sentinel leader-epoch mymaster 2
    sentinel known-replica mymaster 10.0.0.84 6379 # 两次故障切换后, 10.0.0.83成为了新的主节点
    sentinel known-replica mymaster 10.0.0.82 6379
    sentinel known-sentinel mymaster 10.0.0.83 26379 eb357a630f40ff86a6f11cefc8860283e269dd25 # 除了10.0.0.84, 其余两个哨兵节点信息
    sentinel known-sentinel mymaster 10.0.0.82 26379 bb1518fa88dcfc481ed510d94e3ba28c54e864d2
    sentinel current-epoch 2
    

    10.3.4 手动切换主节点

    目前10.0.0.83是刚提升的主节点, 10.0.0.82和10.0.0.84为从节点

    手动下线主节点, 在任意哨兵节点完成即可

    在10.0.0.84上操作, 手动切换主节点

    [02:04:02 root@slave-2 ~]#redis-cli -p 26379
    127.0.0.1:26379> sentinel failover mymaster
    
    新的主节点变成了10.0.0.82
    1891:X 08 Mar 2021 02:13:19.894 # +switch-master mymaster 10.0.0.83 6379 10.0.0.82 6379
    
    10.0.0.82上查看sentinel信息
    
    [01:59:19 root@master ~]#redis-cli -p 26379
    127.0.0.1:26379> info sentinel
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=10.0.0.82:6379,slaves=2,sentinels=3
    

    手动切换并不是让当前的主节点下线, 只是换一个主节点而已, 原先的主节点会自动变成从节点, 通过这种方式完成的主节点切换, redis的配置文件也会被自动修改replicaof字段

    10.3.5 应用程序如何通过sentinel连接redis客户端

    在哨兵集群下, 应用程序必须通过连接sentinel来获取redis主从节点信息, 然后再连接redis, 而非直接连接redis
    

    连接过程:

    1. 客户端应用程序代码要指明所有的sentinel信息, 从这些sentinel中选出一个可用的节点
    2. 客户端向选出的哨兵节点发送get-master-addr-by-name [主从集群的名字]
    3. sentinel返回这个主从架构中master的地址
    4. 客户端应用程序向这个master发送role指令, 来确认其角色
    5. 客户端订阅sentinel的相关频道, 来获取新的master的信息变化, 并自动连接新的master

    Python实现:

    1. 准备一个额外的服务器, CentOS-7(10.0.0.187), 安装依赖包
    [02:28:16 root@python ~]#yum -y install python3 python3-redis
    
    1. 准备测试脚本
    [02:40:04 root@python ~]#vim sentinel_test.py +8
    
    #! /usr/bin/python3
    import redis
    from redis.sentinel import Sentinel
    
    # 连接哨兵服务器(ip地址, 如果有DNS也可以写主机名)
    sentinel = Sentinel([('10.0.0.82', 26379),
                        ('10.0.0.83', 26379),
                        ('10.0.0.84', 26379)], socket_timeout = 0.5)                                                                                                                    
    
    redis_auth_pass = 'redis'
    
    # mymaster是配置哨兵模式的redis主从架构的名字, 此为默认值, 实际名称按照实际情况修改
    
    # 获取主从中master服务器地址
    
    master = sentinel.discover_master('mymaster')
    print(master)
    
    # 获取从服务器地址
    
    slave = sentinel.discover_slaves('mymaster')
    print(slave)
    
    # 获取master服务器地址, 并且写入数据
    master = sentinel.master_for('mymaster', socket_timeout=0.5, password = redis_auth_pass, db = 0)
    
    w_ret = master.set('name','david')
    
    
    # 获取从服务器并进行读取(默认是round-roubin轮询)
    
    slave = sentinel.slave_for('mymaster', socket_timeout = 0.5, password = redis_auth_pass, db = 0)
    
    r_ret = slave.get('name')
    print(r_ret)
    
    # 输出: david
    
    1. 执行, 查看结果
    [02:40:03 root@python ~]#./sentinel_test.py 
    ('10.0.0.82', 6379) # master节点
    [('10.0.0.84', 6379), ('10.0.0.83', 6379)] # slave节点
    b'david' # 获取name对应的value
    

    相关文章

      网友评论

        本文标题:15. Redis 哨兵

        本文链接:https://www.haomeiwen.com/subject/mubbtltx.html