redis主从集群架构图如下:
1.sentinel 说明
(1)监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
(2)提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
(3)自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
2.redis 主从同步原理
(1)Slave服务器连接到master服务器.
(2)Slave服务器发送SYCN命令.
(3)Master服务器备份数据库到.rdb文件.
(4)Master服务器把.rdb文件传输给Slave服务器.
(5)Slave服务器把.rdb文件数据导入到数据库中.
3.架构规划
master:10.1.1.8:6379
salve1:10.1.1.11:6379
salve2:10.1.1.12:6379
salve3:10.1.1.13:6379
sentinel:10.1.1.11:26379
sentinel:10.1.1.12:26379
sentinel:10.1.1.13:26379
4.主从配置
安装redis略过
3.1.配置主从
配置主:
master:10.1.1.8
vim /etc/redis.conf daemonize yes //守护进程 pidfile "/var/run/redis.conf.pid" //pid路径 port 6379 //监听端口 bind 0.0.0.0 //绑定地址 timeout 300 //超时时间 loglevel notice //日志级别 logfile "/data/redis/redis-server.log" //日志路径 databases 16 //实例个数 save 900 1 //900秒有1个变化写磁盘 save 300 10 //300秒有10个变化写磁盘 save 60 10000 //60秒有10000个变化写磁盘 rdbcompression yes //支持RDB压缩 dbfilename "dump.rdb" //DB文件名 dir "/data/redis/lib" //RDB路径 slave-serve-stale-data yes //如果 slave-serve-stale-data 设置成 'yes' (the default) slave会仍然响应客户端请求,此时可能会有问题。 appendonly no //AOF关闭 appendfsync everysec //每秒进行一次写磁盘 no-appendfsync-on-rewrite no //append only 文件的自动重写, 当AOF 日志文件即将增长到指定百分比时,Redis可以通过调用BGREWRITEAOF 来自动重写append only文件。 list-max-ziplist-entries 512 list-max-ziplist-value 64 //如果set中整型元素的数量不超过512时,Redis将会采用该特殊编码 set-max-intset-entries 512 activerehashing yes //指定是否激活重置哈希,默认为开启 masterauth "456789" //认证密码 requirepass "456789"
配置slave1:
salve1:10.1.1.11:6379
daemonize yes pidfile "/var/run/redis/redis-server.pid" port 6379 bind 0.0.0.0 timeout 300 loglevel notice logfile "/data/redis/redis-server.log" databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename "dump.rdb" dir "/data/redis/lib" slave-serve-stale-data yes appendonly no appendfsync everysec no-appendfsync-on-rewrite no list-max-ziplist-entries 512 list-max-ziplist-value 64 set-max-intset-entries 512 activerehashing yes masterauth "456789" requirepass "456789" slaveof 10.1.1.8 6379
配置salve2:
salve1:10.1.1.12:6379
配置同slave1一致
配置salve3:
salve1:10.1.1.13:6379
配置同slave1一致
4.启动进程
启动master:10.1.1.8:
/usr/local/bin/redis-server /etc/redis.conf
启动salve1:10.1.1.11:6379
/usr/local/bin/redis-server /etc/redis.conf
启动salve2:10.1.1.12:6379
/usr/local/bin/redis-server /etc/redis.conf
启动salve3:10.1.1.13:6379
/usr/local/bin/redis-server /etc/redis.conf
查看master日志:
cat /data/redis/redis-server.log .... 16337:M 29 Apr 16:40:00.335 * DB loaded from disk: 0.000 seconds 16337:M 29 Apr 16:40:00.335 * The server is now ready to accept connections on port 6379 16337:M 29 Apr 16:40:14.757 * Slave 10.1.1.11:6379 asks for synchronization 16337:M 29 Apr 16:40:14.757 * Full resync requested by slave 10.1.1.11:6379 16337:M 29 Apr 16:40:14.757 * Starting BGSAVE for SYNC with target: disk 16337:M 29 Apr 16:40:14.757 * Background saving started by pid 16346 16346:C 29 Apr 16:40:14.765 * DB saved on disk 16346:C 29 Apr 16:40:14.766 * RDB: 6 MB of memory used by copy-on-write 16337:M 29 Apr 16:40:14.864 * Background saving terminated with success 16337:M 29 Apr 16:40:14.864 * Synchronization with slave 10.1.1.11:6379 succeeded //salve1 同步ok 16337:M 29 Apr 16:40:33.200 * Slave 10.1.1.12:6379 asks for synchronization 16337:M 29 Apr 16:40:33.200 * Full resync requested by slave 10.1.1.12:6379 16337:M 29 Apr 16:40:33.200 * Starting BGSAVE for SYNC with target: disk 16337:M 29 Apr 16:40:33.201 * Background saving started by pid 16347 16347:C 29 Apr 16:40:33.219 * DB saved on disk 16347:C 29 Apr 16:40:33.220 * RDB: 6 MB of memory used by copy-on-write 16337:M 29 Apr 16:40:33.308 * Background saving terminated with success 16337:M 29 Apr 16:40:33.308 * Synchronization with slave 10.1.1.12:6379 succeeded //salve2 同步ok 16337:M 29 Apr 16:40:35.257 * Slave 10.1.1.13:6379 asks for synchronization 16337:M 29 Apr 16:40:35.257 * Full resync requested by slave 10.1.1.13:6379 16337:M 29 Apr 16:40:35.258 * Starting BGSAVE for SYNC with target: disk 16337:M 29 Apr 16:40:35.260 * Background saving started by pid 16348 16348:C 29 Apr 16:40:35.274 * DB saved on disk 16348:C 29 Apr 16:40:35.275 * RDB: 8 MB of memory used by copy-on-write 16337:M 29 Apr 16:40:35.315 * Background saving terminated with success 16337:M 29 Apr 16:40:35.315 * Synchronization with slave 10.1.1.13:6379 succeeded //salve3 同步ok
登录主查看同步信息:
127.0.0.1:6379> info .... # Replication role:master //角色未主 connected_slaves:3 //3个slave解决 slave0:ip=10.1.1.11,port=6379,state=online,offset=71,lag=1 //salve1信息 slave1:ip=10.1.1.12,port=6379,state=online,offset=71,lag=1 //slave2信息 slave2:ip=10.1.1.13,port=6379,state=online,offset=71,lag=1 //slave3信息 master_repl_offset:71 //复制偏移量 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:70 ....
5.测试主从:
主上插入数据:
# /usr/local/bin/redis-cli 127.0.0.1:6379> set name "ckl" OK
salve1查看:
127.0.0.1:6379> get name "ckl" 127.0.0.1:6379>
salve2查看:
127.0.0.1:6379> get name "ckl" 127.0.0.1:6379>
salve3查看:
127.0.0.1:6379> get name "ckl" 127.0.0.1:6379>
6.配置sentinel
配置sentinel:10.1.1.11:26379:
port 26379 daemonize yes sentinel monitor ckl_master 10.1.1.12 6379 2 sentinel failover-timeout ckl_master 900000 sentinel auth-pass ckl_master 456789 sentinel config-epoch ckl_master 1 sentinel leader-epoch ckl_master 1 logfile "/data/redis/sentinel.log"
配置文件解释:
port 26379 #指定启动的端口 daemonize yes #后台守护进程启动 sentinel monitor ckl_master 10.1.1.12 6379 2 #让sentinel去监控名称为ckl_master 的主节点,ip为10.1.1.8 端口为6379 当两个sentinel检测到失败,才执行切换 sentinel failover-timeout ckl_master 900000 #sentinel判断master断开时间,默认为毫秒 sentinel auth-pass ckl_master 456789 #设置认证密码 sentinel config-epoch ckl_master 1 #从节点由于故障转移事件被提升为主节点时,为了取代它那失效的主节点,会把 configEpoch 设置为它赢得选举的时候的 configEpoch值。 logfile "/data/redis/sentinel.log" #指定日志路径
配置sentine2:10.1.1.12:26379:
同sentinel配置一致
配置sentine3:10.1.1.13:26379:
同sentinel配置一致
7.启动sentinel
启动sentine1:10.1.1.11:26379:
/usr/local/bin/redis-sentinel /etc/sentinel.conf
启动sentine2:10.1.1.12:26379:
/usr/local/bin/redis-sentinel /etc/sentinel.conf
启动sentine3:10.1.1.13:26379:
/usr/local/bin/redis-sentinel /etc/sentinel.conf
查看进程:
# ps -ef | grep redis root 11360 1 0 16:40 ? 00:00:03 /usr/local/bin/redis-server 0.0.0.0:6379 root 11437 1 0 18:06 ? 00:00:00 /usr/local/bin/redis-sentinel *:26379 root 11443 11306 0 18:07 pts/1 00:00:00 grep redis
查看sentinel日志:
... [11501] 29 Apr 18:06:23.656 # Sentinel runid is 2535af9a6926391270af19cb872c93a1cd499ea9 [11501] 29 Apr 18:06:23.656 # +monitor master ckl_master 10.1.1.8 6379 quorum 2 [11501] 29 Apr 18:06:23.657 * +slave slave 10.1.1.11:6379 10.1.1.11 6379 @ ckl_master 10.1.1.8 6379 //salve1同主的信息 [11501] 29 Apr 18:06:23.704 * +slave slave 10.1.1.12:6379 10.1.1.12 6379 @ ckl_master 10.1.1.8 6379 //salve2同主的信息 [11501] 29 Apr 18:06:23.711 * +slave slave 10.1.1.13:6379 10.1.1.13 6379 @ ckl_master 10.1.1.8 6379 //salve3同主的信息 [11501] 29 Apr 18:06:23.973 * +sentinel sentinel 10.1.1.12:26379 10.1.1.12 26379 @ ckl_master 10.1.1.8 6379 [11501] 29 Apr 18:06:25.133 * +sentinel sentinel 10.1.1.11:26379 10.1.1.11 26379 @ ckl_master 10.1.1.8 6379 ...
发现sentinel配置文件发生变化,增加了如下:
# Generated by CONFIG REWRITE dir "/home/chenkangle" sentinel known-slave ckl_master 10.1.1.13 6379 sentinel known-slave ckl_master 10.1.1.11 6379 sentinel known-slave ckl_master 10.1.1.12 6379 sentinel known-sentinel ckl_master 10.1.1.12 26379 3feafdc8dd9dd92bc01034ce2d059db517c2feee sentinel known-sentinel ckl_master 10.1.1.13 26379 2535af9a6926391270af19cb872c93a1cd499ea9 sentinel current-epoch 1
登录到3个sentinel中的一个查看信息:
# /usr/local/bin/redis-cli -p 26379 127.0.0.1:26379> info ...... # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=qm_master,status=ok,address=10.1.1.8:6379,slaves=3,sentinels=3 ....
8.sentinel检测主节点下线原理
主观下线和客观下线
(1)主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
(2)客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。
客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。
只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
每个Sentinel实例都执行的定时任务
(1) 每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。
(2) 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。
(3) 如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。
(4) 如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线。
(5) 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
(6) 当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除。
9.模拟测试主节点down掉:
# /usr/local/bin/redis-cli 127.0.0.1:6379> SHUTDOWN
查看sentinel日志:
# tailf /data/redis/sentinel.log ... [11501] 29 Apr 18:23:17.377 # +sdown master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:17.435 # +odown master ckl_master10.1.1.8 6379 #quorum 3/2 //3分之2检测到节点down掉 [11501] 29 Apr 18:23:17.435 # +new-epoch 2 [11501] 29 Apr 18:23:17.435 # +try-failover master ckl_master10.1.1.8 6379 //主解决故障转移 [11501] 29 Apr 18:23:17.442 # +vote-for-leader 2535af9a6926391270af19cb872c93a1cd499ea9 2 [11501] 29 Apr 18:23:17.455 # 10.1.1.12:26379 voted for 2535af9a6926391270af19cb872c93a1cd499ea9 2 [11501] 29 Apr 18:23:17.456 # 10.1.1.11:26379 voted for 2535af9a6926391270af19cb872c93a1cd499ea9 2 [11501] 29 Apr 18:23:17.534 # +elected-leader master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:17.534 # +failover-state-select-slave master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:17.634 # +selected-slave slave 10.1.1.11:6379 10.1.1.116379 @ ckl_master10.1.1.8 6379 //选举新的主节点 [11501] 29 Apr 18:23:17.635 * +failover-state-send-slaveof-noone slave 10.1.1.11:6379 10.1.1.116379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:17.711 * +failover-state-wait-promotion slave 10.1.1.11:6379 10.1.1.116379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:18.535 # +promoted-slave slave 10.1.1.11:6379 10.1.1.116379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:18.535 # +failover-state-reconf-slaves master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:18.541 * +slave-reconf-sent slave 10.1.1.13:6379 10.1.1.136379 @ ckl_master10.1.1.8 6379 //重设配置指定新的主节点 [11501] 29 Apr 18:23:19.532 * +slave-reconf-inprog slave 10.1.1.13:6379 10.1.1.136379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:19.532 * +slave-reconf-done slave 10.1.1.13:6379 10.1.1.136379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:19.584 # -odown master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:19.584 * +slave-reconf-sent slave 10.1.1.12:6379 10.1.1.12 6379 @ ckl_master10.1.1.8 6379 //重设配置指定新的主节点 [11501] 29 Apr 18:23:20.589 * +slave-reconf-inprog slave 10.1.1.12:6379 10.1.1.12 6379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:20.589 * +slave-reconf-done slave 10.1.1.12:6379 10.1.1.12 6379 @ ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:20.640 # +failover-end master ckl_master10.1.1.8 6379 [11501] 29 Apr 18:23:20.640 # +switch-master ckl_master10.1.1.8 6379 10.1.1.116379 [11501] 29 Apr 18:23:20.640 * +slave slave 10.1.1.13:6379 10.1.1.136379 @ ckl_master10.1.1.116379 [11501] 29 Apr 18:23:20.640 * +slave slave 10.1.1.12:6379 10.1.1.12 6379 @ ckl_master10.1.1.116379 [11501] 29 Apr 18:23:20.641 * +slave slave 10.1.1.8:6379 10.1.1.8 6379 @ ckl_master10.1.1.116379 [11501] 29 Apr 18:23:50.669 # +sdown slave 10.1.1.8:6379 10.1.1.8 6379 @ ckl_master10.1.1.116379
查看新选举的主节点信息:
10.1.1.11
# /usr/local/bin/redis-cli 127.0.0.1:6379> info .... # Replication role:master connected_slaves:2 slave0:ip=10.1.1.13,port=6379,state=online,offset=67708,lag=0 slave1:ip=10.1.1.12,port=6379,state=online,offset=67852,lag=0 master_repl_offset:67852 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:67851
测试新的主从同步:
10.1.1.11:6379
# /usr/local/bin/redis-cli 127.0.0.1:6379> set port "1090"
10.1.1.12:6379
127.0.0.1:6379> get port "1090"
10.1.1.13:6379
127.0.0.1:6379> get port "1090"