前言
我们知道Redis官方给出Redis的QPS能达到10W/s,这是一个非常快的速度,但是如果这样的数据还无法满足我们的需求,比如100W/s。其次,我们业务需要很大的内存存储用户数据,这样我们Redis在单机模式也是无法满足的。我们需要如何解决?
在单机器无法满足需求的时候,我们就会想到多机器来管理,Reids为我们提供了Cluster去能让我们能管理我们的机器,也就是集群管理。
Cluster 在 Redis 3.0 提供
数据分布
当我们单机器无法满足需求时我们就可以使用多机器,数据存在不同的机器这就引出了一个问题,我们数据如何分区才能使效率更高。这有点像HashMap里的hash函数,都是为了解决数据操作效率。
-
1、顺序分布
假设我们有三个节点,我们就平均的将节点分成三份 -
2、哈希分布
同样三个节点,我们取hash(key)%3来存取 -
3 对比
分布方式 特点 典型产品 哈希分布 数据分散度高、键值分布业务无关、无法顺序访问、支持批量操作 一致性哈希Memccache、Redis Cluster 顺序分布 数据分散度易倾斜、键值业务相关、可顺序访问、支持批量操作 Big Table、Hbase
因为Redis Cluster是哈希分布的,所以我们下面对其做详细说明。
哈希分布主要有三种方式:
-
节点取余分区
虽然节点取余方法比较简单,但是也有很大的一个缺点,就是如果我们这是需要添加一个节点,那么我们就需要数据就会做很多的偏移。所以为来缓解这个缺点,我们可以参考HashMap的一个扩容机制,节点控制在2^n并且每次扩容扩大两倍,这样节点的迁移能把迁移量控制在50%。 -
一致性哈希分区
我们把节点数据想象成一个环,每个节点管理环的一个部分。比如说我们对键取hash之后落到图中的黄色位置,这是将按照顺时针方式寻找第一个节点,也就是图中黄色位置的节点就归n2节点管理。
这样有什么好处呢,它有效的避免了节点取余的缺点,比如这时我们添加一个节点。
我们添加节点之后只需要迁移n2的数据,并不会影响到其他节点的数据!
当然这样也还是会有问题,看图就知道这样添加节点会影响数据的分布了,所以还是建议翻倍伸缩,这样才能保证数据的均衡分布。 -
虚拟槽分区(Redis Cluster使用)
使用预设虚拟槽的方式,每个槽映射一个数据子集。这是什么意思?
比如说我有100W个数据,Redis提供给我们默认16384个槽,我们会把100W对16383取余得到每个槽管理的数据,之后当数据进来时使用hash函数CRC16进行hash处理分配到对应的槽。虚拟槽分区是服务端控制管理节点,而其他两种方式都是通过客户端进行管理
上面就是虚拟槽分配的工作原理,分配规则我们上面已经讲过了。现在讲讲具体存储过程。
当keys进来时,我们通过hash函数CRC16进行处理,在对16383取余就可以知道这个keys是属于哪个槽了,之后我们将数据发给Redis Cluster的任意一个节点,首先发送的节点会进行判断这个keys是不是属于我管理的槽,如果是就存下来,如果不是,则会通知你是哪个槽管理的,之后在去寻找对应的槽即可。Redis Cluster使用消息共享的模式,所以每个节点都知道其他节点所管理的槽
集群搭建
我们先看看Redis Cluster的架构
在上图中,我们看到每个节点都是可以相互通信的,所以我们客户端存储的时候对其中一个节点进行请求,都可以得到相应节点的回复。
搭建Redis Cluster
- 1 分配节点
- 2 meet操作(使各个节点能相互通信)
- 3 指派槽
- 4 复制(提供高可用)
集群伸缩
- 伸缩原理
集群的伸缩通过Redis Cluster管理,比如图右侧,我们添加了一个节点,Redis Cluster就会帮我们进行meet,和槽的转移等等操作。集群伸缩 = 槽和数据在节点之间的移动
- 扩容集群
- 准备节点
- 加入集群(进行meet操作)
- 迁移数据
- 缩容集群
客户端操作
-
moved重定向
- 槽未命中
- 槽命中
- 槽未命中
-
ask重定向
当访问数据节点时发现数据已经迁移了
同样的原理 -
moved 和 ask
- 两者都是客户单重定向
- moved:槽以确定迁移
- ask:槽还在迁移中
-
smart客户端
我们客户端可以缓存节点信息,这样就不用每次都需要到服务端进行计算节点了,具体的过程如下: