Redis集群

目录

 

1 Redis 高可用  

1.1 主从复制的问题

2. Redis Sentinel

2.1 Redis sentinel 架构

2.2  主观下线和客观下线

2.3 sentinel的通信命令

2.4  Sentinel 原理

 3 codis

3.1 codis分片原理

3.2 codis 扩容

3.3 mget操作过程

4 cluster

4.1 cluster 分片原理


1 Redis 高可用  

Web 服务器中,高可用 是指服务器可以 正常访问 的时间,衡量的标准是在 多长时间 内可以提供正常服务(99.9%99.99%99.999% 等等)。在 Redis 层面,高可用 的含义要宽泛一些,除了保证提供 正常服务(如 主从分离快速容灾技术 等),还需要考虑 数据容量扩展数据安全 等等。

Redis 中,实现 高可用 的技术主要包括 持久化复制哨兵集群,下面简单说明它们的作用,以及解决了什么样的问题:

  • 持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。

  • 复制:复制是高可用 Redis 的基础,哨兵集群 都是在 复制基础 上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。

  • 哨兵:在复制的基础上,哨兵实现了 自动化故障恢复。缺陷是 写操作 无法 负载均衡存储能力 受到 单机 的限制。

  • 集群:通过集群,Redis 解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善高可用方案

1.1 主从复制的问题

Redis 主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:

  1. 一旦 主节点宕机从节点 作为 主节点 的 备份 可以随时顶上来。
  2. 扩展 主节点 的 读能力,分担主节点读压力。

                                              

主从复制 同时存在以下几个问题:

  1. 一旦 主节点宕机从节点 晋升成 主节点,同时需要修改 应用方主节点地址,还需要命令所有 从节点复制 新的主节点,整个过程需要 人工干预

  2. 主节点写能力 受到 单机的限制

  3. 主节点存储能力 受到 单机的限制

  4. 原生复制 的弊端在早期的版本中也会比较突出,比如:Redis 复制中断 后,从节点 会发起 psync。此时如果 同步不成功,则会进行 全量同步主库 执行 全量备份 的同时,可能会造成毫秒或秒级的 卡顿

 

2. Redis Sentinel

Redis Sentinel 是 Redis 高可用 的实现方案。Sentinel 是一个管理多个 Redis 实例的工具,它可以实现对 Redis 的 监控通知自动故障转移

2.1 Redis sentinel 架构

                                 

2.2  主观下线和客观下线

默认情况下,每个 Sentinel 节点会以 每秒一次 的频率对 Redis 节点和 其它Sentinel 节点发送 PING 命令,并通过节点的 回复 来判断节点是否在线。

  • 主观下线

主观下线 适用于所有 主节点从节点。如果在 down-after-milliseconds 毫秒内,Sentinel 没有收到 目标节点 的有效回复,则会判定 该节点主观下线

  • 客观下线

客观下线 只适用于 主节点。如果 主节点 出现故障,Sentinel 节点会通过 sentinel is-master-down-by-addr 命令,向其它 Sentinel 节点询问对该节点的 状态判断。如果超过 <quorum> 个数的节点判定 主节点 不可达,则该 Sentinel 节点会判断 主节点客观下线

2.3 sentinel的通信命令

Sentinel 节点连接一个 Redis 实例的时候,会创建 cmd 和 pub/sub 两个 连接Sentinel 通过 cmd 连接给 Redis 发送命令,通过 pub/sub 连接到 Redis 实例上的其他 Sentinel 实例。

SentinelRedis 主节点从节点 交互的命令,主要包括:

命令作 用
PINGSentinelRedis 节点发送 PING 命令,检查节点的状态
INFOSentinelRedis 节点发送 INFO 命令,获取它的 从节点信息
PUBLISHSentinel 向其监控的 Redis 节点 __sentinel__:hello 这个 channel 发布 自己的信息主节点 相关的配置
SUBSCRIBESentinel 通过订阅 Redis 主节点从节点__sentinel__:hello 这个 channnel,获取正在监控相同服务的其他 Sentinel 节点

SentinelSentinel 交互的命令,主要包括:

命令作 用
PINGSentinel 向其他 Sentinel 节点发送 PING 命令,检查节点的状态
SENTINEL:is-master-down-by-addr和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点

 

2.4  Sentinel 原理

1、每个 Sentinel 节点都需要 定期执行 以下任务:

  • 每个 Sentinel 以 每秒钟 一次的频率,向它所知的 主服务器从服务器 以及其他 Sentinel 实例 发送一个 PING 命令。

                               

2、如果一个 实例instance)距离 最后一次 有效回复 PING 命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel 标记为 主观下线

                                

3、如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有 Sentinel 节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。

                                 

4、如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的 Sentinel(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线

                                  

5、在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率,向它已知的所有 主服务器从服务器 发送 INFO 命令。当一个 主服务器Sentinel 标记为 客观下线 时,Sentinel下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从 10 秒一次改为 每秒一次

                                     

6、Sentinel 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制

                                    

7、当没有足够数量的 Sentinel 同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向 Sentinel 的 PING 命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。

 

 3 codis

                                    

Codis 使用 Go 语言开发,它是一个代理中间件,它和 Redis 一样也使用 Redis 协议对外提供服务,当客户端向 Codis 发送指令时,Codis 负责将指令转发到后面的 Redis 实例来执行,并将返回结果再转回给客户端。Codis 上挂接的所有 Redis 实例构成一个 Redis 集群,当集群空间不足时,可以通过动态增加 Redis 实例来实现扩容需求。

因为 Codis 是无状态的,它只是一个转发代理中间件,这意味着我们可以启动多个 Codis 实例,供客户端使用,每个 Codis 节点都是对等的。因为单个 Codis 代理能支撑的 QPS 比较有限,通过启动多个 Codis 代理可以显著增加整体的 QPS 需求,还能起到容灾功能,挂掉一个 Codis 代理没关系,还有很多 Codis 代理可以继续服务。

3.1 codis分片原理

Codis 要负责将特定的 key 转发到特定的 Redis 实例,那么这种对应关系 Codis 是如何管理的呢?

Codis 将所有的 key 默认划分为 1024 个槽位(slot),它首先对客户端传过来的 key 进行 crc32 运算计算哈希值,再将 hash 后的整数值对 1024 这个整数进行取模得到一个余数,这个余数就是对应 key 的槽位。

每个槽位都会唯一映射到后面的多个 Redis 实例之一,Codis 会在内存维护槽位和 Redis 实例的映射关系。这样有了上面 key 对应的槽位,那么它应该转发到哪个 Redis 实例就很明确了。

3.2 codis 扩容

刚开始 Codis 后端只有一个 Redis 实例,1024 (2的10次方)个槽位全部指向同一个 Redis。然后一个 Redis 实例内存不够了,所以又加了一个 Redis 实例。这时候需要对槽位关系进行调整,将一半的槽位划分到新的节点。这意味着需要对这一半的槽位对应的所有 key 进行迁移,迁移到新的 Redis 实例。

那 Codis 如何找到槽位对应的所有 key 呢?

Codis 对 Redis 进行了改造,增加了 SLOTSSCAN 指令,可以遍历指定 slot 下所有的 key。Codis 通过 SLOTSSCAN 扫描出待迁移槽位的所有的 key,然后挨个迁移每个 key 到新的 Redis 节点。

在迁移过程中,Codis 还是会接收到新的请求打在当前正在迁移的槽位上,因为当前槽位的数据同时存在于新旧两个槽位中,Codis 如何判断该将请求转发到后面的哪个具体实例呢?

Codis 无法判定迁移过程中的 key 究竟在哪个实例中,所以它采用了另一种完全不同的思路。当 Codis 接收到位于正在迁移槽位中的 key 后,会立即强制对当前的单个 key 进行迁移,迁移完成后,再将请求转发到新的 Redis 实例。

 

3.3 mget操作过程

                                                

mget 指令用于批量获取多个 key 的值,这些 key 可能会分布在多个 Redis 实例中。Codis 的策略是将 key 按照所分配的实例打散分组,然后依次对每个实例调用 mget 方法,最后将结果汇总为一个,再返回给客户端。

 

4 cluster

相对于 Codis 的不同,cluster是去中心化的,每个节点都是master,每个节点可以有多个从节点(保证主节点可以进行故障转移,其实这里的主从跟sentinel有点类似)。

Redis Cluster 将所有数据划分为 16384 (2的14次方)的 slots,它比 Codis 的 1024 个槽划分的更为精细,每个节点负责其中一部分槽位。槽位的信息存储于每个节点中,它不像 Codis,它不需要另外的分布式存储来存储节点槽位信息。当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息。这样当客户端要查找某个 key 时,可以直接定位到目标节点。

另外,每个节点都会存储clusternode(包括自己的、集群中其他节点的节点信息)、cluseterstate (以当前节点为视角的总体集群概况),clusterstate里包含了1个二进位数组,保存对16384个每个槽位对应的节点,这些数据结构会实时的根据节点故障转移、消息传播、迁移划分等操作做出响应的改变。

延伸一下为什么redis的槽位是16384个? redis的作者给的回答是由于节点之间的心跳包都要带上槽位信息,用bitmap压缩后后16384个只占用2K空间,redis集群理论上不会超过1000个节点,不需要更大的槽位。)

                                      

4.1 cluster 分片原理

Cluster 默认会对 key 值使用 crc16 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 (2的14次方)进行取模来得到具体槽位。Cluster 还允许用户强制某个 key 挂在特定槽位上,通过在 key 字符串里面嵌入 tag 标记,这就可以强制 key 所挂在的槽位等于 tag 所在的槽位。

 

总结:

1、sentinel 着眼于高可用,常用于单机模式,1台master,多台salve

2、集群化方案是codis 和 cluster,着眼于可扩展。 codis 是个转发代理的中间件,负责将客户端的请求转发到redis实例。cluster是去中心化的,每个节点都是master。 Codis 会在内存维护槽位和 Redis 实例的映射关系,而cluster槽位信息存储在每个master节点,所以当客户端要查找某个Key时,Codis 需要通过 Proxy 来定位目标节点,而cluster 可以直接定位redis节点。codis 和 cluster的分片原理也不同,cluster 将所有数据划分为 16384 的 slots,它比 Codis 的 1024 个槽划分的更为精细。

问题: 生产环境选择codis还是cluster呢? 

答:codis已经被很多公司用于生产环境,豆瓣也一直在维护升级。cluster 是redis 的亲儿子,国内用的比较少。

codis

Codis是一整套缓存解决方案,包含高可用、数据分片、监控、动态扩态 etc.。
走的是 Apps->代理->redis cluster,一定规模后基本都采用这种方式。

  1. codis是选用了一系列已证明靠谱的方案来构建(如zk选主/存放元数据;采用无状态proxy,而不是smart client等)
  2. 为方便运维提供了一系列工具/接口(dashboard,监控等)
  3. 再加上公司内部的一定规模应用

Redis cluster
刚出来短期不成熟,生产不建议用。
单纯的数据分片,无其他功能。
走的是 Apps->redis server jump redis server,大规模后不方便统一管理。

推荐Codis。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值