redis--切片集群

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

在切片集群中,实例在为数据生成 RDB 时,数据量就小了很多,fork 子进程一般不会给主线程带来较长时间的阻塞。采用多个实例保存数据切片后,我们既能保存大量数据,又避免了 fork 子进程阻塞主线程而导致的响应突然变慢。在实际应用 Redis 时,随着用户或业务规模的扩展,保存大量数据的情况通常是无法避免的。而切片集群,就是一个非常好的解决方案。

如何保存更多数据?

纵向扩展:升级单个 Redis 实例的资源配置,包括增加内存容量、增加磁盘容量、使用更高配置的 CPU。就像下图中,原来的实例内存是 8GB,硬盘是 50GB,纵向扩展后,内存增加到 24GB,磁盘增加到 150GB。

横向扩展:横向增加当前 Redis 实例的个数,就像下图中,原来使用 1 个 8GB 内存、50GB 磁盘的实例,现在使用三个相同配置的实例。

redis--切片集群_第1张图片

纵向扩展的好处是,实施起来简单、直接 ;缺点是当使用 RDB 对数据进行持久化时,如果数据量增加,需要的内存也会增加,主线程 fork 子进程时就可能会阻塞(比如刚刚的例子中的情况)。不过,如果你不要求持久化保存 Redis 数据,那么,纵向扩展会是一个不错的选择。第二个缺点:纵向扩展会受到硬件和成本的限制。

横向扩展是一个扩展性更好的方案,要想保存更多的数据,采用这种方案的话,只用增加 Redis 的实例个数就行了,不用担心单个实例的硬件和成本限制。

数据切片后,在多个实例之间如何分布?

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

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

可以使用 cluster create 命令创建集群,Redis 会自动把这些槽平均分布在集群实例上。当然, 我们也可以使用 cluster meet 命令手动建立实例间的连接,形成集群,再使用 cluster addslots 命令,指定每个实例上的哈希槽个数。集群中不同 Redis 实例的内存大小配置不一,可以把内存小的实例分配较少的哈希槽,这样可以降低内存小的redis实例的压力。

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

客户端如何定位数据?

Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端。客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。

在集群中,实例和哈希槽的对应关系并不是一成不变的,最常见的变化有两个:

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

Redis Cluster 方案提供了一种重定向机制,所谓的“重定向”,就是指,客户端给一个实例发送数据读写操作时,这个实例上并没有相应的数据,客户端要再给一个新实例发送操作命令。

如果这个实例上并没有这个键值对映射的哈希槽,那么,这个实例就会给客户端返回下面的 MOVED 命令响应结果,这个结果中就包含了新实例的访问地址:
GET hello:key
(error) MOVED 13320 172.16.19.5:6379

在实际应用时,如果 Slot 2 中的数据比较多,就可能会出现一种情况:客户端向实例 2 发送请求,但此时,Slot 2 中的数据只有一部分迁移到了实例 3,还有部分数据没有迁移。在这种迁移部分完成的情况下,客户端就会收到一条 ASK 报错信息,如下所示:
GET hello:key
(error) ASK 13320 172.16.19.5:6379

此时,客户端需要先给 172.16.19.5 这个实例发送一个 ASKING 命令。这个命令的意思是,让这个实例允许执行客户端接下来发送的命令。然后,客户端再向这个实例发送 GET 命令,以读取数据。和 MOVED 命令不同,ASK 命令并不会更新客户端缓存的哈希槽分配信息。

redis--切片集群_第2张图片

切片集群中的主从切换?

redis集群的其他节点,每隔一断时间,就会向集群中的其他节点发送ping包,以检测节点是否还活着。如果此时,A主节点阻塞了,收到pong包的时间超时,大于 cluster-node-timeout,就会自动切换主从节点。

  • 通过投票机制来判断master是否不可用,参与投票的是所有的master,所有的master之间维持着心跳,如果一半以上的master确定某个master失联,则集群认为该master挂掉,此时发生主从切换。
  • 通过选举机制来确定哪一个从节点升级为master。选举的依据依次是:网络连接正常->5秒内回复过INFO命令->10*down-after-milliseconds内与主连接过的->从服务器优先级->复制偏移量->运行id较小的。选出之后通过slaveif no ont将该从服务器升为新master。

通过配置文件参数【cluster-node-timeout】指定心跳超时时间,默认是15秒。

                                                                            --内容整理自极客时间《Redis 核心技术与实战》

你可能感兴趣的:(redis,数据库,缓存)