Redis学习:Redis哨兵(Sentinel)、Redis集群(Cluster)
文章目录
1. Redis哨兵(Sentinel)
1. 是什么
- 哨兵和主从复制结合使用,来提高可用性
- 在Redis主从复制时,当主机宕机时,则此时从机也会原地待命等待主机恢复,不会选举一个新的主机,此时就无法保证高可用
- 故引入哨兵对整个主从集群进行监控,当主机宕机时,由哨兵根据选举算法选举一个从机作为新的主机,实现主从互换和高容错备份
- 哨兵监控redis的状态,当master宕机时,会根据投票数自动选举一个从机作为新的主机
- 哨兵的作用就是监控redis的状态(包括master和slave),当master宕机时,选举一个slave变成新的哨兵
2. 能干嘛
- 每个客户端只是一个master或者一个slave,而哨兵要监控主从redis,即一个哨兵要监控多个redis服务器和客户端
- 主从监控:监控主从redis库运行是否正常
- 消息通知:可以将故障转移的结果发给客户端
- 故障转移(自动容错):如果master异常,会自动进行主从切换,将其中一个slave转换为master
- 配置中心:客户端(master或者slave)通过连接哨兵来获得当前Redis服务的主节点地址
3. 怎么玩
- 架构
- 三台哨兵,自动监控和维护集群,不存放数据,只监控redis服务器
- 哨兵不存放数据,只监控redis服务器,也是个redis服务器,故也需要端口号进行启动
- 之所以要有哨兵集群,是为了防止哨兵和master都宕机,故多设置几个哨兵,并且当master宕机后,由多台哨兵进行投票来选举新的master
- 并且master宕机必须多台哨兵都认为master宕机时才会认为是宕机
- 哨兵不存放数据,只起到监控作用,并在发现master出现错误后进行故障转移
- 哨兵不存放数据,只进行监控
- 配置(会被动态修改)
- 将redis中自带的sentinel.conf配置文件拷贝出来,并对自己的哨兵进行配置,然后根据该配置文件对哨兵进行启动
- sentinel.conf配置文件基础配置和redis服务器一样,但要对sentinel的配置进行单独配置,指定要监控的redis_master主服务器和quorum客观最少下线次数,以及所监控的master的密码
- 在sentinel.conf中对 sentinel monitor配置项进行配置,来指定该哨兵所监控的redis主从服务器以及指定quorum:确认客观下线的最少哨兵数量,即对于监控的该master,只有当至少quorum个哨兵认为master挂掉才是真正的挂掉
- 因为网络原因,某个哨兵可能误以为master挂掉,此时是主观下线,但不是真的挂掉,故要配置quorum配置项,指定客观下线的最少哨兵数量
- 也可以配置主观下线的时间,当超过这个时间,该哨兵就会认为当前监控的主机master发生了宕机,当有quorum个哨兵认为master主观下线,则该master会被认为客观下线
- 启动主从redis
- 哨兵的默认端口号是26379,和redis服务器的6379不一样
- 对每个哨兵均要创建一个配置文件,并设置基础配置以及与哨兵有关的配置项,然后对该配置文件启动服务器就可开启哨兵
- redis主从复制配从不配主,只对slave服务器进行配置来指定master的IP和PORT,如果有密码也要设置密码权限,此时就可开启主从复制
- master主机不需要进行配置,配从不配主,但要对master设置密码配置项masterauth “password”,以防止该服务器变为从机,故要设置访问新主机的密码
- 虽然是配从不配主,但也要对主机的conf文件中配置masterauth配置项,以防止该主机后续变为从机后要访问新的主机
- 配置完成后根据conf配置文件来启动对应的redis主从服务器以及哨兵服务器,然后使用 info replication来查看主从信息,从机不可写入只可读取,只有主机才可以写入
- 启动哨兵集群
- 为了防止master和哨兵全部宕机,故要设置多个哨兵进行监控
- 实战
- 去官网查看使用方法,出现错误先看日志
- 要指定哨兵所监控的master,然后哨兵会通过master来自动获得其slave的信息,指定哨兵所监控的master服务器
- 且启动哨兵后会自动对哨兵的配置文件添加一些配置项,配置文件会动态修改
- 当master宕机时,所有的从机会先断开连接,此时由哨兵先选举出leader,然后从slave中选举出新的master,然后发送心跳包重新连接,当选举结束后,从机就都会连接,此时会选择对应的从机变为新的master,并修改配置文件
- 而且会对已经宕机的master修改配置文件,使其变为新的master的slave,此时就算原来的master重新连接,依旧不会变为master,而是作为新的master的slave
- 当master宕机后,哨兵会先认为是主观下线(可以通过配置项来设置客观下线的时间),当有quorum个哨兵认为是主观下线时,该master就会被认为是客观下线
- master宕机后会变为新选举的master的slave,此时就算重新恢复也不会变为master
- 可以查看log文件来查看执行过程
- 问题及总结
- Broken Pipe:断开的管道,当master宕机后,此时主从之间的管道会断开,数据会中断,如果访问过快就会出现该错误,只需要等待一会就会恢复
- 当master宕机时,哨兵Sentinel会先认为主观下线(通过配置项配置最大连接时间,超过就会认为是主观下线),然后进行投票,当有quorum个哨兵都认为是主观下线时就会对该master认为是客观下线,此时就会从slave中选举新的master,然后会对所有的master和slave的配置进行修改,此时原来的master会变为新master的slave,原来的slave会变为新的master的slave
- 因为原来的master如果恢复后会变为新的master的slave,故必须在原来的master的配置文件中设置masterauth配置项
- 当重新选举后,所有sentinel的配置文件conf均会被动态修改,此时配置文件中的master会变为新选举的master的IP和PORT,其他配置项也会物理修改;所有的master和slave的redis服务器的配置文件也会被修改!!!
- 当主从切换时候,master和slave已经sentinel的配置文件均会被动态修改
- 很少出现所有的sentinel全部宕机失效的情况
- 一个哨兵可以同时监控多个master,对每组指定一个name,并对相应的name进行配置,一个哨兵可以监控多个master
4. 运行流程和选举原理
- 当哨兵监控的master发生故障失效后,会由sentinel投票选举出新的master,并对master、slave以及sentinel修改配置文件;哨兵数量一般采取奇数台
- SDown(Subjectively Down)主观下线
- 主观下线是该sentinel所监控的master超过设置的时间未响应而认为是主观下线
- 主观下线SDown时单个sentinel主观上检测到的master的状态,可以在配置文件中进行配置超时时间,当sentinel发出了PING心跳包后,master超时未响应就会认为是主观下线
- 一个哨兵认为主观下线不可以认为master就是宕机的
- 只有当认为该master主观下线的sentinel的个数大于等于配置的quorum个时,该master才会被认为客观下线
- ODown(Objectively Down)客观下线
- 只有多个哨兵都认为该master主观下线后,才可以认为该master客观下线
- 只有master客观下线后才会重新进行选举新的master
- 通过在sentinel monitor配置项中设置对该master的quorum,即只有当主观下线的个数大于等于quorum后才会被认为是客观下线
- quorum是客观下线的依据
- 通过Raft算法选举出**领导者哨兵leader
- 第一个发现master主观下线的sentinel会成为leader,然后由leader来选举新的slave成为master
- 先通过Raft算法选举出leader领导者哨兵后,再由leader哨兵选举出master
- 当master认为客观下线(ODown)后,会选举新的master,此时会先选举出领导者哨兵,由领导者哨兵来选举新的master,并不是所有的哨兵来选举新的master,而是先选举领导者哨兵,然后由领导者哨兵来选举新的master(failover故障迁移)
- 通过Raft算法来选举出leader哨兵,Raft算法是先到先得(早起的鸟儿有虫吃),某个哨兵向别的哨兵发送leader申请,别的哨兵只会同意第一个申请
- 判断主观下线的哨兵节点向其他哨兵节点发送master宕机,如果超过半数的哨兵节点判断master节点进入客观下线的状态,那么率先判断进入主观下线的哨兵将成为领头sentinel
- 当某个哨兵认为当前的master发生宕机后,就会向监控该master的其他哨兵发送信号,如果认为主观下线的哨兵数量大于quorum时,就会认为该master客观下线,此时第一个发现主观下线的哨兵就会被认定为leader哨兵,由其来进行新的master的选举
- 由leader哨兵选举新的master进行failover故障迁移
- 新主登基:选举新的master
- 根据优先级priority越高、offset大的以及RUNID小的来从健康的slave中选举出新的master
- 从剩余的健康的slave中选举出新的master:priority(高) -> replication offset(大) -> Run ID(小)!
- 先根据slave的priority来选举,谁的priority高就选举谁为新的master,priority可以在配置文件中进行配置,越小优先级越高
- 如果priority一样的话,则谁的replication offset(复制偏移量,越大则数据越多)大选举谁为新的master,replication offset是当前slave的数据同步位置,因为延迟所有不一定同步
- 如果replication offset一样时,则根据Run ID最小的作为新的master
- 群臣俯首:slave改变master
- 选举出新的master后,sentinel会对新master执行 slaveof no one 命令使其变为master,并通过slaveof命令使得其余的slave变为新master的slave,且原来的master也会变为新master的slave
- 在master切换过程中,会动态的修改sentinel、master和slave的配置文件
- 故障迁移过程中会动态修改slave、master和sentinel的配置文件,当选举出新的master后,会修改该服务器的配置文件变为master,然后对所有的slave修改配置文件使其成为新master的slave,并修改sentinel的配置文件监控新的master
- 旧主拜服:原master变为slave
- 在选举出新的master后,原来的master也会变为新master的slave
- 此时原来master重新连接时,就会变为slave,故要在master中也要设置访问master密码的参数项masterauth
- 上述流程均由sentinel独立完成,无需人工干预
- 新主登基:选举新的master
5. 使用建议
- 哨兵集群+主从复制并不可以保证数据零丢失!!
- 哨兵集群+主从复制,并不可以保证数据零丢失!!!,因为当宕机到选举新的master会用很长时间,此时就不可以写入新数据。使用集群!!
- 哨兵应该设置多个且为奇数,应该为集群来保证高可用
- 各个哨兵节点的硬件配置应该一致
2. Redis集群(Cluster)
1. 是什么
- 由于数据量过大,单个master复制集难以承担,因此对多个复制集进行集群,形成水平扩展,每个复制集只负责存储整个数据的一部分,这就是redis集群
- 重点是集群的算法和架构
- redis集群就是对外一个整体,内部包含多个实例
- redis集群就是一个提供在多个redis之间共享数据的程序集,允许有多个master,redis集群就是多个master构成的共享数据集
2. 能干嘛
- 集群允许多个master,每个master可以多个slave,且这些master共享数据集
- 集群cluster内置了sentinel,可以自动实现故障转移,不需要再使用哨兵(先通过Raft算法得到leader,然后再选举新的master)
- 集群cluster自带sentinel的故障转移机制,内置了高可用支持,无需再使用sentinel
- 一个集群中有多个master共享数据,所以客户端不需要连接集群中的所有节点,只需要连接一个可用节点即可,但要使用 -c 集群模式(路由分发)开启客户端
3. 集群算法:分片、槽位slot
- 分布式key模式介绍
- redis集群共有16384个slot槽位,且最多配置1000个master节点,每个节点均匀管理着部分槽位
- redis槽位slot有16384个,集群节点master最大1000个
- 集群的每个master节点处理槽位的一部分子集
- redis集群的槽位slot
- redis一共有16384个槽位slot,每个槽位均可以存放数据,且每个master节点(最多1000个)管理一部分槽位
- redis没有使用一致性hash,而是使用了hash槽概念,对于每一个key,先通过算法得到其存放的槽位
- redis集群的分片
- 每个master服务器就是一个分片,每个分片管理着一部分slot槽位
- redis集群会将存储的数据分散到多个master_redis机器上,这就成为分片,即集群中的每个master_redis节点实例都被认为是一个分片,每个分片管理集群槽位slot的一个子集
- 当读写数据时,根据key通过哈希槽算法找到对应槽位slot,然后取模找到管理该槽位的分片(master_redis节点),对该redis服务器进行读写操作即可
- 优势
- 方便扩缩容和数据分派查找
- 当需要扩缩容时,只需要将槽位移动到新增的节点上,或者移出去即可,此时并不会停止服务,不会造成集群不可用,不需要重新洗牌,不会对已经存放的数据造成影响
- slot槽位映射方式
将数据的key映射到对应的槽位slot的算法- 哈希取余分区
- 直接对集群中master_redis节点的数量进行取余来确定将key存放到哪个redis中
- 优势:容易进行计算映射关系
- 缺点:不易扩缩容,此时需要重新进行映射,且原来的数据的映射关系会发生错误,要重新洗牌
- 一致性哈希算法分区
- 为了解决分布式缓存数据变动和映射问题,固定值取模,使得每个key的hash值不会发生改变
- 目的是当服务器个数变动时,尽量减少影响客户端到服务器的映射关系,对于哈希取余算法,当扩缩容时,会导致映射分母改变,此时原来的映射关系均发生
- 即使用固定值进行取模形成哈希环,此时每个key的哈希值是不变的,然后对每个节点根据ip找到对应的位置,然后对key找到对应的位置后顺时针寻找最近的节点进行存储,此时当扩缩容时,只会对对应节点附近的数据有影响,但可能会造成数据切斜
- 三大步骤
- 算法构建一致性哈希环
- 形成一个首尾相连的环形全量哈希空间,使得key的哈希值的范围不受分母的影响(对全量集进行取模)
- 服务器IP节点映射
- 将各个服务器根据某个规则进行哈希映射确定在哈希环中的位置
- key落到服务器的落键规则
- 先对key根据hash函数确定在节点中的位置,然后顺时针行走遇到的第一台服务器就是存储的节点![[Pasted image 20241028130334.png]]
- 算法构建一致性哈希环
- 优点:容错和扩展
- 具有容错性,当某一个节点宕机的时候,只会影响某一段的数据,而且可以继续寻找下一个服务器进行存储
- 具有扩展性,当扩展一个节点时,不需要对所有的数据进行重新洗牌
- 缺点:数据倾斜(分布不均匀)
- 当节点很少时,可能会导致大部分数据全落到一个节点上
- 哈希槽分区
- 是什么
- 因为一致性哈希算法存在数据倾斜问题,故引入哈希槽算法,设置固定数量的hash槽16384个,让每个key求hash后%16384得到对应的槽位(固定的,不会被节点影响),而且对每个节点均匀分配所管理的哈希槽,此时当扩缩容时,只需要修改节点所对应的哈希槽即可,不需要修改数据
- 哈希槽的是指就是一个数组,共2^14个槽slot,共有16384个哈希槽slot
- 其在数据和节点之间加了一层哈希槽(没有什么是加一层解决不了的),用于管理数据和节点之间的映射关系,相当于节点上放的是槽slot,槽中放的是数据
- 哈希槽数目是固定的(故每个key对应的哈希槽也是固定的),对每个节点都分配一定数量的哈希槽(大致均匀),此时只需要在对应的哈希槽中找数据即可
- 哈希槽的计算
- 先对数据的key进行哈希函数得到哈希值,然后对16384取模得到映射的哈希槽位置,然后根据槽和节点的映射就可以得到对应的节点,此时就得到了key和节点的映射关系
- 为什么redis集群的最大槽数是16384?
- 可以节省大量的空间来存储,使得心跳包(包含完整配置信息)的大小变得更小,不需要那么多(最多1000个节点,每个平均16个槽就够了);用bitmap存储压缩比高,传输容易
- redis心跳包中会包含节点的完整配置,如果使用2^16 个槽,此时槽的配置项的大小会很大(每个节点的槽要8k,共65k个槽),而如果使用2^14 个槽,此时空间为2k * 16k ,会大量节省空间消耗
- 而且规定的redis集群中节点的个数不超过1000个(节点太多时会导致网络拥堵),所以不需要太多的插槽,故16384个就足够了,均匀分配每个节点16个左右
- redis底层对于节点对应的哈希槽是通过bitmap来存储的,在传输过程中会压缩,槽位越少,空间越小,压缩比越高,传输越容易
- 是什么
- 哈希取余分区
- redis集群不保证强一致性(cp),在特定情况下会写丢失,如果某个master宕机后还未来得及同步时,此时就会写丢失,加一层会解决大部分问题,但也会出现新的问题,redis集群不保证强一致性,redis集群也会造成数据丢失,不保证强一致性