redis分布式系统
redis分布式系统,可以很好地解决不同redis节点存放不同数据,并将用户请求方便地路由到不同redis的问题
数据分区算法
顺序分区
顺序分区规则可以将数据按照某种顺序平均分配到不同的节点。不同的顺序方式,产生了不同的分区算法。
- 轮询分区算法
- 字面意思,就是轮询
- 适用于数据问题不确定的情况
- 生产者要与所有节点保持连接
- 时间片轮转分区算法
- 还是字面意思,类似cpu按时间片调度
- 每段时间产生数据可能不同,各个节点数据分配存在不均可能
- 可以让生产者一次只连接一个节点
- 数据块分区算法
- 还是字面意思,类似存储管理中的段页式存储
- 不同节点作为段,段中数据按页存
- 业务主题分区算法
- 按照业务驱动划分
哈希分区
哈希分区规则是充分利用数据的哈希值来完成分配,对数据哈希值的不同使用方式产生了不同的哈希分区算法。
- 节点取模分区算法
- 对每个节点分配唯一序号,然后对该数据按照一定算法得到其特征key,再计算hash(key)与节点数量N的模,该计算结果即为该数据的存储节点的序号
- 优势:简单
- 缺点:当分布式系统节点数发生变化,则所有数据要根据新的节点数重新分配节点
- 一致性哈希算法
- 将哈希空间抽象成一个圆环,其取值范围为
[0,2^32-1]
- 将服务器节点通过哈希映射到该圆环上
- 将要存储的数据也通过哈希映射到该圆环上
- 哈希环上的数据按顺时针方向寻找服务器节点映射并存储到所对应的服务器节点中
- 我将其理解为将hash空间按照节点hash分段,所有数据经哈希映射后以统一方向去寻找最近段落边界,然后将数据存储到该边界对应的节点中。当因节点数量变化导致hash分段变化时,新增使得所在段一分为二,删除使得邻接段合二为一,由于数据的hash不会发生改变,那么无论是新增还是删除只会影响到变化节点的逆方向到前一节点之间的数据归属(新增则该部分数据归于新节点,删除则该部分数据归于后一节点)
- 将哈希空间抽象成一个圆环,其取值范围为
- 虚拟槽分区算法
- 该算法首先虚拟处一个固定数量的整数集合,该集合中的每个整数称为一个slot槽。这个槽的数量一般远大于节点数量,然后将所有slot槽平均映射到各个节点上。而数据只与slot槽有关系。数据只通过其key的hash(key)映射到slot槽:
slot=hash(key) % slotNums
- 该算法解耦了数据与节点,客户端无法维护节点,只需维护与slot槽关系即可。
- redis数据分区采用该算法,其计算槽点公式为:
slot=CRC16(key)&16383
,这里优化了计算方法,将数学运算转换为了位运算 - 感觉和一致性哈希算法类似,都是将哈希分段然后映射到对应节点,但不同点在于一致性哈希算法是用整个哈希空间来进行划分,使得要写入数据的哈希始终在该范围,而虚拟槽算法是给定一个整数范围,然后将这个整数分段段映射到不同节点,插入数据的哈希会进行二次映射(一次映射到哈希空间,第二次映射到整数范围中的某个段)去找到所属段;该算法未使用整个哈希空间,而是将写入数据哈希进行取模映射,使得不同段的hash对应数据也会被存放到同一节点,使得数据能更好的分散
- 该算法首先虚拟处一个固定数量的整数集合,该集合中的每个整数称为一个slot槽。这个槽的数量一般远大于节点数量,然后将所有slot槽平均映射到各个节点上。而数据只与slot槽有关系。数据只通过其key的hash(key)映射到slot槽:
系统搭建与运行
- 拷贝并修改redis.conf到一个新的目录
- 同样的,该配置文件用于存放共用配置
- 将
working dir
修改为当前目录 - 将
#cluster-emabled yes
注释取消,以开启集群支持
- 创建redis6380.conf
include redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
appendfilename appendonly6380.aof
replica-priority 90
# 指定该节点的集群配置信息(该配置文件是供redis系统进行自动修改的,必须全局唯一)
cluster-config-file nodes-6380.conf
- 将步骤2中的配置文件复制5份,并命名为redis6381到5,并将配置文件中对应数字进行改变
- 将6个redis服务器按对应的配置文件启动
- 使用
redis-cli --cluster create --cluster-replicas 1 192.168.92.129:6380 192.168.92.129:6381 192.168.92.129:6382 192.168.92.129:6383 192.168.92.129:6384 192.168.92.129:6385
来创建一个有3组为1主1从的分布式集群,该命令后接的1表示每个主服务器有1个从服务器,后面的ip:端口是之前创建的redis主机
集群操作
连接集群
连接分布式系统redis-cli -c -p 6380
,-c
用于指定连接的是分布式系统
写入数据
对集群进行写入操作时,若要一次写入多个数据,由于redis底层的虚拟槽分区算法可能会将数据分配到不同槽中,故不能直接进行,要先对所有数据分组才能进行插入
例:mset name{emp} zs age{emp} 22 depart{emp} market
而对于一次插入一条数据则正常插入即可
集群查询
在查询数据时,只能查询当前主机的数据
故障转移
在该分布式系统中,若一个集群的master宕机,则从服务器变为master,继续正常提供服务。
若一个集群内的master和从服务器均宕机则虚拟槽无法覆盖所有空间,默认情况下该分布式系统无法提供服务,若将# cluster-require-full-coverage yes
配置的注释取消掉,则剩余集群仍能对外提供服务
集群扩容
下面会动态扩容1个端口号为6386的master和端口号为6387的slave节点
- 复制并修改两个服务器对应的配置文件(和上节配置的类似)
- 启动系统和两个节点
- 将两个节点绑定为主从集群
- 使用
redis-cli -c --cluster add-node 192.168.92.129:6386 192.168.92.129:6380
命令将集群添加到分布式系统- 该命令中第一个ip为待添加的master,第二个为分布式系统中任一主机ip
- 使用
redis-cli -c --cluster reshard 192.168.92.129:6380
命令来为分布式系统重新分配虚拟槽(会让依次键入要分配槽的大小,分配的目标服务器id,分配方式)- 同样的该ip为分布式系统中任一主机(之前就存在的)
- 使用
redis-cli -c -p 6380 cluster nodes
查看集群状况 - 使用
redis-cli --cluster add-node <slave-id> <集群中任一服务器ip,端口号> --cluster-slave --cluster-master-id <master-id>
命令将slave添加到指定master下
集群缩容
下面会动态移除端口号为6387的slave和端口号为6386的master
- 查看集群各节点信息
redis-cli -c -p <集群中任意主机的ip:端口号> cluster nodes
- 移除slave
redis-cli --cluster del-node <slave的ip和端口号> <slave的动态id>
- 移除master的虚拟槽
redis-cli --cluster reshard <集群中任意主机的ip:端口号>
- 指定要重新分配的虚拟槽数量(会出现一个列表,找到要移除master所对应的数值即可)
- 指定接收虚拟槽主机的动态id
- 指定虚拟槽提供者的动态id
- 移除master节点
redis-cli --cluster del-node <master的ip和端口号> <master的动态id>
redis分布式系统的限制
- 只支持0号数据库
- 在批量key操作支持有限(需要指定组)
- 分区仅限于key
- 事务支持有限(当数据的key的槽点分布到不同的主机上,事务失效)
- 不支持分级管理