Redis 切片集群

切片集群

假设需要有30G的数据需要存入到 redis, 所有数据放一个实例中虽然是可行的, 但是如果把蛋都放在一个篮子里务必就会产生很多风险和副作用。譬如:

  1. 当数据增多时只能纵向扩展,且到了一定阶段还需要考虑到硬件成本问题。
  2. 如果是使用 RDB 进行持久化时,Redis 会 fork 父进程的页表给子进程,页表的数量上,数据越大,页表越多,复制就越花时间,导致 redis 性能下降。

譬如这个时候就可以采用集群的方案,redis 的切片集群大致可以分为两种,无中心化的集群方案和中心化的集群方案。Redis Cluster 是官方提供的一种切片集群方案,属于无中心化集群。

切片集群就是指启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存。切片集群主要的目的是降低节点的压力和单节点内存大小,每个节点的数据是不一致的,分布式的,共同承担整个redis集群查询操作。

数据如何分布

在切片集群中,数据需要分布在不同实例上,Redis Cluster 方案采用哈希槽来处理数据和实例之间的映射关系。一个切片集群共有 16384 个哈希槽(Slot),哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。通过对 key CRC16 校验后得到的值对对 16384 取模后得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。 (Slot=CRC16(key)%16384)

为什么是 16384 个哈希槽呢? 简单来说就是为了做性能的权衡,保证切片集群在一定的规模内的性能。 有兴趣可以看看作者解答

在多数情况下都是通过 cluster create 命令创建集群时会平均把 Slot 分到各个实例,每个实例的哈希槽个数是 16384/N 个。但是在 redis 实例硬件差距比较大的情况下就通过需要通过 cluster addslots 命令手动的分配 Slot,对于机器性能好的机器可以分配多一些 Slot,性能没那么好的少配一些 Slot 来做到最佳的性能。在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作。

客户端如何获取

客户端可以通过 key 可以计算得到所属的 Slot,但是 Slot 处于哪个实例客户端是不知道的。

在大多数情况下集群创建结束后每个 redis 节点会把自己的 Slot 信息发给和它相连接的其它实例,来完成 Slot 分配信息的扩散。当实例之间相互连接后,每个实例就有所有 Slot 的映射关系了,客户端和集群实例建立连接后,实例就会把 slot 的分配信息发给客户端,客户端通过计算得到 key 所在的 Slot,然后发往相应的实例。

但是 Slot 对应关系并不是变的,最常见的几种变化场景:

  1. 新增、删除 redis 实例。redis 需要重新分配 slot。
  2. 数据倾斜、热点数据导致部分 slot 访问频繁,需要重新进行分布。

客户端是无法主动感觉到 slot 发生变化的,当客户端把一个键值对的操作请求发给一个实例时,如果这个实例上并没有这个键值对映射的 Slot 实例会返回一个 moved 响应结果。

1
2
3
GET key:hello

(error) MOVED 13320 172.0.0.5:6379

moved 命令中包含了slot 和 slot 对应的实例信息。客户端接受到 moved 命令就可以把响应的请求发到对应的实例,并缓存最新的实例关系。

还有一种特殊的情况。如果客户端请求的同时,恰巧哈希槽正在迁移且还没完成。客户端会受到一条 ASK 报错信息。

1
2
3
GET key:hello

(error) ASK 13320 172.0.0.5:6379

Slot 13320 正在迁移到 172.0.0.5 实例上,但是还没有迁移完成,客户端需要给 172.0.0.5 实例发送一个 ASKING 命令。告诉它下一条指令不能不理,而要当成自己的槽位来处理。ASK 命令并不会更新客户端缓存的哈希槽分配信息。客户端下次依旧会给 Slot 原有实例发送请求,接受到 Moved后在更新 Slot 。

最后

切片集群面对海量数据的时候还是非常有优势的。集群可以非常方便的横向扩展。Redis Cluster 是在 redis 3.0之后推出的,在此之前其实就有一些非常成熟的切片集群方案,之后会对比几种方案。

  1. 客户端分片
  2. Codis
  3. Twemproxy
  4. Redis Cluster

客户端分片、Redis Cluster 属于无中心化的集群方案,Codis、Tweproxy 属于中心化的集群方案。如果使用 Redis Cluster 方案,那么 redis 节点数保持在1000以内是可以得到不错的性能的。


Redis 切片集群
http://example.com/posts/10521.html
作者
她微笑的脸y
发布于
2023年3月20日
许可协议