一.reids集群(主从复制)
1.配置步骤:
1). 修改从节点(slave)的redis.conf文件的slaveof属性(redis5.0以上版本: replicaof);
slaveof 主节点ip 主节点端口号 / replicaof 主节点ip 主节点端口号
2). 如果主节点有密码,则需要更改masterauth属性;
masterauth 主节点密码
3). 修改主节点(master)redis.conf文件的bind属性;bind属性表示:允许那个ip访问此节点;
bind 从节点ip(多个用空格隔开)/0.0.0.0(任意ip都可以访问)
4). 在启动rdis client连接redis server后,可以使用info replication命令,查看当前redis client连接的redis server的节点信息.
2.数据同步
1). 全量复制: 主节点生成快照,保存到磁盘,之后发送给从节点;新增节点时或初始化,采用全量复制;
2). 增量复制: 主节点发送相同命令给从节点,从节点执行;例: 主节点执行set A 123 命令,主节点会把这个命令发送给从节点,从节点接收后执行此命令;
3). 无磁盘复制: 主节点在内存中生成快照,不保存到磁盘,之后发送给从节点; 通过redis.conf文件总的repl-diskless-sync属性来配置; repl-diskless-sync : yes
全量复制示意图:
1). slave节点发送psync命令给master节点,命令的第一个参数:runId,第二个参数:偏移量,由于第一次复制,slave节点不知道master的runId,也不知道自己的偏移量,这时会传 ? 和 -1,通知master节点是第一次同步;
2). master接收到psync ? -1 时,就知道slave节点要全量复制,就会将自己的runId和offset告知slave节点;
3). slave节点将masterInfo保存;
4). master节点执行bgsave操作,生成一个RDB文件;
5). 将RDB发送给slave节点;
6). 将复制缓冲区记录的操作数据发送给slave节点;(主节点执行bgsave之后的数据,放在数据缓冲区中)
7). salve节点清空自己的所有老数据;
8). slave节点加载RDB文件和复制缓冲区的数据, 完成同步;
3.其他
- min-slaves-to-write(/min-replicas-to-write)属性: redis.conf文件中, 通过min-slaves-to-write(/min-replicas-to-write)属性, 来保证master节点在同步 几 个从节点之后,才可以接收下一次请求.例: min-slaves-to-write: 3;
- min-slaves-max-lag(/min-replicas-max-lag)属性: 允许从节点最大丢失时间.超过这个时间就认为从节点断开;例: min-slaves-max-lag: 10 (单位s)
- 思考: 如何保证从节点断开后,下次启动从节点时,同步master节点数据,是从slave节点上次断开处, 同步数据? —从节点中有个叫backlog日志文件, 其中有个offset属性, 改属性记录的是从主节点同步数据的断点位置,这样就可以保证数据一致.
- 从节点监听主节点同步数据命令: -->> replconf listening-port 6379 -->> sync;
- 主节点会不断发送 PING 命令,不断监测从节点,类似心跳包;
二.哨兵集群
1.概述:
redis sentinel 是一个分布式系统, 为redis提供了高可用性解决方案. 可以在一个架构中运行多个sentinel进程, 这些进程使用流言协议( gossip protocols来接收关于主节点是否下线的信息, 并使用投票协议来决定是否执行自动故障迁移, 以及选择那个从节点作为新的主节点
redis的sentinel系统用于管理多个redis节点, 该系统执行以下三个任务:
- 监控(Monitoring): sentinel会不断定期检查主节点是否运作正常;
- 提醒(Notification): 当被监控的某个redis节点出现问题时, sentinel可以通过API向管理员或者其他应用程序发送通知;
- 自动故障转移(Automaticfailover): 当一个主节点不能正常工作时, sentinel会开始一次自动故障转移操作, 它会将失效的主节点中的一个从节点升级为新的主节点, 并让失效的主节点的其他从节点改为复制新的主节点; 当客户端试图连接失效的主节点时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器;
2.配置步骤:
1). 哨兵是单独配置的,配置文件名:sentinel.conf
2). 设置 sentinel monitor < master-name > < master-ip > < master-port > < quorum > : 哨兵节点定期监控,名字为master-name,ip为master-ip,端口号为master-port的主节点. quorum: 表示哨兵判断主节点是否发生故障的票数. 也就是说如果将< quorum >设置为2,就代表至少需要2个哨兵认为主节点故障, 才算这个主节点是客观下线的了, 一般设置为 sentinel的总节点数 / 2 +1;
3). 如果主节点设置了密码,则需要设置 sentinel auth-pass < master-name > < password >, 否则哨兵无法对主节点进行监控;
4). sentinel down-after-milliseconds < master-name > < times > : 每个哨兵节点会定期发送ping命令来判断redis节点和其他哨兵节点是否可达, 如果超过了配置的 < times > 时间没有收到pong回复, 就主观判断节点是不可达的, times单位:毫秒;
5). sentinel parallel-syncs < master-name > < nums > : 当哨兵节点都认为主节点故障时, 哨兵投票选出的leader会进行故障转移, 选出新的主节点, 原来的从节点会向新的主节点发起复制, 这个配置控制在故障转移之后, 每次可以向新的主节点发起复制的节点的个数, 最多为 < nums >个, 因为如果不加控制会对主节点的网络和磁盘IO资源很大的开销;
6). sentinel failover-timeout < master-name > < times > : 哨兵进行故障转移时,如果超过了配置的 times 时间就表示故障转移超时失败;
7). 哨兵启动命令 : ./redis-sentinel 指定sentinel.conf文件位置;例: ./redis-sentinel ./sentinel.conf
3.其他:
哨兵机制的高可用: 由多个sentinel实例组成的sentinel系统可以监视任意多个主节点, 以及这些主节点下的所有从节点, 并在被监视的主节点进入下线状态时, 自动将下线主节点下的某个从节点升级为新的主节点.
哨兵的定时监控
1). 每个哨兵节点每10s会向主节点发送info命令,获取节点信息, 哨兵配置时只需要配置对主节点的监控即可,通过向主节点发送 info命令,获取从节点的信息, 并当有新的从节点加入时,可以马上感知;
Sentinel默认会以每10秒一次的频率,通过命令连接向主服务器发送info命令,通过分析info命令的回复来获取主服务器的当前信息,就像在客户端输入info replication 命令一样,Sentinel可以获取以下两方面的信息:
(1) 关于主服务器本身的信息, 包括服务器run_id, role的服务器角色。
(2) 关于所有从服务器的信息, 每个从服务器都由一个slave字符串开头的行记录, 记录了从服务器IP和端口(主服务器中 有从库的配置信息)
(3) 当Sentinel发现主服务器有新的从服务器出现时, Sentinel除了会为这个新的从服务器创建相应的实例结构(sentinel Redis Instance)之外, Sentinel还会创建连接到从服务器的命令连接和订阅连接. Sentinel默认会以每10秒一次的频率通过命令连接从服务器发送info命令, 通过分析info命令的回复来获取从服务器的当前信息. 包括:从服务器运行run_ID, 从服务器角色role, 主服务器的ip及端口, 主从服务器的连接状态master_link_status, 从服务器的优先级slave_priority.
2).每个哨兵节点每隔2s会向redis数据节点的指定频道上发送该哨兵节点对于主节点的判断以及当前哨兵节点的信息, 同时每个哨兵节点也会订阅该频道, 来了解其他哨兵节点的信息及对主节点的判断, 其实就是通过消息publish/发布和subscribe/订阅来完成的;(哨兵与哨兵之间的感知,是通过共同检测redis master感知的,实现原理也是通过publish/subscribe来实现的)Sentinel向主从服务器发送信息
在默认情况下, Sentinel会以每2秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:
PUBLISH sentinel:hello "< s_ip >,< s_port >,< s_runid >,< s_epoch >,< m_name >,< m_ip >,< m_port >,< m_epoch >"
这条命令向服务器的_sentinel_:hello频道发送了一条信息,信息的内容由多个参数组成:
(1) 以s_开头以参数记录的是sentinel本身的信息。
(2) 而m_开头的参数记录的则是主服务器的信息,如果sentinel正在监视的是主服务器,那么这些参数就是主服务器的信息,如果sentinel正在监视的是从服务器,那么这些参数记录就是从服务器正在复制的主服务器的信息。
以下是一条sentinel通过publish命令向主服务器发送的信息示例:
这个示例中sentinel的ip地址为172.0.0.1端口号为26379, 运行ID为后面一串,当前纪元为0。主服务器的名字为mymaster,ip地址为127.0.0.1,端口号为6379, 当前纪元为0。
sentinel接收来自主服务器和从服务器的频道信息
当sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:subscribe_sentinel_:hello 。对于每个与Sentinel连接的服务器,Sentinel既通过命令连向服务器的_sentinel_:hello频道发送信息,又通过订阅连接从服务器的_sentinel_:hello频道接收信息。
当有三个sentinel,分别是sentinel1、sentinel2 、sentinel3。三个sentinel在监视同一个服务器,那么当sentinel1向服务器的_sentinel_:hello频道发送一条信息时,所有订阅了_sentinel_:hello频道的sentinel(包括sentinel1自己在内)都会收到这条信息。
当一个sentinel从_sentinel_:hello频道收到一条信息时,sentinel会对这条信息进行分析,提取出信息中sentinel 的 ip 、port、runID等8个参数,并进行以下检查:
(1) 如果信息中记录的sentinel运行ID和接收信息的sentinel运行ID相同,那么说明这条信息是sentinel自己发送的,sentinel将丢弃这条信息,不做进一步处理。
(2) 相反地,如果信息中记录的sentinel运行ID和接收信息的sentinel运行ID不相同,那说明这条信息监视同一个服务器的其它sentinel发来的,接收信息的sentinel将根据信息中的参数,对相应主服务器的实例结构进行更新。sentinel更新自己的sentinels字典
sentinel为主服务器创建实例结构中的sentinels字典,保存了sentinel本身,还监视这个主服务器的其他sentinel的资料。当一个sentinel接收到其他sentinels发来的信息时,接收的sentinel会从信息中分析并提取出两方面参数:
(1)与sentinel有关的参数,包括sentinel的ip、port、runid、配置纪元。
(2)与主服务器有关的参数, 包括监视主服务器的ip、port、runid、配置纪元。
假设分别有三个sentinel: 127.0.0.1:26379、127.0.0.1:26380、127.0.0.1:26381。三个sentinel正在监视主服务器127.0.0.1:6379, 那么当127.0.0.1:26379这个sentinel接收到以下消息时:
这个sentinel将执行以下动作:
(1) 第一条信息发送者为自己,信息忽略。
(2) 第二条信息发送者为26381, sentinel会根据信息提取出内容,对sentinels字典中26381对应的实例结构进行更新。
(3) 第三条信息发送者为23680,同样更新字典中的23680对应的实例结构。
每个sentinel都有自己的一个sentinels字典, 对于26379的sentinel它的sentinels字典信息保存了26380和26381两个sentinel信息。其它sentinel也一样sentinel创建连向其他sentinel的命令连接
当sentinel通过频道信息发现一个新的sentinel时,不仅更新sentinels字典,还会创建一个连向sentinel命令连接,而新的sentinel也会创建连向这个sentinel的命令连接,最终监视同一个主服务器的多个sentinel将形成相互连接的网络。
3). 每隔1秒每个哨兵会向主节点/从节点以及其它的哨兵节点发送一次ping命令做一次心跳检测, 这个是哨兵用来判断节点是否正常的重要依据;
主观下线(Subjective Down/sdown): 所谓的主观下线, 就是单个哨兵节点认为某个redis服务下线(有可能是接收不到订阅, 或者之间的网络不通等原因);
sentinel会以 1次/s 的频率向所有与其建立了命令连接的实例(master,从服务,其他sentinel)发ping命令,通过判断ping回复是有效回复,还是无效回复来判断实例是否在线(对此sentinel借点来说是“主观在线”).
sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度, 如果实例在down-after-milliseconds毫秒内, 返回的都是无效回复, 则sentinel会认为该实例已主观下线,修改flags状态为SRI_S_DOWN. 如果多个sentinel监视一个服务, 有可能存在多个sentinel的 down-after-millisecoinds配置不同, 这个在实际生产中需要注意;
客观下线(Objective Down/odown): 当主观下线的节点是主节点时, 此时该哨兵节点会通过 sentinel 的 is-masterdown-by-addr 指令寻求其它哨兵节点对主节点的判断, 如果其它哨兵节点也认为主节点主观下线, 并且认为主观下线的票数超过了 quorum 的数量, 此时哨兵节点则认为该主节点存在问题, 该主节点客观下线;
- 哨兵leader选举流程
如果主节点被判定为客观下线后, sentinel集群就会选取一个哨兵节点(leader)来完成后面的故障转移工作, 选举leader的算法采用raft协议(raft协议/算法,详细解释:请点击这里), 选举流程:
a). 每个在线的哨兵节点都可以成为领导者,当它确认(比如哨兵3)主节点下线时,会向其它哨兵发is-master-down-by-addr命令,征求判断并要求将自己设置为领导者,由领导者处理故障转移;
b)当其它哨兵收到此命令时,可以同意或者拒绝它成为领导者;
c)如果哨兵3发现自己在选举的票数大于等于num(sentinels)/2+1时,将成为领导者,如果没有超过,继续选举… - 自动故障转移机制
在从节点中选择新的主节点: 选点的依据依次是:网络连接正常->5秒内回复过INFO命令->10*down-after-milliseconds内与主连接过的->从服务器优先级->复制偏移量->运行id较小的。选出之后通过slaveof no one将该从服务器升为新主服务器;
通过slaveof ip port命令让其他从服务器复制该主服务器; 最后当旧主重新连接后将其变为新主的从服务器. 注意如果客户端与旧主服务器分隔在一起,写入的数据在恢复后由于旧主会复制新主的数据会造成数据丢失.
故障转移成功后会通过发布订阅连接广播新的配置信息,其他sentinel收到后依据配置纪元更大来更新主服务器信息。
资料参考: https://www.cnblogs.com/Eugene-Jin/p/10819601.html