Redis 高可用 RedisCluster

762 阅读2分钟

当一个Redis的内存容量需求越来越大时,我们就需要对Redis进行扩容。首先想到的方案就是选择内存更大的云主机来部署Redis。但是这种方法有两方面的弊端:

  • 云主机的单机内存扩容有上限,无法做到无限扩容
  • 单机内存太大会造成持久化RDB文件太大,故障恢复缓慢。
  • 在对RDB进行持久化时,Redis fork子进程的耗时变大,阻塞主线程,导致Redis响应变慢。

于是乎,有了切片集群Redis Cluster。

数据切分后我们需要解决两个问题:

  • 数据切片后,多个实例之间数据如何分布?
  • 客户端怎么确定想要访问的数据?

Redis Cluster采用的是Hash Slot来处理数据和实例之间的映射关系。切片集群一共有16384个hash slot,类似于数据分区的概念。映射分为两步:

  • 键值对key按照CRC16算法计算一个16bit的值。
  • 对16384取模,就找到了模数对应编号的hash slot。

在部署Redis Cluster时,可以使用cluster create命令创建集群,这里Redis实例会自动平均分配给集群实例hash slot。也就是有N个实例,分配16384/N个slot。

也可以使用cluster meet手动建立实例间的连接。cluster addslots 指定实例的hash slot个数。 需要注意的是手动分配hash slot需要把16384个slot都分配完,否则Redis集群无法正常工作。

客户端如何定位数据在哪一个实例呢?

客户端和集群实例建立连接后,实例会把hash slot的分配信息发给客户端,客户端会本地缓存。一旦hash slot信息发生改变,例如:

  • 集群 实例有新增删除,Redis hash slot要重新分配
  • 为了负载均衡 Redis 需要把hash slot重新分布一遍

Redis Cluster提供了重定向机制来解决客户端hash slot信息和实例节点之间不一致的情况。 如果请求发给一个实例,该实例并没有这个键值对对应的hash slot。那么实例返回一个MOVED命令给客户端并告知正确的地址。客户端再次请求并获取结果,更新本地缓存。

另外如果节点之间的hash slot正在迁移,就存在返回的地址可能是新地址或者还是旧地址的情况。这时Redis实例会返回ASK命令,客户端收到ASK返回的地址,会尝试向对应节点发送ASKING命令获取数据。和MOVED命令不同的是,ASK 命令并不会更新客户端缓存的哈希槽分配信息。