12.Redis集群面试题(高频面试题)

在大数据高并发场景下,Sentinel存在一些问题,写请求全部落在 Master 节点,Master 节点就一个实例,存储容量、CPU、内存、IO都存在瓶颈,如果我们扩容内存,会导致RDB文件过大,从而fork子进程时会阻塞较长时间。此时Redis 集群方案应运而生。

1.数据如何分片?

Redis Cluster 采用的是虚拟槽分区,一个集群共有 16384 个哈希槽,Redis Cluster会自动把这些槽平均分布在集群实例上。例如,如果集群中有 N 个实例,那么,每个实例上的槽个数为 16384/N个。

12.Redis集群面试题(高频面试题)_第1张图片

Redis Cluster 会对 key 进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位。

2.扩容机制

如图所示,6379、6380、6381三个主节点,6382是6379的从节点,6383是6380的从节点,6384是6381的从节点,现在因为业务发展过快,需要进行扩容,我们新增一个主节点6385和一个从节点6386。

12.Redis集群面试题(高频面试题)_第2张图片

步骤一:首先需要为新节点指定槽的迁移计划,也就是将哪些节点的哪些槽迁移到新节点中。并且迁移计划要确保每个节点负责相似数量的槽,从而保证各节点的数据均匀。槽迁移计划确定后开始逐个把槽内数据从源节点迁移到目标节点中。

12.Redis集群面试题(高频面试题)_第3张图片 12.Redis集群面试题(高频面试题)_第4张图片

如上图所示,6379准备把自己的4097-5460槽迁移给新节点6385,6380准备把自己的9558-10921槽迁移给新节点6385,6381准备把自己的15019-16383槽迁移给新节点6385。

步骤二:迁移数据数据迁移过程是逐个槽进行的,每个槽迁移的流程如下流程说明:

12.Redis集群面试题(高频面试题)_第5张图片

①对目标节点发送cluster setslot {slot} importing {sourceNodeId}命令,让目标节点准备导入槽数据。

②对源节点发送cluster setslot {slot} migrating {targetNodeId}命令,让源节点准备迁出槽数据。

③源节点循环执行cluster getkeysinslot {slot} {count}命令,获取count个数据槽{slot}的键。

④在源节点上执行migrate {targetIp} {targetPort} key 0 {timeout} 命令把指定key迁移

注意:Redis3.2.8后,使用pipeline传输

⑤重复步骤3、4直到槽下所有的键值数据迁移到目标节点。

⑥向集群内所有主节点发送cluster setslot {slot} node {targetNodeId}命令,通知槽分配给目标节点。

3.缩容机制

缩容的三种情况:

①下线迁移槽

②忘记节点

③关闭节点

槽迁移和扩容一样

4.MOVED

当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个 MOVED 指令并携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。

客户端收到 MOVED 指令后,要立即纠正本地的槽位映射表。后续所有 key 将使用新的槽位映射表。

案例:

首先计算出哈希值,然后取模16384,得到槽

12.Redis集群面试题(高频面试题)_第6张图片

计算哈希值命令:

127.0.0.1:6379>cluster keyslot "hello world"

命中

12.Redis集群面试题(高频面试题)_第7张图片

未命中

12.Redis集群面试题(高频面试题)_第8张图片

MOVED命令里包含两个信息,一个是槽的位置,一个是目标节点地址。

5.Asking

12.Redis集群面试题(高频面试题)_第9张图片

集群的伸缩(扩容/缩容)的时候,当我们去源节点访问时,发现key已经迁移到目标节点,会回复ask转向异常,收到异常后,先是执行asking命令,然后给目标节点再次发送命令,然后就会返回结果。

假如我们执行一个get key命令,这个key原来是在A节点,现在迁移到B节点,然后会给我们返回ASK转向异常,当我们收到ASK转向异常后,需要执行一条Asking命令给目标节点,然后在发送get命令。

ASK与MOVED共同点:两者都是重定向
ASK与MOVED不同点:

  • MOVED:槽已经确定
  • Asking:槽在迁移过程,key有可能在source节点有可能在target节点

6.槽位迁移感知

如果集群中某个槽位正在迁移或者已经迁移完了,客户端如何能感知到槽位的变化?

客户端保存了槽位和节点的映射关系表,当客户端收到moved指令的时候,他会去刷新槽位映射关系表,获取到最新的映射关系。当收到ask转向异常时,不会刷新槽位映射关系表,因为它是临时纠正。

7.容错

Redis Cluster 可以为每个主节点设置若干个从节点,单主节点故障时,集群会自动将其中某个从节点提升为主节点。如果某个主节点没有从节点,那么当它发生故障时,集群将完全处于不可用状态。不过 Redis 也提供了一个参数cluster-require-full-coverage可以允许部分节点故障,其它节点还可以继续提供对外访问。

你可能感兴趣的:(Redis)