Redis学习——入门篇④
- 6. Redis集群(cluster)
- 6.1 Redis集群是什么,能干什么
- 6.2 Redis集群的槽位-分片
- 6.2.1 槽位
- 6.2.2 分片
- 6.2.3 优点
- 6.3 slot槽位映射 分区,一般业界有 3 种解决方案
- 6.3.1 哈希取余分区算法
- 6.3.1.1 哈希取余分区算法优点
- 6.3.1.2 哈希取余分区算法缺点
- 6.3.2 一致性hash算法分区
- 6.3.2.1 一致性hash算法分区的步骤
- 6.3.2.2 一致性hash算法分区优点
- 6.3.2.3 一致性hash算法分区缺点
- 6.3.3 哈希槽分区(最牛逼)slot到底怎么来的!!!
- 6.4 经典面试题:why redis-cluster use 16384 slots?
- 6.5 不保证强一致性
- 6.6 环境搭建
- 6.6.1 集群读写
- 6.6.2 主从容错切换
- 6.6.3 CLUSTER FAILOVER ——节点从属调整
- 6.6.4 集群扩容
- 6.6.5 缩容
- 6.7 小总结
- 6.7.1 slot(槽)常用配置和命令
6. Redis集群(cluster)
6.1 Redis集群是什么,能干什么
https://redis.io/docs/reference/cluster-spec/
由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Redis的集群,其作用是提供在多个Redis节点间共享数据的程序集。
熟悉 复制 -》哨兵 -》集群的演进过程。
High performance and linear scalability up to 1000 nodes.
Tips:1000个节点
Redis集群是一个提供在多个Redis节点间共享数据的程序集
Redis集群可以支持多个Master
- Redis集群支持多个Master,每个Master又可以挂载多个Slave
- 读写分离
- 支持数据的高可用
- 支持海量数据的读写存储操作
- 由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
- 客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一一个可用节点即可
- 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系
6.2 Redis集群的槽位-分片
对于6.2小节 我们先知道槽位-分片的概念就好 我们看完6.3 然后在回来看6.2!!!!!
https://redis.io/docs/reference/cluster-spec/#key-distribution-model
6.2.1 槽位
集群的密钥空间被分成16384个槽,有效地设置了16384 个主节点的集群大小上限(但是,建议的最大节点大小约为1000个节点)。
集群中的每个主节点处理16384个哈希槽的一个子集。当没有集群重新配置正在进行时(即哈希槽从一个节点移动到另一一个节点),集群是稳定的。当集群稳定时,单个哈希槽将由单个节点提供服务(但是,服务节点可以有一个或多个副本,在网络分裂或故障的情况下替换它,并且可以用于扩展读取陈旧数据是可接受的操作)
Redis没有使用一致性Hash,而是使用Slot槽位。每一个 key 经过 CRC16算法取模后落到某一个具体的槽位。
HASH_SLOT = CRC16(key) mod 16384
6.2.2 分片
A | B |
---|---|
分片是什么 | 使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。 |
如何找到给定 | 为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这key的分片意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。 |
6.2.3 优点
最大优势,方便扩缩容和数据分派查找这种结构很容易添加或者删除节点比如如果我想新添加个节点D,我需要从节点A, B, C中得部分槽到D上,如果我想移除节点A.需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态
6.3 slot槽位映射 分区,一般业界有 3 种解决方案
6.3.1 哈希取余分区算法
2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一-个集群, 用户每次读写操作都是根据公式
hash(key) % N个机器台数
,计算出哈希值,用来决定数据映射到哪一个节点上。
6.3.1.1 哈希取余分区算法优点
简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一-段时间的数据 支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求( 并维护这些请求的信息),起到负载均衡+分而治之的作用。
6.3.1.2 哈希取余分区算法缺点
原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化: Hash(key)/3
会变成Hash(key) /?
。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。
某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
普通 hash 取余最大的问题就集群节点扩容的时候,取模公式会发生变化。
6.3.2 一致性hash算法分区
一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。
提出一致性Hash解决方案。
- 目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系
6.3.2.1 一致性hash算法分区的步骤
- 算法构建一致性哈希环
一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0, 2 32 − 1 2^{32}-1 232−1] ,这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连( 0 = 2 32 0 = 2^{32} 0=232 ),这样让它逻辑上形成了一个环形空间。
它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对 2 32 2^{32} 232 取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个 虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1 (即哈希值是一个32位无符号整形) ,整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一一个 点代表1,以此类推,2、3、4、一直到 2 32 − 1 2^{32}-1 232−1, 也就是说0点左侧的第一个 点代表 2 32 − 1 2^{32}-1 232−1,0和 2 32 − 1 2^{32}-1 232−1在零 点中方向重合,我们把这个由 2 32 2^{32} 232个点组成的圆环称为Hash环。
- 服务器IP节点映射
将集群中各个IP节点映射到环上的某一个位置。
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip))
, 使用IP地址哈希后在环空间的位置如下:
- key落到服务器的落键规则
当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key), 将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。
如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一-致性Hash算法, 数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。
6.3.2.2 一致性hash算法分区优点
容错性
假设Node C宕机可以看到此时对象A、B、D不会受到影响。一般的, 在一致性Hash算法中, 如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器) 之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据且这些数据会转移到D进行存储。
扩展性
数据量增加了,需要增加一台节点NodeX, X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。
6.3.2.3 一致性hash算法分区缺点
Hash环的数据倾斜问题
一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一 台服务器上)问题,例如系统中只有两台服务器
6.3.3 哈希槽分区(最牛逼)slot到底怎么来的!!!
1. 为什么出现
- 一致性哈希算法的数据倾斜问题
- 哈希槽实质就是一个数组, 数组 [ 0 , 2 14 − 1 ] [0,2^{14} -1] [0,214−1]( [ 0 , 16383 ] [0,16383] [0,16383])形成hash slot空间。
2. 能干什么
- 解决均匀分配的问题, 在数据和节点之间又加入了一层,把这层称为哈希槽(slot) ,用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
在数据和节点中间加一层 slot
HASH_SLOT = CRC16(key) mod 16384
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配
3 多少个hash槽
- 一个集群只能有16384个槽,编号0-16383 (0-2^14-1) 。这些槽会分配给集群中的所有主节点,分配策略没有要求。
- 集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取模,余数是几key就落入对应的槽里。
- HASH_ SLOT = CRC16(key) mod 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
Redis集群中内置了16384个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在Redis集群中放置一个key-value时,redis先对key使用crc16 算法算出- -个结果然后用结果对16384求余数[ CRC16(key) % 16384],这样每个key都会对应一个编号在0-16383之间的哈希槽,也就是映射到某个节点上。如下代码,key之A、B在Node2,key之 C落在Node3上
6.4 经典面试题:why redis-cluster use 16384 slots?
-
如果槽位为65536,发送ping信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]
。 当槽位为65536时, 这块的大小是:
65536➗ 8➗1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]
。 当槽位为16384时, 这块的大小是: 16384➗8➗1024=2kb
因为每秒钟,redis
节点需要发送一定 数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。 -
redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。那么, 对于节点数在1000以内的redis cluster集群,16384个 槽位够用了。没有必要拓展到65536个。 -
槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap
的形 式来保存的,在传输过程中会对bitmap
进行压缩,但是如果bitmap的填充率slots / N
很高的话(N表示节点数),bitmap的压缩率就很低。如果 节点数很少,而哈希槽数量很多的话,bitmap
的压缩 率就很低。
214=16384、216=65536。
如果槽位是65536个,发送心跳信息的消息头是65536/8/1024 = 8k。
如果槽位是16384个,发送心跳信息的消息头是16384/8/1024 = 2k。
因为Redis每秒都会发送一定数量的心跳包,如果消息头是8k,未免有些太大了,浪费网络资源。
上面提过,Redis的集群主节点数量一般不会超过1000个。集群中节点越多,心跳包的消息体内的数据就越多,如果节点过多,也会造成网络拥堵。因此Redis的作者Salvatore Sanfilippo不建议Redis Cluster的节点超过1000个,对于节点数在1000个以内的Redis Cluster,16384个槽位完全够用。
Redis主节点的哈希槽信息是通过bitmap存储的,在传输过程中,会对bitmap进行压缩,bitmap的填充率越低,压缩率越高。
bitmap 填充率 = slots / N (N表示节点数)。
也就是说slots越小,填充率就会越小,压缩率就会越高,传输效率就会越高。
6.5 不保证强一致性
集群并不能保证数据的一个强一致。
6.6 环境搭建
目标:三主三从搭建。
第一步:准备集群配置文件。
bind 0.0.0.0
protected-mode no
daemonize yes
port 6379
logfile "/root/redis-cluster/6379.log"
pidfile /root/redis-cluster/redis_6379.pid
dir /root/redis-cluster/
dbfilename 6379.rdb
appendonly yes
appendfilename "6379.aof"
requirepass 123456
masterauth 123456cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
其他5台将 6379 改为对应端口。
第二步:启动 6台 Redis 实例。
Tips:因为内存原因,这里放在一台机器上启动6个实例,生产环境务必拆分。
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6379.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6380.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6381.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6382.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6383.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-server redisCluster6384.conf
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ ps -ef|grep redis
matthew 99779 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6379 [cluster]
matthew 99785 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6380 [cluster]
matthew 99791 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6381 [cluster]
matthew 99797 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6382 [cluster]
matthew 99803 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6383 [cluster]
matthew 99809 852 0 14:54 ? 00:00:00 redis-server 0.0.0.0:6384 [cluster]
matthew 99815 28780 0 14:55 pts/0 00:00:00 grep --color=auto redis
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$
第三步:通过 redis-cli 构建集群关系。
redis-cli -a 123456 --cluster create --cluster-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:6384redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.139.140:6379 192.168.139.140:6380 192.168.139.140:6381 192.168.139.140:6382 192.168.139.140:6383 192.168.139.140:6384
分配结果
Tips:实际主从实例分配会有不同,以实际为准,如果使用127.0.0.1可能会在SpringBoot连接过程中报错,参考最后
第四步:连接任一实例查看集群信息
redis-cli -p 6379 -a 123456
CLUSTER NODES 命令类似于 INFO replication
CLUSTER INFO 某一个节点信息
6.6.1 集群读写
默认情况下,连某一台实例只能操作管理的 slot
127.0.0.1:6379> set k1 v1
(error) MOVED 12706 127.0.0.1:6381
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> keys *
1) "k2"
那么问题来了!我的k1呢!!! 它提示6381 好!我们看看6381
matthew@matthew-virtual-machine:~/redis-7.2.4/myredis$ redis-cli -p 6381 -a 123456
127.0.0.1:6381> keys *
(empty array)
127.0.0.1:6381> set k1 v1
OK
127.0.0.1:6381>
一脸懵啊!
一定注意槽位的范围区间,需要路由到位,路由到位,路由到位,路由到位!!!
咋看槽位
使用 -c 路由
CLUSTER KEYSLOT 命令查看某个key属于某个slot
再看看槽位!
6.6.2 主从容错切换
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6384,state=online,offset=1592,lag=1
(看你自己的 slave是什么 这个是例子)已知 6379 的 slave 是 6384,我们手动将 6379 停机观察集群情况。
[root@localhost redis-cluster]# redis-cli -p 6379 -a 123456 -c
127.0.0.1:6379> shutdown
not connected> quit[root@localhost redis-cluster]# redis-cli -p 6380 -a 123456 -c
127.0.0.1:6380> CLUSTER nodes
可以看到 6384 变为了 master,如果 6379 回到集群呢 ?
[root@localhost redis-cluster]# redis-server 6379.conf
[root@localhost redis-cluster]# redis-cli -p 6380 -a 123456 -c
6379 变为了 slave
6.6.3 CLUSTER FAILOVER ——节点从属调整
我想恢复怎么办???
将 slave 提升为 master ,原来的 master 降级为 slave
[root@localhost redis-cluster]# redis-cli -p 6380 -a 123456 -c
127.0.0.1:6380> CLUSTER FAILOVER
(error) ERR You should send CLUSTER FAILOVER to a replica
127.0.0.1:6380> quit
[root@localhost redis-cluster]# redis-cli -p 6379 -a 123456 -c
127.0.0.1:6379> CLUSTER FAILOVER
OK
127.0.0.1:6379>
[root@localhost redis-cluster]# redis-cli -p 6379 -a 123456 -c
6.6.4 集群扩容
口诀:加主,分配,加从
第一步:新建两个配置文件,端口号改为6385和6386,启动服务
[root@localhost redis-cluster]# cp 6379.conf 6385.conf
[root@localhost redis-cluster]# cp 6379.conf 6386.conf
[root@localhost redis-cluster]# redis-server 6385.conf
[root@localhost redis-cluster]# redis-server 6386.conf
[root@localhost redis-cluster]# ps -ef|grep redis
root 85927 1 0 13:47 ? 00:00:04 redis-server 0.0.0.0:6380 [cluster]
root 85957 1 0 13:48 ? 00:00:04 redis-server 0.0.0.0:6381 [cluster]
root 85981 1 0 13:48 ? 00:00:05 redis-server 0.0.0.0:6382 [cluster]
root 86001 1 0 13:48 ? 00:00:05 redis-server 0.0.0.0:6383 [cluster]
root 86023 1 0 13:48 ? 00:00:05 redis-server 0.0.0.0:6384 [cluster]
root 96087 1 0 14:15 ? 00:00:01 redis-server 0.0.0.0:6379 [cluster]
root 99298 1 0 14:23 ? 00:00:00 redis-server 0.0.0.0:6385 [cluster]
root 99332 1 0 14:23 ? 00:00:00 redis-server 0.0.0.0:6386 [cluster]
root 99398 4969 0 14:24 pts/0 00:00:00 grep --color=auto redis
第二步:加入集群
[root@localhost redis-cluster]# redis-cli -a 123456 --cluster add-node 127.0.0.1:6385 127.0.0.1:6379
相当于6385通过6379(介绍人)加入集群(组织)。
第三步:重新分配 slot, 16384 / 4 = 4096
redis-cli -a 123456 --cluster reshard 127.0.0.1:6379
Source node #1: 填 all
-–cluster check
检查集群命令
[root@localhost redis-cluster]# redis-cli -a 123456 --cluster check 127.0.0.1:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379 (21257959...) -> 0 keys | 4096 slots | 1 slaves.
127.0.0.1:6381 (942c3eb2...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:6380 (1aa080e1...) -> 0 keys | 4096 slots | 1 slaves.
127.0.0.1:6385 (49356d9d...) -> 1 keys | 4096 slots | 0 slaves.
[OK] 2 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 212579596bef87a4cd4dd35b6a6f15a2a78a069d 127.0.0.1:6379slots:[1365-5460] (4096 slots) master1 additional replica(s)
M: 942c3eb2894912308f166c1035167ec70f6cceb2 127.0.0.1:6381slots:[12288-16383] (4096 slots) master1 additional replica(s)
S: 4a6a56ea1aa80cf7ba4e32cbc35cf8901e16485c 127.0.0.1:6382slots: (0 slots) slavereplicates 1aa080e1ed7cd0f8d7c871ac274b0f7b01db8b42
M: 1aa080e1ed7cd0f8d7c871ac274b0f7b01db8b42 127.0.0.1:6380slots:[6827-10922] (4096 slots) master1 additional replica(s)
M: 49356d9d1c0c8fd1dc7b0d3a29371f032f5b1afa 127.0.0.1:6385slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
S: 74c5b67bf568bf1b5e487d3a5c6673edc7b05842 127.0.0.1:6383slots: (0 slots) slavereplicates 942c3eb2894912308f166c1035167ec70f6cceb2
S: e1c3fcd46f3fd4da0bbca08c2fc3ad06d1cf2f5a 127.0.0.1:6384slots: (0 slots) slavereplicates 212579596bef87a4cd4dd35b6a6f15a2a78a069d
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost redis-cluster]#
可以看到每一个master都是4096个slot
第四步:给6385添加 slave 6386
redis-cli -a 123456 --cluster add-node 127.0.0.1:6386 127.0.0.1:6385 --cluster-slave --cluster-master-id 49356d9d1c0c8fd1dc7b0d3a29371f032f5b1afa
cluster-master-id 填 master 6385 的 ID
[root@localhost redis-cluster]# redis-cli -a 123456 --cluster check 127.0.0.1:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379 (21257959...) -> 0 keys | 4096 slots | 1 slaves.
127.0.0.1:6381 (942c3eb2...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:6380 (1aa080e1...) -> 0 keys | 4096 slots | 1 slaves.
127.0.0.1:6385 (49356d9d...) -> 1 keys | 4096 slots | 1 slaves.
[OK] 2 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 212579596bef87a4cd4dd35b6a6f15a2a78a069d 127.0.0.1:6379slots:[1365-5460] (4096 slots) master1 additional replica(s)
M: 942c3eb2894912308f166c1035167ec70f6cceb2 127.0.0.1:6381slots:[12288-16383] (4096 slots) master1 additional replica(s)
S: 4a6a56ea1aa80cf7ba4e32cbc35cf8901e16485c 127.0.0.1:6382slots: (0 slots) slavereplicates 1aa080e1ed7cd0f8d7c871ac274b0f7b01db8b42
M: 1aa080e1ed7cd0f8d7c871ac274b0f7b01db8b42 127.0.0.1:6380slots:[6827-10922] (4096 slots) master1 additional replica(s)
M: 49356d9d1c0c8fd1dc7b0d3a29371f032f5b1afa 127.0.0.1:6385slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master1 additional replica(s)
S: 74c5b67bf568bf1b5e487d3a5c6673edc7b05842 127.0.0.1:6383slots: (0 slots) slavereplicates 942c3eb2894912308f166c1035167ec70f6cceb2
S: 3ef2ce807bdd74f767033e1fb33c5c4f3d28ea60 127.0.0.1:6386slots: (0 slots) slavereplicates 49356d9d1c0c8fd1dc7b0d3a29371f032f5b1afa
S: e1c3fcd46f3fd4da0bbca08c2fc3ad06d1cf2f5a 127.0.0.1:6384slots: (0 slots) slavereplicates 212579596bef87a4cd4dd35b6a6f15a2a78a069d
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost redis-cluster]#
6.6.5 缩容
口诀:删从,重分配,删主。
第一步:删除从节点 6386
[root@localhost redis-cluster]# redis-cli -a 123456 --cluster del-node 127.0.0.1:6386 3ef2ce807bdd74f767033e1fb33c5c4f3d28ea60
>>> Removing node 3ef2ce807bdd74f767033e1fb33c5c4f3d28ea60 from cluster 127.0.0.1:6386
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
删除后 check 命令可以看到少了一台 6386
第二步:重新分配槽位
redis-cli -a 123456 --cluster reshard 127.0.0.1:6379
What is the receiving node ID? 填想要接收 slot 的ID,填 6379 的ID。
Source node #1: 填 slot 来源的 ID,填 6385 的ID。
Source node #2:done
M: 212579596bef87a4cd4dd35b6a6f15a2a78a069d 127.0.0.1:6379slots:[0-6826],[10923-12287] (8192 slots) master2 additional replica(s)
第三步:删除节点
redis-cli -a 123456 --cluster del-node 127.0.0.1:6385 49356d9d1c0c8fd1dc7b0d3a29371f032f5b1afa
第四步:check
127.0.0.1:6379 (21257959...) -> 1 keys | 8192 slots | 1 slaves.
127.0.0.1:6381 (942c3eb2...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:6380 (1aa080e1...) -> 0 keys | 4096 slots | 1 slaves.
6.7 小总结
不在一个slot下的多key操作支持不好,通识占位符
[root@localhost redis-cluster]# redis-cli -a 123456 -p 6379 -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> mget k1 k2
(error) CROSSSLOT Keys in request don't hash to the same slot
127.0.0.1:6379> mset k1{z} v1 k2{z} v2 k3{z} v3
-> Redirected to slot [8157] located at 127.0.0.1:6380
OK
127.0.0.1:6380> mget k1{z} k2{z} k3{z}
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6380>
不在同一个 slot 无法使用 mset mget,可以使用{}定义一个组的概念,使 key 中{}相同内容的放到一个slot 中。
6.7.1 slot(槽)常用配置和命令
-
配置文件参数:
cluster-require-full-coverage yes
:要求集群完整性设置为yes,否则设置为no。
- -
CLUSTER COUNTKEYSINSLOT slotNum
:统计某个 slot key 的数量
-
CLUSTER KEYSLOT key
:计算key会落到哪一个slot。