主从复制:将一台redis服务器复制到其他服务器上,前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。默认情况下每个redis都是一个独立的主节点,且一个主节点可以有多个从节点,但一个从节点只能拥有一个主节点。
作用:实现了数据的热备份,是持久化存储的一种冗余方式,当一台redis服务器出现故障以后可快速切换到其他服务器内。在主从复制的基础上,配合读写分离,由主节点提供写入,从节点提供读取,分担服务器负载,大大的提高了redis服务器的并发量。
主从复制流程全量同步:出现在slave初始化的阶段,从节点链接主节点发送sync,主节点收到sync命令以后启动一个进程,将数据快照保存到数据文件中,并把当前快照后的操作命令记录到缓冲区中。执行完之后向所有从节点发送快照文件,并在发送期间继续记录修改数据。从节点收到快照文件以后丢弃缓存中的数据,从快照文件中载入新的数据。主节点发送完快照以后会向从节点发送缓冲区中的命令,从节点执行完快照文件以后接收主节点的命令并执行来自主服务器缓冲区的操作命令。
增量同步:出现在slave初始化后的阶段,主节点每执行一个操作指令就向从服务器发送一个指令,从服务器接收并执行。
同步策略:主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
搭建redis主从复制楼主本次使用的环境是一主二从,如果不会搭建redis服务器的话可以看看之前写的
192.168.0.115 redis-master
192.168.0.111 redis-slave
192.168.0.114 redis-slave
首先修改master服务器中的配置文件
bind * protected-mode no daemonize yes logfile /var/log/redis.log
在修改slave服务器中的配置文件
bind * protected-mode no daemonize yes logfile /var/log/redis.log replicaof 192.168.0.115 6379 #主节点的ip和端口号 #masterauth redis #主节点服务器的密码,无可不写
需要先启动主服务器,在启动从服务器
[root@master ~]# cd /usr/local/redis-6.2.7/ && bin/redis-server redis.conf [root@slave1 ~]# cd /usr/local/redis-6.2.7/ && bin/redis-server redis.conf [root@slave2 ~]# cd /usr/local/redis-6.2.7/ && bin/redis-server redis.conf
在主服务器看看是否成功运行了
[root@master redis-6.2.7]# bin/redis-cli 127.0.0.1:6379> auth redis OK 127.0.0.1:6379> info replication # Replication role:master #角色 master connected_slaves:2 #2个从节点 slave0:ip=192.168.0.111,port=6379,state=online,offset=2268,lag=1 #从节点 slave1:ip=192.168.0.114,port=6379,state=online,offset=2268,lag=0 #从节点 master_failover_state:no-failover master_replid:7cd4375acd4d0f8ffab807c65ac6f79707aee5c8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:2268 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2268 127.0.0.1:6379> set test 1 #在主节点上设置一个key OK 127.0.0.1:6379>
在从服务器上查看是否能看到key,如果可以看到那就证明主从已经搭建成功
[root@slave1 redis-6.2.7]# bin/redis-cli 127.0.0.1:6379> auth redis OK 127.0.0.1:6379> info replication # Replication role:slave #角色 从节点 master_host:192.168.0.115 master_port:6379 master_link_status:up master_last_io_seconds_ago:2 master_sync_in_progress:0 slave_read_repl_offset:2433 slave_repl_offset:2433 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:7cd4375acd4d0f8ffab807c65ac6f79707aee5c8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:2433 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2433 127.0.0.1:6379> get test #成功看到test key的值 "1" 127.0.0.1:6379>哨兵模式
当我们主从模式中主服务器一旦宕机无法使用,那么需要人工干预去指定一台主服务器,同时还要通知应用方更新主节点地址,增加了我们的人力成本,对于很多应用场景这种故障处理的方法是无法接受的。但是Redis从2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。
哨兵核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移。
实现原理:
三个定时监控任务
1)每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构。
2)每隔2秒,每个Sentinel节点会向Redis数据节点的__sentinel__:hello频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息,同时每个Sentinel节点也会订阅该频道,来了解其他Sentinel节点以及它们对主节点的判断。
3)每隔一秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,来确认这些节点当前是否可达。
主观下线
因为每隔一秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,当这些节点超过down-after-milliseconds没有进行有效回复,Sentinel节点就会对该节点做失败判定,这个行为叫做主观下线。
客观下线
当Sentinel主观下线的节点是主节点时,该Sentinel节点会向其他Sentinel节点询问对主节点的判断,当超过
领导者Sentinel节点选举
Raft算法:假设s1(sentinel-1)最先完成客观下线,它会向其余Sentinel节点发送命令,请求成为领导者;收到命令的Sentinel节点如果没有同意过其他Sentinel节点的请求,那么就会同意s1的请求,否则拒绝;如果s1发现自己的票数已经大于等于某个值,那么它将成为领导者。
故障转移
1)领导者Sentinel节点在从节点列表中选出一个节点作为新的主节点
2)上一步的选取规则是与主节点复制相似度最高的从节点
3)领导者Sentinel节点让剩余的从节点成为新的主节点的从节点
4)Sentinel节点集合会将原来的主节点更新为从节点,并保持着对其关注,当其恢复后命令它去
搭建哨兵模式还是用我们刚刚搭建好的主从环境
192.168.0.115 redis-master
192.168.0.111 redis-slave
192.168.0.114 redis-slave
哨兵配置文件详解
# 哨兵sentinel实例运行的端口,默认26379 port 26379 # 哨兵sentinel的工作目录 dir ./ # 是否开启保护模式,默认开启。 protected-mode:no # 是否设置为后台启动。 daemonize:yes # 哨兵sentinel的日志文件 logfile:./sentinel.log # 哨兵sentinel监控的redis主节点的 ## ip:主机ip地址 ## port:哨兵端口号 ## master-name:可以自己命名的主节点名字(只能由字母A-z、数字0-9 、这三个字符".-_"组成。) ## quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了 sentinel monitor mymaster 127.0.0.1 6379 2 # 当在Redis实例中开启了requirepass,所有连接Redis实例的客户端都要提供密码。 sentinel auth-pass mymaster redis # 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒 sentinel down-after-milliseconds mymaster 30000 # 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。 sentinel parallel-syncs mymaster 1 # 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面: ## 1. 同一个sentinel对同一个master两次failover之间的间隔时间。 ## 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。 ## 3. 当想要取消一个正在进行的failover时所需要的时间。 ## 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了 sentinel failover-timeout mymaster 180000 # 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。 # 对于脚本的运行结果有以下规则: ## 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。 ## 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。 ## 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。 sentinel notification-script mymaster /var/redis/notify.sh
修改所有节点下的哨兵配置文件
daemonize yes logfile /var/log/sentinel.log sentinel monitor mymaster 192.168.0.115 6379 2 sentinel auth-pass mymaster redis sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 180000
启动哨兵
[root@master redis-6.2.7]# bin/redis-sentinel sentinel.conf [root@slave1 redis-6.2.7]# bin/redis-sentinel sentinel.conf [root@slave2 redis-6.2.7]# bin/redis-sentinel sentinel.conf
查看哨兵信息,可以看到1个主节点2个从节点和三个哨兵
[root@master redis-6.2.7]# bin/redis-cli -p 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=192.168.0.115:6379,slaves=2,sentinels=3
模拟主节点故障
[root@master redis-6.2.7]# ps -aux | grep redis root 2142 0.2 0.9 165076 9524 ? Ssl 01:19 0:01 bin/redis-server *:6379 root 2165 0.3 0.9 162624 9868 ? Ssl 01:21 0:01 bin/redis-sentinel *:26379 [sentinel] root 2233 0.0 0.0 112824 984 pts/0 S+ 01:26 0:00 grep --color=auto redis [root@master redis-6.2.7]# kill 2142
在从节点查看,发现192.168.0.111由从节点已经变成了主节点,另一个从节点自动指向主节点
[root@slave1 redis-6.2.7]# bin/redis-cli 127.0.0.1:6379> info replication Error: Server closed the connection 127.0.0.1:6379> auth redis OK 127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave0:ip=192.168.0.114,port=6379,state=online,offset=72576,lag=0 master_failover_state:no-failover master_replid:8759df6c607af24503e6686713632a8c22e22987 master_replid2:3b1aca7e017a45ac47be8232d309d7d5163cce82 master_repl_offset:72717 second_repl_offset:70989 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:50968 repl_backlog_histlen:21750 127.0.0.1:6379>
我们在启动原来的主节点看看会发生什么变化
[root@master redis-6.2.7]# bin/redis-server redis.conf [root@master redis-6.2.7]# bin/redis-cli 127.0.0.1:6379> auth redis OK 127.0.0.1:6379> info replication # Replication role:slave master_host:192.168.0.111 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_read_repl_offset:130928 slave_repl_offset:130928 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:8759df6c607af24503e6686713632a8c22e22987 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:130928 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:122249 repl_backlog_histlen:8680 127.0.0.1:6379>
可以看到,当主机挂了的时候,哨兵选举从节点成为新的主节点,主节点恢复以后,变为了从节点并指向了新的主节点。



