背景
这篇文章是对黄建宏第三部分的总结/学习笔记。
所谓的高可用,其实也就是这一部分介绍的几个点,即 复制 + 哨兵 + 集群。
复制
目的
复制的目的是数据一致,就是从要达到和主的数据一致。
流程
1.一开始,即初次
2.后面
一开始是发送同步命令,同步数据,数据达到一致。
后面是新的命令,主会把新的命令转发给从。
实现原理
两种方法,
1.数据法
2.命令法
断线重连
1.旧版很低效
2.新版通过部分同步,解决低效
如果断线重连,旧版每次同步所有数据,而新版只同步掉线这段时间的数据。
而且同步数据非常耗时,我们应该尽可能的减少数据的复制,特别是避免每次复制所有数据,这样就可以避免每次复制了重复的数据。
增量复制的细节
既然是增量复制,那么就要记录复制的进度。事实上,哪怕是全量复制,也有一个中介文件,即RDB文件。现在,增量复制,只是多了一个要记录进度的要求。
为什么从断线重连主的时候,可能切换主?
就是有可能连接的不是同一个主,为什么?
为什么还要弄一个缓冲区? 服务器端已经有了偏移量,为什么还要弄一个缓冲区?
为什么还要缓冲区?
心跳检测
作用
用于主从连接的检测。
基于心跳检测实现的几个功能?
异常
复制的时候,可能出现两种异常
1.长时间掉线,因为宕机了
2.短时间临时掉线,因为网络原因
如果是长时间掉线,在重连之后,也可以复制掉线这段时间的所有命令。具体实现技术是,部分丢失命令重同步。
如果是短时间临时掉线,因为网络原因,那么这个时候只是某一个命令丢失,也可以针对这一个命令进行重发。具体实现技术是,1.客户端(从节点),发送心跳 2.服务器发送丢失的某个命令。
不管是哪一种情况,长时间多命令,还是短时间临时的某一个命令,都是根据服务器端(主节点)缓冲区+偏移量来解决命令丢失然后重发的问题。
心跳本身的实现原理是什么?
首先,要理解的是,心跳的作用是什么,作用是:
1.是否可以通信
2.通信数据本身
至于具体的方式是什么还真不重要,只要能达到目的就可了:
1.ping
2.tcp socket
一般来说,心跳不光光是检查是否可以通信,而且要通信数据,所以一般就不使用ping,而且tcp socket通信。具体表现出来的形式是:
1.客户端发送数据
比如,redis的心跳包含,心跳命令名字 + 偏移量。
2.服务器接受数据
如果发现和客户端偏移量不一样,就知道刚刚的那个命令丢失了,现在要重发,即可。
心跳时间间隔
1s。如果超过1s,即认为命令丢失,需要重发丢失命令。
哨兵
先来一个图
首先,要明白一个大前提,那就是哨兵也是一个节点,只不过是一个没有数据的节点,那要它何用?监控数据节点。
哨兵节点之间互相通信吗?通信。 RocketMQ监控节点之间是不通信的。监控节点只与数据节点通信。
还有一点,每个哨兵节点是与所有数据节点保持通信(即监控)。哨兵节点之间,也是每个哨兵节点会与其他所有的哨兵节点通信,因为升级数据节点为主的时候,会选择一个leader哨兵节点。
如何配置被监控的数据节点?
有两种方式,
1.一开始就在哨兵节点配置文件配置好,然后启动的时候,加载
2.或者,先启动哨兵节点,再启动主数据节点(配置好哨兵节点),注册到哨兵节点
不管是哪一种方式,都是监控主节点,那从节点是怎么监控的呢?因为可以从主数据节点获取到从数据节点的信息,所以也就可以监控到从数据节点。
数据结构
哨兵节点和主数据节点建立连接,必须有两种连接:
1.命令
2.订阅hello
命令就是发送命令到主数据节点。
订阅hello是干嘛的?订阅就是订阅主题,目的是实现哨兵节点之间的通信。因为所有哨兵节点都订阅数据节点的同一个主题,如果有某一个哨兵节点发送数据到数据节点,那么所有哨兵节点都会收到订阅数据(包括发送数据的哨兵节点它自己也会收到,因为它也订阅了该数据节点的主题)。具体数据是1.输入数据是定时几秒发送命令2.输出数据是各个节点(哨兵节点和数据节点)的信息,比如,ip port之类的信息,如果这些信息有变更,那么就更新。
总结
哨兵和哨兵之间的通信,与哨兵和数据节点的通信是不同的。
哨兵和数据节点是直接通信,因为有配置ip port。
而哨兵如何其他哨兵,是因为每个哨兵都监控了数据节点,并且都订阅了数据节点的同一个主题,所以,只要某一个哨兵发送数据到数据节点,其他哨兵就会收到这些信息,从而就知道了别的所有哨兵的存在了(包括ip port等信息数据)。所以,哨兵之间没有直接通信,而是间接的通过数据节点的主题来通信,所以也就不需要哨兵节点之间互相配置ip port。
哨兵与哨兵的第一次通信,是通过数据节点的订阅主题间接的实现连接和通信。完成第一次通信之后,就得到了对方的信息,马上还会互相双向创建命令连接,进行命令通信,以便及时更新对方的信息。
注意
哨兵和数据节点之间,是有两种连接:1,订阅连接 2,命令连接。
而,哨兵之间,只有一种连接,那就是命令连接,因为订阅的是数据节点,哨兵之间不需要互相订阅。
订阅连接和命令连接的区别是什么?
首先,订阅连接的对象是,哨兵订阅数据节点,哨兵之间不会互相订阅;
命令连接的对象是,所有节点之间,包括哨兵/数据节点和哨兵/哨兵,注意主数据节点和主数据节点不通信。
其次,作用,订阅连接的作用是,所有的哨兵节点都要订阅同一个数据节点的同一个主题,目的是可以自动发现别的哨兵,订阅连接算是第一次通信,创建数据;而数据连接的作用是,用于后来定时更新数据。
哪些节点之间是有连接/通信的?
1.哨兵和所有的节点(包括主和从)都有连接 再细分为两种,一种是哨兵和数据节点是订阅连接+命令连接,一直是哨兵之间只有命令连接没有订阅连接因为不需要订阅连接。
2.主和自己的从/多从 + 哨兵
3.从和自己的主且只有一个主 + 哨兵
还有,连接都是异步连接,什么是异步连接?
哨兵检测数据节点是否下线 两种方法
1.主观
2.客观
如何实现?基于命令连接。
主观就是个人认为的意思,在这里是当前这个哨兵认为,具体的判断算法是,一段时间内(几十秒),一直收不到命令连接(ping命令)的响应(数据节点会组装响应数据),那么就认为数据节点下线。
而客观是,数据节点真的已经下线,什么叫真的,就是很多哨兵都检测到数据节点确实已经连接不上了,那么就认为该数据节点真的挂了。具体算法是: 1.哨兵1检测到数据节点挂了
2.哨兵1询问其他的哨兵节点是否真的挂了
3.其他哨兵节点都一致认为数据节点确实挂了
4.哨兵1就把数据节点状态置位下线
5.其他哨兵也是同理处理
至于什么叫一致认为,这个数字可配置,规定是几个,就是几个,而且每个哨兵规定的可能不一样,总之,只要最终计算得到的数量大于这个值,那么就认为是客观下线。
就算是主观下线,一段时间内,这个时间也是可配置,不同哨兵可能配置的值也不一样。
总结
虽然下线有两种,但是判断一个数据节点是否下线的标志是,主观和客观都要满足。主观是单个哨兵认为下线,并记录下线信息,客观是配置数量的哨兵互相通信得到对方的下线信息,然后计算数量,最终才确认下线。
下线之后,怎么办?选择新的主数据节点。具体步骤是:
1.哨兵之间先选一个leader哨兵
2.leader哨兵实现故障转移,说是故障转移,其实就是升级其中的某一个从数据节点为主,降级主数据节点为新的主节点的从
选leader哨兵的算法?
1.输入数据
包含字段:
1)是否下线 //0未下线,1下线
2)是检测是否下线还是选leader //*检测是否下线,当前哨兵runId就是选leader
3)计数 //一开始是0
说明
由于选leader的命令和检测是否下线的命令是同一个命令,只是有个参数不同,用于标识当前命令是选Leade还是检测是否下线。
2.输出数据
包含字段:
1)是否下线 //0未下线,1下线
2)是检测是否下线还是选leader //*检测是否下线,当前哨兵runId就是选leader
3)计数 //如果同意,每次加1
关于计数
举个例子
1.哨兵1申请哨兵2,成功,加1
2.哨兵1申请哨兵3,成功,再加1
3.哨兵1的计数现在是2,过半,成为leader
注:什么纪元不纪元,其实就是计算数量。每次申请别人是否同意自己成为leader,如果同意,这个字段的值就加1,最终总数超过一半的哨兵,那么就是leader。因为申请的时候,有先后顺便,谁最先过半,谁就是leader。
选从数据节点的算法?
按以下几项的先后顺序,依次进行排序,最终得到一个从数据节点。
1.是否下线
2.优先级
3.偏移量 4.服务器id
细节如下
首先,得到所有的节点的集合。
是否下线指,1.过滤已经下线的(客观下线)2.过滤几秒之内没有响应的(主观下线)3.过滤几毫秒之内没有响应的(临时网络问题),总之,就是过滤掉下线或网络通信不好的。
剩下的,再按优先级排序。优先级是指?所有的任何一个优先级,都是一个值为数字的字段,比如线程优先级,或者应用程序里经常会使用到的优先级。
偏移量最大,说明数据最新。
最后,服务器id排序。
完成,选出一个从数据节点。
节点之间通信的几种不同类型?
1.订阅连接
2.命令连接
3.info命令
4.ping
前面两种是连接,命令包括设置这样的操作,比如设置从为主(slaveof no one)。 info和ping是为了获取状态信息,即是否通信正常等。
但凡是涉及到监控通信状态是否正常的,基本上都是几秒一次。
slaveof no one,表示设置为主,slaveof ip port,表示设置为ip/port的从,slaveof 参数,这个命令是由哨兵发出的。
如何监控节点
如何选择升级节点
步骤
1.先选择一个哨兵leader
2.再选择一个从节点进行升级
这里面最重要的是如何选择,即选择的算法是什么。
集群
参考
黄建宏