Redis-Cluster
1.哨兵模式和redis-cluster模式的区别
哨兵模式的问题:1.只有一个master节点可以提供写的操作,qps 最多10w,对于高并发特别高的大型互联网系统
2.单节点不会内存太大,内存很大会给主节点造成压力,所以一般不建议超过10G,但是显然对于一些,商城等大型的 互联网系统10G显然不够用
3.瞬短,主从选举切换需要10-50s时间,对于访问量特别高的系统也是不能忍受的
2.redis 集群架构
数据分片存放,每一个小的分区都是一个主从(可以选举),数据不重复(由hash解决),master挂掉之后可以从slave中选举出一个主节点
相对于哨兵解决了哨兵了问题么:
1.对于瞬断问题,没有完全解决:当master1出现问题的时候,需要从master1节点存取的key回出现问题,但是如果经过hash后是master1以外的机器,就不会受到影响
2.针对单节点的存储问题,Cluster中的节点是可以横向扩容了,理论最大值是1w个,但是出于不同节点间相互访问的性能出发,推荐是1k个左右,
3.多个小集群的架构也直接扩充了qbs的值
Redis Cluster中有一个16384长度的槽的概念,他们的编号为0、1、2、3……16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。
正常工作的时候,Redis Cluster中的每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。
集群中的每个节点负责处理一部分插槽。 举个例子, 如果一个集群可以有主节点, 其中:
节点 A 负责处理 0 号至 5460 号插槽。
节点 B 负责处理 5461 号至 10922 号插槽。
节点 C 负责处理 10923 号至 16383 号插槽。
4. 数据分配
Redis Cluster中对于不同的小集群存储什么样子的数据是通过一个虚拟的数据插槽来绑定的,有0-16383 共16384个值,集群中的每个节点负责处理一部分插槽。
eg:
节点 A 负责处理 0 - 5460 号插槽。
节点 B 负责处理 5461 - 10922 号插槽。
节点 C 负责处理 10923 - 16383 号插槽。
槽位只会分配给主节点
Redis-Cluster info 查看redis集群的信息
一个小集群的主节点从节点不会放到同一台机器上
集群构建和启动不是一套命令,之后启动只需要分别启动节点就行
选举使用的是goosip协议(最终一致),来感染所有节点,所以当前节点通知到最远的节点是需要一定的时间的,所以要控制集群的数量
cluster-node-timeout的值不能设置的太少不然遇到网络抖动,瞬断,就会立马选举出一个新的主节点,导致会有两个主节点,脑裂产生
Redis集群选举原理分析
当save发现自己的master变为FAL状态时,便尝试进行Falog,以期成为新的maste,由于挂增的masther可能会有多个saye,从而存在多个save竞争成为masler节点的过程
其过程如下:
5.redis集群选举原理分析
1.slave发现自己的master变为FAIL
2 将自己记录的集群currentEpoch(选举周期)加1,并广播FAILOVER AUTH REQUEST (只有master响应)信息
3其他节点收到该信息,只有masier响应,判听请求者的合法性,并发送FAILOVER_AUTH ACK,对每一个epoch只发送一次ack
4.尝试failover的slave收集master返回的FAILOVER AUTH ACK
5.slave收到超过半数mesle的ack后变成新Masler(这里解释了集联为什么至少需要三个主节点,如果只有两个,当其中一个挂了,只剩一个主节点是不能进举成功的)
6.slave广播Ping消息通知其他集群节点。
从节点共不最在生节点一进入 FAL 状态就马上尝试发起讲举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在集群中传播,slave或许尚未意识到FAL状态,可能会拒绝投票
延迟计算公式:
A、B、C 三个主节点,每个节点下有2个从节点形成集群,当A节点出现问题(Ac1、Ac2为主节点A的两个从节点)
情况1: Ac1 (currentEpoch1)向 B、C 发送广播并且得到ack,这样得到了大于一半以上的节点的选选票(3/2=1.5)Ac1会取代A成为主节点,之后会通过goosip的ping同步信息
情况2: Ac1 、Ac2(currentEpoch1)向 B、C 发送广播,分别得到了1条ack,重新发起一轮选举,Ac1 (currentEpoch2)向 B、C 发送广播并且得到ack,这样得到了大于一半以上的节点的选选票(3/2=1.5)Ac1会取代A成为主节点,之后会通过goosip的ping同步信息
从节点共不最在生节点一进入 FAL 状态就马上尝试发起讲举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在集群中传播,slave或许尚未意识到FAL状态,可能会拒绝投票
DELAY = 500ms + random(0 - 500ms)+SLAVE RANK*1000ms
SLAVE_RANK表示此skave己经从master复制据的总量的rank。Rank越小代表已复制的改据越新,这种方式下,持有量新数据的slave将会首先发起选举(理论上)。
为了避免票数不能过半频繁发生的情况,redis设置了延迟时间,目的是让从节点不同时发出消息,并且+SLAVE RANK*1000ms 可以保证当前同步数据最多的节点,成为新的master,也就意味着拥有最新、最多数据的节点更可能成为新的节点,redis的主从不是同步复制的,客户端向master发送成功,但是master没有来得及向从节点同步就挂掉,就会丢失数据,理论上选举出来的应该是数据最全的,
脑裂问题
由于网络问题导致原来的主节点被集群隔离出来了,此时内部选举出了新的主节点,一部分客户端向原来的主节点发送消息,一部分向现在的主节点发送消息,当网好了原来的主节点加入集群后,回变为集群的叶子几点,数据回同步,则脑裂这段时间的原来主节点的数据就会丢失
解决脑裂问题、和主从切换数据丢失问题(对于redis意义不大损失AP)
min-slaves-to-write 配置 1 则写入后至少需要向1个从节点写入数据才会返回ture 半数+1
但是会牺牲集群的可用性
集群是否完整才能对外提供服务
cluster-require-full-coverage: 默认值 yes , 即需要集群完整性,方可对外提供服务,
一个小集群挂了,其他的小集群依旧可以对外提供服务
批量操作
redis会保证命令的原子性,批量存储如果不能命中一个slot,redis会直接报错,如果想进行批量操作,就要保证hash结果的命中的槽位是一个就要用到hashtag
HashTag机制可以影响key被分配到的slot,从而可以使用那些被限制在slot中操作。
HashTag即是用{}包裹key的一个子串,如{user:}1, {user:}2。
在设置了HashTag的情况下,集群会根据HashTag决定key分配到的slot, 两个key拥有相同的HashTag:{user:}, 它们会被分配到同一个slot,允许我们使用MGET命令。
通常情况下,HashTag不支持嵌套,即将第一个{和第一个}中间的内容作为HashTag。若花括号中不包含任何内容则会对整个key进行散列,如{}user:。
HashTag可能会使过多的key分配到同一个slot中,造成数据倾斜影响系统的吞吐量,务必谨慎使用。
集群扩容
add-node + 当前要新加的节点 + 当前的集群中人一个存活的节点
新加的节点的信息会通过高goosip的meet命令同步集群的信息
还需要切换到原来集群的一个主节点做槽位移动,才可以写入信息
回询问你需要迁移多少个槽位给新的节点,给出计划,执行,会将槽位和槽位对应的数据都会迁移过来