Redis-Cluster集群设计以及原理分析

2020-01-24  本文已影响0人  javap

Redis集群

Redis数据分区

思考:

主从复制是通过将master上的数据全量的复制到一个或多个节点上,这是一种通过数据冗余的形式来保证数据的安全性,但是当主节点发生故障时需要从它的从节点中选出一个作为新的主节点,剩下的从节点要与这个新的主节点进行全量复制,如果节点的数据量非常大的时候会代来两个主要问题,网络阻塞和从节点恢复数据会导致进程阻塞,最终会影响到对外提供服务的稳定性。
解决这个问题的关键是要在不影响服务的前提如何做到这点至关重要减少Redis的数据量,通常我们会采用数据分片的形式来解决问题。将主节点上的全量数据通过分区规则,拆分到不同的分区中,每个节点上可以保存一个或多个分区的数据,将这些节点组成集群对外提供服务。


Cluster集群架构设计
Redis的数据分区规则:

Redis Cluser采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(key)&16383。集群中的每个主节点(Master)都负责处理16384个哈希槽中的一部分,当集群处于稳定状态时,每个哈希槽都只由一个主节点进行处理,每个主节点可以有一个到N个从节点(Slave),当主节点出现宕机或网络断线等不可用时,从节点能自动提升为主节点进行处理。


槽与节点的关系
key映射到槽
Redis集群的特点:
Redis集群与单机相比较在功能上存在一些限制:

集群环境搭建

①准备节点

节点 角色 状态 工作
6379 Master online 处理slot:0-5460
6380 Master online 处理slot:5461-10922
6381 Master online 处理slot:10923-16383
6382 Slave online 复制6379节点
6383 Slave online 复制6380节点
6384 Slave online 复制6381节点

②集群文件目录:


配置文件【 redis-{port}.conf 】:
port 6379
logfile log/6379.log
cluster-enabled yes
dir data
cluster-node-timeout 15000
cluster-config-file nodes-6379.conf

启动:
redis-server conf/redis-6379.conf
redis-server conf/redis-6380.conf
redis-server conf/redis-6381.conf
redis-server conf/redis-6382.conf
redis-server conf/redis-6383.conf
redis-server conf/redis-6384.conf

节点启动成功后会生成一个nodes-{port}.conf的集群配置文件。当集群内节点信息发生变化,如添加节点、节点下线、故障转移等。节点会自动保存集群状态到配置文件中。需要注意的是,Redis自动维护集群配置文件,不要手动修改。
启动后集群配置文件里显示的内容:


<id> <ip:port> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>
127.0.0.1:6379>cluster meet 127.0.0.1 6381
127.0.0.1:6379>cluster meet 127.0.0.1 6382
127.0.0.1:6379>cluster meet 127.0.0.1 6383
127.0.0.1:6379>cluster meet 127.0.0.1 6384


④分配槽
Redis集群把所有的数据映射到16384个槽中。每个key会映射为一个固定的槽,只有当节点分配了槽,才能响应和这些槽关联的键命令。
cluster addslots命令为节点分配槽。所有槽分配完成后集群的状态会变为ok。
⑤主从复制
还有三个节点没有使用,作为一个完整的集群,每个负责处理槽的节点应该具有从节点,保证当它出现故障时可以自动进行故障转移。集群模式下,Reids节点角色分为主节点和从节点。首次启动的节点和被分配槽的节点都是主节点,从节点负责复制主节点槽信息和相关的数据。
cluster replicate <masterid>


redis-trib.rb搭建集群

redis-trib.rb是采用Ruby实现的Redis集群管理工具。内部通过Cluster相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用之前需要安装Ruby依赖环境。

  1. Ruby官网下载安装文件
  2. http://curl.haxx.se/ca/cacert.pem下载证书,放在ruby安装目录下
  3. 设置环境变量SSL_CERT_FILE,指向证书文件
  4. 运行Start Command Prompt with Ruby
  5. 输入gem install redis
    6.从redis3.2源码中的src文件夹下redis-trib.rb 复制到搭建的集群文件夹下
    7.运行redis-trib.rb
准备6个节点,同手动搭建方式一致

*创建集群

redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384

命令语义:创建集群为每个主节点指定一个从节点
create --replicas <slave num> <master ...> <slave ...>
集群完整性检查
集群完整性指所有的槽都分配到存活的主节点上,只要16384个槽中有一个没有分配给节点则表示集群不完整。可以使用redis-trib.rb check命令检测之前创建的集群是否成功。

重新分片

Redis集群提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以下线部分节点进行缩容。扩容与缩容的本质是,对Redis的槽进行重新的分配。
6385新节点上线:



重新分片流程:


重新分配槽:redis-trib.rb reshard host:port --from --to --slots --yes --timeout --pipeline

命令路由


请求重定向最重要的两个步骤是,计算槽和查找槽所在的节点
a.计算槽

故障转移

Redis集群自身实现了高可用,当集群内少量节点出现故障时通过自动故障转移保证集群可以正常对
外提供服务。
1、故障发现
Redis集群内节点通过ping/pong消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。因此故障发现也是通过消息传播机制实现的,主要环节包括:主观下线(pfail)和客观下线(fail)。

typedef struct clusterNodeFailReport {
     struct clusterNode *node; /* 报告该节点为主观下线的节点 */
     mstime_t time; /* 最近收到下线报告的时间 */
} clusterNodeFailReport;

③根据更新后的下线报告链表告尝试进行客观下线。
尝试客观下线流程:


如果在cluster-node-time*2时间内无法收集到一半以上槽节点的下线报告,那么之前的下线报告将会过期,也就是说主观下线上报的速度追赶不上下线报告过期的速度,那么故障节点将永远无法被标记为客观下线从而导致故障转移失败。因此不建议将cluster-node-time设置得过小。
向集群广播下线节点的fail消息:
上一篇下一篇

猜你喜欢

热点阅读