吃透Redis系列:“高端”的Redis Cluster

RedisCluster:数据分片与高可用性的深度解析
本文介绍了Redis的哨兵模式局限性及RedisCluster的解决方案,强调了其数据分片带来的容量提升和性能优化。通过环境搭建和测试展示了RedisCluster的高可用性和伸缩性,以及其在大规模场景的应用价值。

欢迎关注微信公众号:互联网全栈架构

Redis提供了高可用的解决方案:哨兵模式,特别是它的自动故障转移功能,很酷,详情请参见:吃透Redis系列:高可用的哨兵模式

然而,它也有一个比较大的缺陷,就是所有的数据都存放在单个主节点上,这样,存储的容量就受到了很大的限制,而且性能也会受到影响。所以,对于大数据量场景下的应用而言,哨兵模式也不是最佳选择。Redis Cluster就应运而生,简单来讲,它把数据进行分片(Shard),然后存放在多个节点上,每个节点只负责一部分数据,这样就大大提升了系统的容量和性能。

本文主要包括以下几个部分:

一、总体介绍

二、环境搭建

三、测试

四、小结

总体介绍

前面提到,Redis Cluster对数据进行分片,然后水平分配到多个节点上,不同节点存储的数据是不一样的,所以它提升了系统的存储容量,同时,Redis Cluster还具备故障检测和自动恢复的机制,集群中的节点会相互检测健康状态。所以,这种集群模式不光支持大数据量、高并发,同时也支持高可用性。

Redis Cluster的整体架构如下:

5b07ce18a226ed9766863e182d81fa85.png

Redis没有使用一致性哈希,而是使用哈希槽(Hash Slot)的方式将数据分片。Redis Cluster一共有16384个槽位,每个key进行CRC16计算,计算结果对16384取余,然后决定分配到哪位槽位。

集群中的每个节点都负责处理一部分槽位,比如,集群中有三个节点,槽位的分配如下:

      • 节点A包含的槽位:0~5500

      • 节点A包含的槽位:5501~11000

      • 节点C包含的槽位:11001~16383

这样的话,在集群中增加或者删除节点就比较方便了,比如,我们想要增加一个节点D,只需要把A,B,C中的一部分槽位移动到节点D中即可;类似的,如果想要删除节点A,只需要把A中的槽位移动到节点B,C中即可,一旦迁移完成,就可以把节点A彻底地删除了。

key的槽位分配示意图如下:

2679fc5923d1979ae339070b36c2ec8d.png

环境搭建

接下来,我们在一台服务器上搭建Redis Cluster,通过不同的端口和不同的配置文件来区分各个服务。

几个关键的配置模板信息如下(不同的端口需要做相应的修改):

port 7000  # 端口号
cluster-enabled yes  # 开启集群模式
cluster-config-file nodes-7000.conf  # 集群状态信息,以端口号区分
cluster-node-timeout 5000  # 节点超时时限,单位为毫秒
dbfilename "dump-7000.rdb" # 以端口号区分

protected-mode no
logfile "logfile-7000.log"  # 日志文件,以端口号区分

requirepass 123456
masterauth 123456

pidfile "redis_7000.pid"  # 进程号文件,以端口号区分

然后创建测试目录,每个端口都有自己的配置文件:

mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005

把配置文件redis.conf复制到7000等各个以端口号命名的目录中,按照上面的模板信息做相应的修改(主要是配置端口,以及各个文件名通过端口号区分)。启动redis服务(详细可参考文章:吃透Redis系列:总体介绍):

./redis-server ./cluster-test/7000/redis.conf &
./redis-server ./cluster-test/7001/redis.conf &
./redis-server ./cluster-test/7002/redis.conf &
./redis-server ./cluster-test/7003/redis.conf &
./redis-server ./cluster-test/7004/redis.conf &
./redis-server ./cluster-test/7005/redis.conf &

查看日志,以端口7000为例,可以看到,每个节点都被赋予了一个ID(很萌的自我介绍):

No cluster configuration found, I'm 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580

接下来创建集群,执行下面的命令:

redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1 -a 123456

create命令用来创建一个集群,参数--cluster-replicas 1,表示为每个master创建一个副本。其它带有IP和端口的参数,就是想要加入集群的实例。另外,对于Redis Cluster,最少也需要三个主节点。

输入yes确认,控制会提示类似以下这样的信息,可以看到,6个实例被分成了三主三从,主和从的对应的关系也建立了,包括主节点分配的槽位等:

M: 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: a3a394d035d9e39246b76d8b336d4409e0c2ae40 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580
S: c6b663db98875fafb5b39f8c2258684dbae444fb 127.0.0.1:7005
   slots: (0 slots) slave
   replicates 7e5caaf9bfa4b049c11f52259dc4f93a7076b341
S: 1838d7e245204d25e272b57e9d257eaa0a5a835c 127.0.0.1:7003
   slots: (0 slots) slave
   replicates 7e043979136d32a5c81a39985928354ca01eb5d4
M: 7e5caaf9bfa4b049c11f52259dc4f93a7076b341 127.0.0.1:7001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 7e043979136d32a5c81a39985928354ca01eb5d4 127.0.0.1:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
   
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

测试

使用客户端命令行工具来进行一些简单的测试,首先连上集群,使用如下的命令,有两个参数要注意一下,一个是-c,它表示连接到集群,一个是-a,它后面跟的是redis密码:

redis-cli -h 127.0.0.1 -p 7000 -c -a 123456

然后输入一些set/get命令:

127.0.0.1:7000> set slogan good
-> Redirected to slot [16191] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get slogan
-> Redirected to slot [16191] located at 127.0.0.1:7002
"good"
127.0.0.1:7002> get hello
-> Redirected to slot [866] located at 127.0.0.1:7000
"world"

可以看到,它会计算出key对应哪个槽位,然后把客户端重定向到对应的Redis节点。有一个常用的命令,可以计算key对应的槽位,我们来确认下,对于key为hello和slogan,上面的计算是否正确:

127.0.0.1:7000> cluster keyslot hello
(integer) 866
127.0.0.1:7000> cluster keyslot slogan
(integer) 16191

我们测试一下如果Master不可用了,会发生什么事情。从环境搭建那一节当中,我们可以看到,端口7000、7001、7002对应的实例为主节点,它们对应的从节点端口分别为7004、7005、7003,也可以执行命令cluster nodes来找到这样的对应关系。

127.0.0.1:7002> cluster nodes
7e5caaf9bfa4b049c11f52259dc4f93a7076b341 127.0.0.1:7001@17001 master - 0 1714028017000 2 connected 5461-10922
a3a394d035d9e39246b76d8b336d4409e0c2ae40 127.0.0.1:7004@17004 slave 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 0 1714028016602 1 connected
3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 127.0.0.1:7000@17000 master - 0 1714028018227 1 connected 0-5460
1838d7e245204d25e272b57e9d257eaa0a5a835c 127.0.0.1:7003@17003 slave 7e043979136d32a5c81a39985928354ca01eb5d4 0 1714028018000 3 connected
7e043979136d32a5c81a39985928354ca01eb5d4 127.0.0.1:7002@17002 myself,master - 0 1714028016000 3 connected 10923-16383
c6b663db98875fafb5b39f8c2258684dbae444fb 127.0.0.1:7005@17005 slave 7e5caaf9bfa4b049c11f52259dc4f93a7076b341 0 1714028018734 2 connected

我们把端口7002对应的实例停掉,然后再执行命令cluster nodes,发现7002已经提示master,fail的状态了,而它之前对应的从节点7003,则被提升为master了。如果我们再次把7002启动,会发现它已经变成slave了,而对应的master就是7003,此处不再粘贴结果。

127.0.0.1:7000> cluster nodes
a3a394d035d9e39246b76d8b336d4409e0c2ae40 127.0.0.1:7004@17004 slave 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 0 1714029198765 1 connected
3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 127.0.0.1:7000@17000 myself,master - 0 1714029197000 1 connected 0-5460
c6b663db98875fafb5b39f8c2258684dbae444fb 127.0.0.1:7005@17005 slave 7e5caaf9bfa4b049c11f52259dc4f93a7076b341 0 1714029197237 2 connected
1838d7e245204d25e272b57e9d257eaa0a5a835c 127.0.0.1:7003@17003 master - 0 1714029197543 7 connected 10923-16383
7e5caaf9bfa4b049c11f52259dc4f93a7076b341 127.0.0.1:7001@17001 master - 0 1714029198261 2 connected 5461-10922
7e043979136d32a5c81a39985928354ca01eb5d4 127.0.0.1:7002@17002 master,fail - 1714029174564 1714029172000 3 disconnected

还有一个常用命令可以查看集群的详细情况,包括槽位的分配等:

[root@192 bin]# redis-cli --cluster check 127.0.0.1:7000 -a 123456
127.0.0.1:7000 (3a0523fd...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:7003 (1838d7e2...) -> 2 keys | 5461 slots | 1 slaves.
127.0.0.1:7001 (7e5caaf9...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 3 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: a3a394d035d9e39246b76d8b336d4409e0c2ae40 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 3a0523fd0ecd1f84acd60ee28c52b0f8920d5580
S: c6b663db98875fafb5b39f8c2258684dbae444fb 127.0.0.1:7005
   slots: (0 slots) slave
   replicates 7e5caaf9bfa4b049c11f52259dc4f93a7076b341
M: 1838d7e245204d25e272b57e9d257eaa0a5a835c 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 7e5caaf9bfa4b049c11f52259dc4f93a7076b341 127.0.0.1:7001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 7e043979136d32a5c81a39985928354ca01eb5d4 127.0.0.1:7002
   slots: (0 slots) slave
   replicates 1838d7e245204d25e272b57e9d257eaa0a5a835c
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

小结

可以看出,Redis Cluster还是很强大的,它具备很强的伸缩性、高可用性,通过数据分片的方式,大大提升了Redis的存储容量,以及横向扩展的能力。相比哨兵模式的自动故障转移,它显得更“高端”一些。

Redis的部署模式这么多,后续再写一篇文章对比这些模式之间的优缺点,以及它们各自的适用场景,敬请期待。

创作不易,烦请点个在看、点个赞。

有任何问题,也欢迎留言讨论。

鸣谢:

https://redis.io/docs/latest/operate/oss_and_stack/management/scaling/

推荐阅读:

吃透Redis系列:对过期数据挥刀问斩

吃透Redis系列:高可用的哨兵模式

吃透Redis系列:数据持久化

吃透Redis系列:琳琅满目的数据类型(下篇,文末彩蛋)

吃透Redis系列:琳琅满目的数据类型(上篇)

吃透Redis系列:总体介绍

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值