redis并发竞争
某个时刻多个系统都是更新同一个key,但是由于网络等原因导致本来应该先到的数据后到了,就会出现问题
- 基于 zookeeper 实现分布式锁,同一个时间只能有一个实例能够操作数据
- 写入缓存的时候将数据的时间戳也带上,每次需要更新的时候先判断要更新的数据的时间是不是在原数据的时间之后,是,才更新
redis cluster集群
redis 原生支持的 redis 集群模式,主要是针对海量数据+高并发+高可用的场景,支持 N 个 redis master node,每个 master node 都可以挂载多个 slave node。这样整个 redis 就可以横向扩容了。如果你要支撑更大数据量的缓存,那就横向扩容更多的 master 节点,每个 master 节点就能存放更多的数据了。
- 自动将数据进行分片,每个master上放一部分数据
- 提供高可用性,部分master宕机,还是可以继续工作
每个redis实例开发两个端口,比如一个7898端口,另外一个加10000,就是17898端口,前者与外部的通信,后者是节点之间通信,遵循gossip协议。
节点间的内部通信
- 集中式:就是将集群所有的元数据集中存储在摸个节点上,大数据领域的storm就是用的这个,底层是基于zookeeper对所有元数据进行维护,好处就是时效性非常好,一旦元数据更新就立即更新到集中式的存储中,但是不好的是这样对于元数据的存储空间有一定的压力
- gossip协议:就是将元数据不是放在一个地方,而是放在每个节点上,redis cluster 节点间采用 gossip 协议进行通信,好处就是缓解元数据存储的压力,坏处就是元数据的更新会有延迟,可能会导致集群中的一些操作会滞后。
gossip 协议
gossip 协议包含多种消息,包含 ping
,pong
,meet
,fail
等等。
- meet:每个节点发送meet给新加入的节点,让新节点加入集群,这样新节点就能正常通信
- ping:每个节点都会给其他节点发送ping,互相通过 ping交换元数据,但是不能很频繁,可能会加重网络负担,具体时间设置cluster_node_timeout可以调节,越大代表时间越长,每次 ping,会带上自己节点的信息,还有就是带上 1/10 其它节点的信息,发送出去,进行交换。至少包含
3
个其它节点的信息,最多包含总节点数减 2
个其它节点的信息。 - pong:返回ping和meet消息,包含自己的状态信息
- fail:某个节点判断另一个节点 fail 之后,就发送 fail 给其它节点,通知其它节点说,某个节点已经宕机
分布式寻址算法
- hash算法:对key进行hash取模,打在不同的节点上,当某个节点宕机就会导致,就会对剩下的节点进行取模,导致大部分缓存丢失,数据直接访问数据库
- 一致性hash算法:将整个 hash 值空间组织成一个虚拟的圆环,将各个master节点(使用ip或者主机名)进行hash,确定在圆环上位置,来一个key首先计算hash值,然后顺时针遇到的第一个节点,就打在他上面,影响就是这一段,但是可能会造成节点分布不均匀缓存热点问题,后来加入了虚拟节点,这样就首先了数据的均匀分布,负载均衡
- hash slot算法:redis cluster 有固定的
16384
个 hash slot,对每个key
计算CRC16
值,然后对16384
取模,可以获取 key 对应的 hash slot。每个master节点都是持有一部分hash slot,每增加或减少一个master节点,hash slot都会转移到其他节点上,移动 hash slot 的成本是非常低的。客户端的 api,可以对指定的数据,让他们走同一个 hash slot,通过hash tag
来实现,因为key找的是hash slot,所以宕机或者增加机器没有影响
redis cluster 的高可用与主备切换原理
一个节点认为另外一个节点宕机(在 cluster-node-timeout 内,某个节点一直没有返回 pong),就是pfail,然后会ping给其他节点,多个节点都认为就是fail,然后从这个节点的slave node中检查与master node 断开连接的时间,如果超过了 cluster-node-timeout * cluster-slave-validity-factor,那么就没有资格切换成 master,根据每个从节点对master复制数据的offset,来设置一个选举时间,offset越大,代表数据复制越多,优先选举。所有的master node来投票,如果超过半数都同意,那这个从节点就切换成主节点。整个过程与哨兵非常类似。