Redis学习(四)Redis主从、哨兵、集群

Redis学习(四)Redis主从、哨兵、集群

Redis主从复制

什么是主从复制

在这里插入图片描述

主对外从对内,主可写,从不可写

主挂了,从不可为主

主从配置

主Redis配置

主Redis无需特殊配置

从Redis配置

修改redis.conf文件:

# slaveof <masterip> <masterport>
# 表示当前【从服务器】对应的【主服务器】的IP是127.0.0.1,端口是6379。
slaveof 127.0.0.1 6379
实现原理
  • Redis的主从同步,分为全量同步增量同步
  • 只有从机第一次连上主机是全量同步
  • 断线重连有可能是全量同步也有可能是增量同步(master判断runid是否一致)
  • 除此之外全部都是增量同步

在这里插入图片描述

全量同步

Redis的全量同步过程主要分为3个阶段:

  • 同步快照阶段:Master创建并发送快照RDB给Slave,Slave载入并解析快照。Master同时将此阶段所产生的新的写的命令存储到缓冲区
  • 同步写缓存阶段:Master向Slave同步存储在缓冲区的写操作命令
  • 同步增量阶段:Master向Slave同步写操作命令

在这里插入图片描述

增量同步
  • Redis增量同步主要指Slave完成初始化后开始正常工作时,Master发生写操作同步到Slave的过程。
  • 通常情况下,Master每执行一个写命令就会向Slave发送相同的写命令,然后Slave接受并执行。

Redis哨兵机制

Redis主从复制的缺点:没有办法对master进行动态选举(Master宕机后,需要重新选举master),需要使用sentinel机制完成动态选举。

Redis的哨兵模式到了2.8版本之后

Sentinel(哨兵)进程是用于监控Redis集群中Master主服务器工作的状态

在Master主服务器发生故障时,可以实现Master和Slave服务器的切换,保证系统的高可用(HA)

哨兵进程的作用

  • 监控(Monitoring):哨兵(Sentinel)会不断的检查Master和Slave是否运作正常
  • 提醒(Notification):当监控的某个Redis节点出现问题时,哨兵(Sentinel)可以通过API向管理员或者其他应用程序发送通知
  • 自动故障迁移(Automatic Failover):当一个Master不能正常工作时,哨兵(Sentinel)会开始一次自动故障迁移操作
故障判定原理

在这里插入图片描述

  1. 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器、Slave从服务器、以及其他的Sentinel(哨兵)进程发送一个PING命令
  2. 如果一个实例(instance)距离最后一次有效回复PING命令的时间超过down-after-milliseconds选项所指定的值,则这个实例会被Sentinel(哨兵)进程标记为主观下线(SDOWN)
  3. 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入主观下线状态。
  4. 当有足够数量的Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN),则Master主服务器会被标记为客观下线(ODOWN)
  5. 在一般情况下,每个Sentinel(哨兵)进程会议每10秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送INFO命令
  6. 当Master主服务器被Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的Master主服务器的所有Slave从服务器发送INFO命令的频率会从10秒一次改为1秒一次
  7. 若没有足够数量的Sentinel(哨兵)进程同意Master主服务器下线,Master主服务器的客观下线状态就会被移除,若Master主服务器重新向Sentinel(哨兵)发送PING命令返回有效回复,Master主服务器的主观下线状态就会被移除
自动故障迁移
  • 它会将失效的Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master
  • 当客户端试图连接失效Master时,集群也会返回新的Master的地址,集群可以使用现在的Master替换失效的Master
  • Master和Slave服务器切换后,Master的redis.conf、Slave的redis.conf和Sentinel.conf的配置文件内容都会发生相应的改变,即Master主服务器的redis.conf配置文件中会多一行Slaveof的配置,sentinel.conf的监控目标也会随之调换
其他配置项说明

sentinel.conf

# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数的sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
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 <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

通过redis-sentinel启动哨兵服务

./redis-sentinel sentinel.conf

Redis集群

Redis-cluster架构图

Redis3以后,官方的集群方案 Redi-Cluster

Redis3 使用lua脚本实现

Redis5 直接实现

在这里插入图片描述

在这里插入图片描述

架构细节
  1. 所有的redis主节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效
  3. 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  4. redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护

node<->slot<->value

Redis 集群中内置了 16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

在这里插入图片描述

Redis-cluster投票:容错

在这里插入图片描述

  1. 主节点投票,如果超过半数的主都认为某个主节点down了,则该主节点就down了(主选择单数)
  2. 主节点设置,选出挂了的主节点的从节点升级为主节点
集群宕机的情况
  • 半数的主节点都挂了,不能投票生效,则集群就挂了
  • 挂了的主机的从机也挂了,造成slot槽分配不连续(16384不能完全分配),集群就挂了

Redis集群最少需要三台主服务器,三台从服务器。

本地搭建redis伪集群
端口号分别为:7001~7006
1.创建7001实例,并编辑redis.conf文件,修改port为7001。
2.修改redis.conf配置文件,打开cluster-enable yes
3.复制7001,创建7002~7006实例,注意端口修改。
4.启动所有的实例
5.创建Redis集群
./redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1


客户端连接集群
./redis-cli -h 127.0.0.1 -p 7001 -c
-c 表示以集群方式进行连接

查看集群状态
cluster info

查看集群中的节点
cluster nodes
维护节点

集群创建成功后可以继续向集群中添加节点

添加主节点

1.先创建7007节点
2.添加7007结点作为新节点,并启动,执行命令
	./redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
hash槽重新分配(数据迁移)

添加完主节点需要对主节点进行hash槽分配,这样主节点才可以存储数据

redis集群由16384个槽,及群中的每个节点分配槽,通过查看集群节点可以就看到槽占用情况。

1.给刚添加的7007结点分配槽
	./redis-cli --cluster reshard 127.0.0.1:7007
2.输入要分配的槽数量
	How many slots do you want to move (from 1 to 16384)? 3000
输入:3000,表示要给目标节点分配3000个槽
3.输入接收槽的结点id
	What is the receiving node ID?
4.输入源结点id
    Please enter all the source node IDs.
        Type 'all' to use all the nodes as source nodes for the hash slots.
        Type 'done' once you entered all the source nodes IDs.
    输入:all
5.输入yes开始移动槽到目标结点id
添加从节点
添加7008从结点,将7008作为7007的从结点
./redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave  --cluster-master-id 主节点id
注意:如果原来该结点在集群中的配置信息已经生成到cluster-config-file指定的配置文件中(如果cluster-config-file没有指定则默认为nodes.conf),这时可能会报错:
[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (checkwith CLUSTER NODES) or contains some key in database 0

解决方法是删除生成的配置文件nodes.conf,删除后再执行./redis-trib.rb add-node指令
删除节点
./redis-cli --cluster del-node 127.0.0.1:7008  需要删除的节点id

删除已经占有hash槽的结点会失败,报错如下:

[ERR] Node 127.0.0.1:7008 is not empty! Reshard data away and try again.

需要将该结点占用的hash槽分配出去(参考hash槽重新分配章节)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值