文章目录
1、是什么
1.1、定义
1.2、官网
1.3、一图
1.4、一句话
- Redis集群是一个提供在多个Redis节点间共享数据的程序集
- Redis集群可以支持多个Master。
2、能干嘛
- Redis集群支持多个Master,每个Master又可以挂载多个Slave
- 读写分离
- 支持数据的高可用
- 支持海量数据的读写存储操作
- 由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵。
- 客户端与Redis的节点连接,不再需要连接集群中的所有的节点,只需要任意连接集群中的一个可用节点即可。
- 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系
3、集群算法-分片-槽位slot
3.1、官网出处
说明:
3.1、redis集群的槽位slot
3.2、redis集群的分片
3.3、他俩的优势
- 最大优势,方便扩缩容和数据分派查找。
3.4、slot槽位映射,一般业务有三种解决方案
哈希取余分区
一致性哈希算法分区
是什么:
- 一致性Hash算法背景:
- 一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。
能干嘛:
- 提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。
三大步骤:
- 算法构建一致性哈希环
- 服务器ip节点映射
- key落到服务器的落键规则
优点:
- 一致性哈希算法的容错性:
- 一致性哈希算法的扩展性:
缺点:
- 一致性哈希算法的数据倾斜问题:
小总结:
哈希槽分区
是什么
HASH_SLOT = CRC16(key) mod 16384
- 为什么出现
- 由于一致性哈希算法存在数据倾斜问题,所以提出了哈希槽的做法。
- 哈希槽的实质就是一个数组,数组[0,2^14-1]形成hash slot空间。
- 能干什么
- 解决均匀分配问题,在数据和节点之间又接了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系。现在就相当于节点上放的是槽,槽里放的是数据。
- 槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。
哈希槽计算
3.5、经典面试题
为什么redis集群的最大槽数位16384个?
说明一:
说明二:
3.6、Redis集群不保证强一致性,这意味着在特定的条件下,redis集群可能会丢失一些被系统收到的写入请求命令
4、集群环境案例步骤
4.1、3主3从redis集群配置
找3台真实虚拟机,各自新建
mkdir -p /myredis/cluster
新建6个独立的redis实例服务
IP:192.168.100.100+端口6381/端口6382:
vim /myredis/cluster/redisClustser6381.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6381
logfile "/myredis/cluster/cluster6381.log"
pidfile /myredis/cluster6381.pid
dir /myredis/cluster
dbfilename dump6381.rdb
appendonly yes
appendfilename "appendonly6381.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6381.conf
cluster-node-timeout 5000
vim /myredis/cluster/redisClustser6382.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6382
logfile "/myredis/cluster/cluster6382.log"
pidfile /myredis/cluster6382.pid
dir /myredis/cluster
dbfilename dump6382.rdb
appendonly yes
appendfilename "appendonly6382.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6382.conf
cluster-node-timeout 5000
IP:192.168.100.101+端口6383/端口6384:
vim /myredis/cluster/redisClustser6383.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6383
logfile "/myredis/cluster/cluster6383.log"
pidfile /myredis/cluster6383.pid
dir /myredis/cluster
dbfilename dump6383.rdb
appendonly yes
appendfilename "appendonly6383.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6383.conf
cluster-node-timeout 5000
vim /myredis/cluster/redisClustser6384.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6384
logfile "/myredis/cluster/cluster6384.log"
pidfile /myredis/cluster6384.pid
dir /myredis/cluster
dbfilename dump6384.rdb
appendonly yes
appendfilename "appendonly6384.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6384.conf
cluster-node-timeout 5000
IP:192.168.100.102+端口6385/端口6386:
vim /myredis/cluster/redisClustser6385.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6385
logfile "/myredis/cluster/cluster6385.log"
pidfile /myredis/cluster6385.pid
dir /myredis/cluster
dbfilename dump6385.rdb
appendonly yes
appendfilename "appendonly6385.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6385.conf
cluster-node-timeout 5000
vim /myredis/cluster/redisClustser6386.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6386
logfile "/myredis/cluster/cluster6386.log"
pidfile /myredis/cluster6386.pid
dir /myredis/cluster
dbfilename dump6386.rdb
appendonly yes
appendfilename "appendonly6386.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6386.conf
cluster-node-timeout 5000
启动六个集群实例:
通过redis-cli命令为6台机器构建集群关系
构建主从关系命令:redis-cli -a 111111 --cluster create --cluster-replicas 1 192.168.100.100:6381 192.168.100.100:6382 192.168.100.101:6383 192.168.100.101:6384 192.168.100.102:6385 192.168.100.102:6386
- –cluster-replicas 1 :表示为每一个master创建爱你一个slave节点。
新出现的配置文件:
一切OK的话,三主三从配置完成。
链接进入6381作为切入点,查看并验证集群状态
链接进入6381作为切入点,查看节点状态:
info replication
:
cluster info
:
cluster nodes
:
4.2、3主3从redis集群读写
对6381新增两个key,看看效果如何
为什么报错
- 一定要注意槽位的范围区间,需要路由到位,路由到位,路由到位,路由到位。
如何解决
- 防止路由失效加参数-c并新增两个key进行测试
查看集群信息
查看某个key该属于对应的槽位值
CLUSTER KEYSLOT 键名称
4.3、主从容错切换迁移案例
容错切换迁移
先查看集群信息,查看主从关系:
停止主机6381,再次查看集群关系:
随后,6381原来的主机回来了,是否会上位:
集群不保证数据一致性100%ok,一定会有数据丢失情况
- Redis集群不保证强一致性,这意味着在特定的条件下,Redis集群可能会丢掉一些被系统收到的写入请求命令。
手动故障转移or节点从属调整该如何处理
- 上面一换6381、6384主从对调了,和原始设计图不一样了,该如何
- 重新登陆6381机器。
- 常用命令:
CLUSTER FAILOVER
4.4、主从扩容案例
新建6387、6388两个服务实例配置文件+新建后启动
vim /myredis/cluster/redisCluster6387.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6387
logfile "/myredis/cluster/cluster6387.log"
pidfile /myredis/cluster6387.pid
dir /myredis/cluster
dbfilename dump6387.rdb
appendonly yes
appendfilename "appendonly6387.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6387.conf
cluster-node-timeout 5000
vim /myredis/cluster/redisCluster6388.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6388
logfile "/myredis/cluster/cluster6388.log"
pidfile /myredis/cluster6388.pid
dir /myredis/cluster
dbfilename dump6388.rdb
appendonly yes
appendfilename "appendonly6388.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-6388.conf
cluster-node-timeout 5000
启动87/88两个新的节点实例,此时他们自己都是master
将新增的6387节点(空槽号)作为master节点加入原集群
- 将新增的6387作为master节点加入原有集群
- 命令:
redis-cli -a 密码 --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
6387 就是将要作为master新增节点
6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群
redis-cli -a 111111 --cluster add-node 192.168.100.102:6387 192.168.100.100:6381
检查集群情况第一次
命令:
redis-cli -a 密码 --cluster check 真实IP地址:6381
重新分配槽号(reshard)
命令:
redis-cli -a 密码 --cluster reshard IP地址:端口号
几个问题:
这里相当于16384个槽四个主节点分,一个主节点是4096个:
这里表示要分配给谁:
没有问题填写all:
检查集群情况第二次
槽号分配说明:
- 为什么6387是三个新区间,以前的还是连续?
- 重新分配成本太高,所以前3家格子匀出一部分,从6381/6383/6385三个旧节点分别匀出1364个坑位给新节点6387。
为主节点6387分配从节点6388
命令:
redis-cli -a 密码 --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
检查集群情况第三次
4.5、主从缩容案例
目的:6387和6388下线
检查集群情况第一次,先获得从节点6388的节点ID
从集群中将4号从节点6388删除
命令:
redis-cli -a 密码 --cluster del-node ip:从机端口 从机6388节点ID
检查一下发现只剩下7台机器了:
将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
检查集群情况第二次
将6387删除
检查集群情况第三次,6387/6388被彻底祛除
5、集群常用操作和CRC16算法分析
5.1、不在同一个slot槽位下的多键操作支持不好,通识占位符登场
不在同一个slot槽位下的键值无法使用mset、mset等多键操作。
可以通过{}来定义同一组的概念,使用key中{}内相同内容的键值对放到一个slot槽位去,对照下图类似k1k2k3都映射为x,自然槽位一样。
5.2、Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置在哪个槽。
- 集群的每个节点负责一部分hash槽。
CRC16源码浅谈:
cluster.c:
5.3、常用命令
集群是否完成才能对外提供服务
cluster-require-full-coverage
CLUSTER COUNTKEYSINSLOT 槽位数字编号
- 返回1:表示该槽位被占用
- 返回2:表示该槽位没占用
CLUSTER KEYSLOT 键名称
- 该键应该存在哪个槽位上