切片集群

切片集群,也叫分片集群,就是指启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存。

这里需要注意的是,这多个实例对外其实是提供一个服务,因为每个实例只有所有数据的一部分,他们内部是5个,客户端在使用时其实只会感知到1个。

image-20231221112358729

如何保存更多数据

Redis应对数据量增多有两种办法:

  • 纵向扩展(scale up):指的是升级单个Redis实例的配置资源,包括增加容量,使用更高配CPU等。
  • 横向扩展(scale out):增加Redis实例的个数。
image-20231221112825594

纵向扩展实现起来最简单,换一个机器就可以,但是会面临问题,即内存越大,单实例存储的数据就越多,在进行RDB持久化时,主线程fork子进程时就可能阻塞。如果不要求持久化,是一个不错的选择。

而针对于特别大的数据量,更好的方案是切片集群。

数据切片和实例的对应分布

数据和实例之间如何对应,与Redis Cluster有关。

具体来说,Redis Cluster 方案采用哈希槽(Hash Slot,接下来我会直接称之为 Slot),来处理数据和实例之间的映射关系。在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。

首先根据键值对的 key,按照CRC16 算法计算一个 16 bit 的值;然后,再用这个 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。

在部署 Redis Cluster 方案时,可以使用 cluster create 命令创建集群,此时,Redis 会自动把这些槽平均分布在集群实例上。

image-20231221154113991

在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作

客户端定位

在定位键值对数据时,它所处的哈希槽是可以通过计算得到的,这个计算可以在客户端发送请求时来执行。

客户端和集群建立连接后。实例就会把哈希槽的分配信息发送给客户端。但是刚创建的时候,每个实例只知道自己的哈希槽,不知道其他的哈希槽信息,这时Redis实例会把自己的哈希槽信息发送给它相连接的其他实例,来完成哈希槽信息分配的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。

但是,哈希槽并不是一直不变的,最常见的有以下两种变化:

  • 在集群中,实例有新增或删除,Redis 需要重新分配哈希槽;

  • 为了负载均衡,Redis 需要把哈希槽在所有实例上重新分布一遍。

此时,Redis实例之间可以通过相互传递消息,获得最新的哈希槽分配。但是客户端是无从感知的。Redis Cluster提供了一种重定向机制。该机制,指的是客户端给一个实例发送读写操作时,这个实例上没有对应的数据,客户端需要给一个新的实例发送数据。

具体来说,如果请求的实例没有数据,那么该实例会给客户端返回拥有该数据的实例,然后客户端再次请求即可。

image-20231221161342141