Redis的集群功能和实现
要了解Redis的集群功能,可以从数据分片、数据迁移、集群通讯、故障检测以及故障转移等方面进行了解,Cluster相关的代码也不是很多,注释也很详细,可自行查看,地址是:https://github.com/antirez/redis/blob/unstable/src/cluster.c。
这里由于篇幅的原因,主要从数据分片和数据迁移两方面进行详细介绍:
数据分片
Redis cluster在设计中没有使用一致性哈希(consistency hashing),而是使用数据分片(sharding),引入哈希槽(hash slot)来实现;一个 redis cluster包含16384(0~16383)个哈希槽,存储在redis cluster中的所有的键都会被映射到这些slot中,集群中的每个键都属于这16384个哈希槽的其中一个,集群使用公式slot=CRC16(key)/16384来计算key属于哪个槽,其中CRC16(key)语句用于计算key的CRC16 校验和。
集群中的每个主节点(Master)都负责处理16384个哈希槽中的一部分,当集群处于稳定状态时,每个哈希槽都只由一个主节点进行处理,每个主节点可以有一个到N个从节点(Slave),当主节点出现宕机或网络断线等不可用时,从节点能自动提升为主节点进行处理。
如上,clusterNode数据结构中的slots和numslots属性记录了节点负责处理哪些槽。其中,slot属性是一个二进制位数组(bitarray),其长度为16384/8=2048 Byte,共包含16384个二进制位。集群中的master节点用bit(0和1)来标识对于某个槽是否拥有。比如,对于编号为1的槽,master只要判断序列的第二位(索引从0开始)的值是不是1即可,时间复杂度为O(1)。
集群中所有槽的分配信息都保存在clusterState数据结构的slots数组中,程序要检查槽i是否已经被分配或者找出处理槽i的节点,只需要访问clusterState.slots[i]的值即可,复杂度也为O(1)。clusterState数据结构如下所示:
查找关系如下图:
数据迁移
数据迁移可以理解为slot和key的迁移,这个功能很重要,极大的方便了集群做线性扩展,实现平滑的扩容或缩容。
那么它是一个怎样的实现过程呢
下面举个例子:现在要将Master A节点中的编号为1、2、3的slot迁移到Master B节点中,在slot迁移的中间状态下,slot 1、2、3在Master A节点的状态表现为MIGRATING,在Master B节点的状态表现为IMPORTING。
MIGRATING状态
这个状态如上图所示是被迁移slot在当前所在Master A节点中出现的一种状态,预备迁移slot从Mater A到Master B的时候,被迁移slot的状态首先变为MIGRATING状态,当客户端请求的某个key所属的slot的状态处于MIGRATING状态的时候,可能会出现以下几种情况:
1)如果key存在则成功处理
2)如果key不存在,则返回客户端ASK,客户端根据ASK首先发送ASKING命令到目标节点,然后发送请求的命令到目标节点
3)当key包含多个命令时:
- 如果都存在则成功处理
- 如果都不存在,则返回客户端ASK
- 如果一部分存在,则返回客户端TRYAGAIN,通知客户端稍后重试,这样当所有的key都 迁移完毕的时候客户端重试请求的时候回得到ASK,然后经过一次重定向就可以获取这批键
此时并不刷新客户端中node的映射关系
IMPORTING状态
这个状态如上图所示是被迁移slot在目标Master B节点中出现的一种状态,预备迁移slot从Mater A到Master B的时候,被迁移slot的状态首先变为IMPORTING状态。在这种状态下的slot对客户端的请求可能会有下面几种影响:
1)如果key不存在则新建
2)如果key不在该节点上,命令会被MOVED重定向,刷新客户端中node的映射关系
如果是ASKING命令则命令会被执行,从而key没在被迁移的节点,已经被迁移到目标节点的情况命令可以被顺利执行。
键空间迁移
这是完成数据迁移重要的一步,键空间迁移是指当满足了slot迁移前提的情况下,通过相关命令将slot 1、2、3中的键空间从Master A节点转移到Master B节点,这个过程由MIGRATE命令经过3步真正完成数据转移。步骤示意如下:
经过上面三步可以完成键空间数据迁移,然后再将处于MIGRATING和IMPORTING状态的槽变为常态即可,从而完成整个重新分片的过程。
请您简单介绍下Redis的高可用方案,如果可以,结合您的实践经验和案例进行分析
根据业务的规模以及Redis使用环境的不同,Redis的高可用方案也比较多。这里举一些例子说明一下业界比较常用的一些方案吧。需要说明一下的是下面的这些方案不涉及到同城多活或异地多活的场景,但是部分方案能够做到跨数据中心的灾备。
- Keepalive + Redis
- Redis Sentinel
- Twemproxy + Redis Sentinel + Redis
- Redis Cluster
- Redis Sentinel + Proxy + Zookeeper + Redis
- Zookeeper + MySQL + Redis + DNS