面试官:Redis集群模式有了解过吗?具体的工作原理可以简单说一下吗?
面试官的心理分析:主要考察的是在实际工作中是否接触过海量数据 高并发 高可用的场景。以及Redis这几年的一个变化。因为在前几年Redis本身不支持 集群模式,只能依赖于一些中间件,比如codis、推特的twemproxy等。但是最近几年Redis官方支持了集群模式Cluster,在实际应用中 该集群模式也被广泛使用,面试官主要是想考察了解你对Redis的一个掌握程度。
派大星:有了解,前几年主要通过Redis的一些中间件来做,比如codis、推特的twemproxy等,但是最近几年Redis官方支持了集群模式 Cluster。
面试官:那你简单介绍一下Redis Cluster吧。
派大星:好的,Redis Cluster它会自动将数据进行分片,同时每个master只有一部分数据。提供内置的高可用支持,部分master不可用 时还是可以对外提供服务的。在Redis Cluster架构下,每个Redis需要开发两个端口,比如一个是:6379 一个是16379;另外一个就是 加1w的端口号,比如16379。端口号用来进行节点之间的通信,也被称为cluster bus。cluster bus的通信用来故障检测、配置更新、故 障转移授权。cluster bus用了另外一种二进制协议,gossip
协议,用于节点间进行高效的数据交换,占用较少的网络带宽和处理时间
面试官:不错,可以继续讲一讲节点间的内部通信机制吗
派大星:可以,首先来讲一般集群元数据的维护方式有两种:
- 集中式、gossip协议,Redis采用的是gossip协议进行通信。
面试官:这两个有什么区别吗?
派大星:当然,首先针对与集中式来说,它是将集群元数据(节点信息,故障信息)等集中存储在某个节点上,这种存储方式有点典型的代 表就是大数据中storm
。它是分布式的大数据实时计算引擎,是集中式的元数据存储的结构,底层基于zookeeper对所有元数据进行存 储维护。如图:
集中式的好处就在于:对于元数据的读取和更新时效性
非常好,一旦出现数据的变更,就立即更新到集中式存储中,其它节点也可以 第一时间进行感知到。缺点就是所有的元数据都在一个地方。可以会导致元数据的存储有压力。
派大星:其次对于goosip
协议来讲它的优点相比较于集中式存储它的元数据信息相对比较分散,不集中在一个地方,更新请求会分散 在其它有元数据的节点,从而降低了压力。相对来说时效性没有那么好。会有一些滞后。
面试官:gossip协议你了解多少,可以简单介绍以下嘛?
派大星:gossip协议包含很多信息,比如ping
、 pong
、 meet
、 fail
等等。
- meet:某个节点会发送meet给新加入的节点,然后新节点就会加入集群中,并于其它节点进行通信
- ping:每个节点都会给其它节点频繁的发送ping,其中包含自己元数据信息,互相通过ping来交换元数据信息。
- pong:返回ping和meet,包含自己的状态和其它信息,用于信息广播和更新。
- fail:某个节点判断另外一个节点fail后,就会给其它节点发送fail。通知其它节点告诉某个节点宕机了。
派大星:ping是要携带一些元数据,如果很频繁的话可能会导致网络开销较大。并且每个节点每秒会执行10次的ping,每次会选择5个 最久没有通信的其它节点。当然这期间如果发现了某个节点通信延时达到了(cluster_node_time_out / 2
)。那么就会立即发送平,避免 数据交换延时过长,落后的时间太长了。比如说两个节点已经有10分钟没有交换数据了,那么整个集群就存在严重的数据不一致的情况 ,就会有问题。所以cluster_node_timeout
可以去调节,调节的比较好的好。ping频率自然也就降低了。
面试官:既然Redis Cluster有这么多的节点,它是如何做的选择呢,也就是怎么做的节点负载均衡?
派大星:说到节点负载均衡就需要知道分布式的寻址算法:
- hash算法:(大量缓存重建)
- 一致性hash算法:(自动缓存迁移) 虚拟节点(自动负载均衡)
- Redis cluster的Hash slot算法
以上三种算法Redis中采用的是Hash slot算法。
面试官:那你能简单介绍下这三种算法吗?
派大星:好的, 首先Hash算法,会根据key计算其Hash值,然后对节点数取模
,接着打在不同的master节点上。一旦某一个节点宕机,所有请求打过来,都会基于最新的剩余的master节点进行取模尝试获取数据。这样就会导致后续所有请求过来,都无法拿到有效的缓存,导致大量的请求直接打到DB上。对于一致性Hash算法而言,它会将整个Hash值空间组装成一个虚拟的圆环,整个空间按顺时针方向流转,下一步将各个master节点进行Hash,这样就能确定每个节点在其Hash环位置上。请求过来的时候,会先根据key计算Hash值并确定此数据在环上的位置,从此位置沿着环的顺时针方向行走,遇到的第一个master节点就是key所在的位置。这种情况即使有一个节点挂了宕机了,受影响的数据仅仅是此节点到环空间前一个节点(也就是沿着逆时针方向行走遇到的第一个节点)之间的数据,其它不会受到影响,增加一个节点也同理。相比较于Hash算法即使挂了一个节点不会使后面的所有请求都直接打到DB上。但是一致性Hash算法如果在节点特别少的情况下,容易出现因为节点分布不均匀而造成缓存热点
的问题。为了解决这种热点问题,一致性Hash算法引入了虚拟节点机制
,即对每一个节点计算多个Hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。
至于Redis Cluster的Hash slot算法。首先Redis Cluster中有固定的16384
个Hash slot,对每个key计算CRC16
值,然后对16384取模,可以获取key对应的Hash Slot。Redis Cluster中每个master都会持有部分slot,比如有3个master,那么每个master可能会持有5000多个Hash Slot。Hash Slot让node的增加移除变得简化,增加一个master,将其它master的hash slot移动部分过去即可,减少一个slot,将它的hash slot移动到其它的master即可。移动hash slot的成本也很低。针对客户端的API可以针对指定的数据,让其走同一个Hash Slot,通过Hash Tag即可以实现。这样就保证了任何一台机器宕机,其它的节点都不受影响,因为key要找的是Hash Slot而不是机器。
面试官:不错,那Redis Cluster的高可用机制的主备切换原理是什么,这个有了解过吗?
派大星:首先来说Redis Cluster 的主备切换原理其实和Redis Sentinel是十分相似的。第一步:它会先判断是否宕机。如果一个节点认为另外一个节点宕机,难么就是pfail
,也就是主观宕机。假设如果多个节点都认为另外一个节点宕机了。那么就是fail
客观宕机。这里和odown
、sdown
很相似。主要表现形式则是:在cluster-node-timeout
内,某个节点一直没有返回pong
,那么就会认为是pfail
。一个节点一旦认为某个节点pfail
了,就会在gossip ping
消息中,ping
给其它的节点,如果超过半数的节点
都认为pfail
了,那么就会是fail
至于如何选举,对宕机的master node,会从其所有的slave node中选举一个master node。首先会判断并检查每个slave node于master node断开连接的时间,如果超过了cluster-node-timeout * cluster-slave-validity-factor
了,就没有资格成为master。这一步之后每个从节点,都会根据自己对master复制数据的offset来设置一个选举的事件,offset越大(代表复制的数据越多)的从节点,选举的事件越靠前,会优先进行选举。这时候所有的master node开始对要进行选举的slave node进行投票,如果大部分master node(N/2 1 )都投给了某个slave node。那么选举就会被通过。表明该slave node会切换成master。综上所述,整个流程和哨兵相比很类似。所以说Redis Cluster功能强大。直接集成了Relocation
和Sentinel
。