Redis的cluster原理
redis的备份策略目前有这样集中
- 使用主从
- 使用sentinel
- 使用cluster
其中cluster最近几个版本才添加上的,是redis自带的,本文主要讨论的是cluster在使用中会遇到的问题
分布策略
和类似tomcat的集群一样,redis的cluster难点也是在路由上,百万级别的并发,究竟将键存储到哪一个平台上是我们最关心的问提,也就是分键策略;说分区前先说一下cluster的问题:
- cluster不支持在多个节点上的多件操作,这个在后续会告知愿意
- cluster不支持单机版本的多db,如单机可以是用0-15db,cluster只能使用0
- cluster是把能存储的所有可以分为 16385(其实是0-16384)个槽,然后平均或者不平均的分给其他cluster节点;而键值就是放在槽上;槽就是slot
- 当我们根据键分节点,其实就是看在哪个槽上,而槽又属于哪个节点上
redis默认的分键策略属于hash分区方式(还有一种顺序分区方式如hbase) - 节点取余分区:根据key值算出hash,如有有n个节点,在把hash值/n,算出在哪个节点上
- 一致性hash分区: 为每个几点分配一个token;当计算出的hash值>token时,就属于这个节点
- 虚拟槽分区:就是品均分配slot,然后计算key在哪个槽slot上;能够最大程度上平均;
由于如mget和mset这种操作的key可能存在在多个槽上;所以在cluster之后不再支持
在客户端中,如jedis;在进行存储的时候,实际是不知道会放在哪个槽上,jedis会随机从连接池中取出一个链接,这个链接可能链接了cluster集群的任何一个节点,当放入的key不属于这个节点;就会再次从连接池随机取出一个链接;
- 由于正式由于这种随机性,可能造成大量的connection
- 一旦节点宕机,任何已经获取的链接都将报错
- 尝试的次数是有限制的,jedis默认只有5次;
- 即便jedis次数限制修改了上线;当cluster有n个节点的时候,依然可能很快用光
所以redis的cluster在使用的时候,最常见的错误是 JedisConnectionException
cluster风暴:放生故障的时候
- 先获取写锁,再执行cluster slots初始化缓存;
- 所有键都需要重新计算节点slot,
- 写锁只能被一个请求使用;高并发会不断请求写锁;并不断跑出JedisClusterMaxRedirectionException
slots缓存初始化是瓶颈,所以新版本极大减少了slots初始化的场景
节点故障
- 几点采用ping pong的方式互相判断
- 只有除目标节点外,所有节点都认为目标节点不可达,才认为节点故障