R

[Redis学习] Redis集群相关模式

RoLingG 其他 2024-04-22

Redis Cluster(集群模式)

假如我们的用户量千万,需要缓存的数据越来越大,我们应该怎么处理呢?

纵向扩展:升级单个 Redis 实例的资源配置,包括增加内存容量、增加磁盘容量、使用更高配置的 CPU。

横向扩展:横向增加当前 Redis 实例的个数,把数据等分成几个部分。

虽然纵向扩展简单直接,直接扩大内存就好了,但是有一些缺点:

  1. 硬件限制,比如我们有1TB的内存数据,单机就很难支持了,线上机器实例很少会这样配置,有也不给你 Redis 。
  2. 持久化,大数据量持久化时,fork导致主线程阻塞看,数据越大,阻塞时间越长

从 3.0 开始,官方提供了一个名为 Redis Cluster 的方案,Redis Cluster 是 Redis 中一种高可用的框架,用于实现切片集群。Redis Cluster 方案中就规定了数据和实例的对应规则。

将单机 Redis 转向为 多机集群 Redis。

请输入图片描述

集群通信

一个 Redis 集群由多个节点组成,各个节点之间是怎么通信的呢?通过 Gossip 协议!(也叫Epidemic Protocol流行病协议

我们希望这些变化能够让整个集群的每个节点能够尽快发现,那么各个节点之间就需要相互连通并且携带相关状态数据进行传播,这就用到了 Gossip 协议。

你可能会想到用广播的方式不也可以实现,答案是当然可以,但是对CPU和带宽的消耗比较大,所用还是采用 Goosip 协议。

该协议的特点是,在节点数量有限的网络中,每个节点都会“随机”(也不是真正的随机,而是根据规则选择通信节点)与部分节点通信,经过一番杂乱无章(传染病)的通信后,每个节点的状态可以在一定时间内达成一致。

常用的 Gossip 消息分为4种,分别是:ping、pong、meet、fail。

meet 消息:通知新节点加入,当消息发送者接到客户端发送CLUSTER MEET命令时,消息发送者会向接收者发送 meet 消息,之后消息发送者通知接收者加入到当前集群。meet 消息通信正常完成后,接收节点会加入到集群中并进行周期性的 ping、pong 消息交换。

ping 消息:集群内交换最频繁的消息,集群内每个节点每秒向多个其他节点发送 ping 消息,该信息包含自己的状态还有维护的集群元数据,用于检测节点是否在线和交换彼此状态信息。

pong 消息:当接收到 ping、meet 消息时,作为响应消息回复给发送方确认消息正常通信,返回 ping 和 meet ,包含自己的状态和其它信息。节点也可以向集群内广播自身的 pong 消息来通知整个集群对自身状态进行更新

fail消息:当节点判定集群内另一个节点下线时,会向集群内广播一个 fail 消息,其他节点接收到 fail 消息之后把对应节点更新为下线状态

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

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

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

使用Redis Cluster 方案时,可以使用 cluster create 命令创建集群,此时 Redis 会自动把这些槽平均分布在集群实例上。例如,如果集群中有 N 个实例,每个实例上的槽个数为 16384/N 个。

当然我们也可以手动设置机器上面的hash槽个数,应对线上机器不同配置的情况,这个大家去查看官方文档就好了。

客户端怎么确定数据在哪个实例上?

假设数据一成不变

在定位键值对数据时,客户端发送请求时,来计算它所处的哈希槽。但是,要进一步定位到实例,还需要知道哈希槽分布在哪个实例上。

但集群模式下,Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。

客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。

当然,有一些特殊情况,hash槽对应的实例会有变化

  1. 在集群中,实例有新增或删除,Redis 需要重新分配哈希槽。
  2. 为了负载均衡,Redis 需要把哈希槽在所有实例上重新分布一遍。

此时客户端缓存的数据就不准了,可能出现以下情景:

本地缓存的实例ip是192.168.0.1,但是此时该hash槽的对应ip变成了192.168.0.2。

MOVED 命令含义:表示请求的key,对应的 hash 槽与对应的实例信息,然后客户端只需要重新在对应的实例去操作就可以了。

当迁移的数据量过大时,就可能出现一种情况,请求时这个 hash 槽只迁移了一部分数据到新实例,还有一部分数据在老实例。

ASK 命令含义,当在 Redis Cluster 中使用 ASK(Ask Redirect)返回报错时,通常表示在执行命令时客户端与集群之间发生了某种异常情况。ASK 是 Redis Cluster 中的一种特殊机制,用于在槽迁移时指示客户端重定向到另一个节点。

优缺点分析

优点

  1. Redis Cluster 采用分布式架构,自动将数据分片存储在多个节点上,提供了良好的横向扩展性和高可用性。
  2. 集群节点可以自动发现和重新分片,并且支持节点动态扩容和缩减,减少了集群管理的复杂性。
  3. 当新的节点加入或离开集群时,Redis Cluster 能够自动进行节点发现和重新分片,而无需手动干预,这简化了集群管理的复杂度。

缺点

  1. Redis Cluster 不支持跨分片的事务操作,事务必须在同一分片上执行,这可能会在某些场景下带来限制。
  2. 配置和管理 Redis Cluster 相对复杂,需要理解分布式系统的原理和网络分区等问题。需要投入更多的精力来实施和维护集群。

综上所述,集群模式极大的降低了实例的数据量,适合大规模的 Redis。

Cluster Proxy(集群代理)

Proxy 模式通过在 Redis 客户端和服务端之间插入代理(Proxy)来实现负载均衡、故障转移和数据分片等功能。Proxy 可以根据负载情况将请求分发到不同的 Redis 节点上,并在节点故障时自动切换到备用节点。Proxy 模式提供了更灵活的架构设计和更好的可扩展性,但也增加了系统的复杂性和延迟。

请输入图片描述

优点:

  1. 负载均衡: Redis Proxy可以实现负载均衡,将客户端请求分发到多个后端的 Redis 服务器上,从而平衡集群中各个节点的负载,提高系统的整体性能和吞吐量。
  2. 故障转移: 当后端的 Redis 服务器出现故障或不可用时,Redis Proxy可以自动将请求重新路由到其他可用的节点上,从而实现故障转移,保证系统的高可用性。
  3. 数据分片: Redis Proxy可以将数据分片存储在多个后端的Redis服务器上,并根据数据的键来选择合适的服务器,从而增加系统的存储容量和并发处理能力。
  4. 协议转换: Redis Proxy 可以支持多种 Redis 协议,如 RESP( REdis Serialization Protocol)、Memcached 协议等,可以根据客户端的请求协议,将请求转换成后端服务器所支持的协议格式。
  5. 缓存: 一些 Redis Proxy 还提供了缓存功能,可以缓存常用的请求结果,并在后续的请求中直接返回缓存的结果,对于热点数据,非常好用。

缺点:

  1. 单点故障: Redis Proxy 本身也可能成为系统的单点故障,如果 Proxy 出现故障或不可用,会影响整个系统的稳定性和可用性。
  2. 性能损耗: 由于 Redis Proxy 介于客户端和后端 Redis 服务器之间,数据传输需要经过额外的中间层,可能会引入一定的性能损耗和延迟。
  3. 复杂性: 引入 Redis Proxy 会增加系统的复杂性,需要额外的管理和维护工作,包括配置管理、监控和故障排查等,增加了系统的开发和运维成本。
  4. 一致性问题: 如果 Redis Proxy 缓存了部分数据,并且与后端 Redis 服务器之间存在数据不一致的情况,可能会导致数据一致性的问题,需要谨慎处理。

综上所述,集群代理模式虽然相比于集群模式优化了一些地方,但同时也出现了一些缺陷。集群代理模式整体像哨兵模式,但是相比于哨兵模式它的适用规模更大。

PREV
[后端知识] TCP和UDP
NEXT
[Mysql] Mysql的覆盖索引与索引下推

评论(0)

发布评论