Redis5.0.10单机伪集群搭建
1、Redis集群概述
Redis cluster去除了中心化,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。Redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。
注意的是:必须要3个以后的主节点,否则在创建集群时会失败,我们在后续会实践到。
所以,我们假设现在有3个节点已经组成了集群,分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:
- 节点A覆盖0-5460
- 节点B覆盖5461-10922
- 节点C覆盖10923-16383
那么,现在我想设置一个key ,比如set k1 v1 ,按照Redis cluster的哈希槽算法:CRC16(‘k1’)%16384 = 2412。 那么就会把这个key 的存储分配到 A 上了。同样,当我连接(A,B,C)任何一个节点想获取k1这个key时,也会这样的算法,然后内部跳转到A节点上获取数据。这种哈希槽的分配方式有好也有坏,好处就是很清晰,比如我想新增一个节点D,Redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样:
- 节点A覆盖1365-5460
- 节点B覆盖6827-10922
- 节点C覆盖12288-16383
- 节点D覆盖0-1364,5461-6826,10923-12287
Redis Cluster主从模式
Redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。举个例子,集群有A、B、C三个主节点,各自从节点为A1、B1、C1,那么如果C主节点挂掉了,C1结点就会自动代替上,变成主节点。所以我们在集群建立的时候,一定要为每个主节点都添加了从节点,从而达到高可用性。如果C节点和C1节点同时挂掉了,那么这个集群也会挂掉。
2、搭建集群
1、安装Redis
这里我就不多说什么了,参考:Redis学习(一)----简介与安装
2、修改配置,创建节点
我们进入Redis的安装目录,先创建redis_cluster目录,然后再分别在redis_cluster下创建7001、7002、7003、7004、7005、7006这6个目录。
然后将redis解压目录下的redis.conf配置文件复制过来。
将六个节点的 redis.conf 配置文件进行修改 ,修改以下几个:
- port 7001:六个节点配置文件分别是7001-7006
- daemonize yes:redis后台运行
- pidfile /var/run/redis_7001.pid:pidfile文件对应7001-7006
- logfile "7001.log":日志文件
- cluster-enabled yes:开启集群
- cluster-config-file nodes_7001.conf:保存节点配置,自动创建,更新对应7001-7006
- cluster-node-timeout 5000:集群超时时间,节点超过这个时间没反应就断定是宕机
①、修改端口
②、让redis以守护进程的方式运行,将 daemonize 改成yes
③、修改pidfile文件
④、修改日志文件
⑤、 开启集群,打开注释cluster-enabled yes,这里必须打开,很重要。
⑥、 保存节点配置
⑦、设置集群超时时间
分别将7001-7006配置一遍。
3、编写Redis集群启动脚本
编写集群的启动和停止shell脚本,这样方便:
vi start.sh 加入下面内容:
01 02 03 04 05 06 | /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7001 /redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7002 /redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7003 /redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7004 /redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7005 /redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/ 7006 /redis.conf |
vi stop.sh 加入下面内容:
01 02 03 04 05 06 | /usr/local/redis/bin/redis-cli -p 7001 shutdown /usr/local/redis/bin/redis-cli -p 7002 shutdown /usr/local/redis/bin/redis-cli -p 7003 shutdown /usr/local/redis/bin/redis-cli -p 7004 shutdown /usr/local/redis/bin/redis-cli -p 7005 shutdown /usr/local/redis/bin/redis-cli -p 7006 shutdown |
修改权限:
01 | chmod 755 start.sh stop.sh |
然后启动所有节点
4、启动集群
注意:在启动集群的时候redis数据库必须是空的,否则会报错提示:[ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0。
解决方法:删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb。
在Redis3.0的版本启动集群使用的命令是:redis-trib.rb create --replicas 1 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 127.0.0.1:7006 ,Redis官方提供了redis-trib.rb工具,但是在使用之前需要安装ruby,以及redis和ruby连接工具。
但是Redis5.0集群管理工具redis-trib.rb已经被废弃,所以不用安装ruby啥的了,现在已经集成到了redis-cli中,并且可以在有认证的情况执行了,可以通过redis-cli --cluster help查看使用方式。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | [root @localhost redis_cluster]# cd /usr/local/redis/bin/ [root @localhost bin]# ./redis-cli --cluster help Cluster Manager Commands: create host1:port1 ... hostN:portN --cluster-replicas <arg> check host:port --cluster-search-multiple-owners info host:port fix host:port --cluster-search-multiple-owners reshard host:port --cluster-from <arg> --cluster-to <arg> --cluster-slots <arg> --cluster-yes --cluster-timeout <arg> --cluster-pipeline <arg> --cluster-replace rebalance host:port --cluster-weight <node1=w1...nodeN=wN> --cluster-use-empty-masters --cluster-timeout <arg> --cluster-simulate --cluster-pipeline <arg> --cluster-threshold <arg> --cluster-replace add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id <arg> del-node host:port node_id call host:port command arg arg .. arg set-timeout host:port milliseconds import host:port --cluster-from <arg> --cluster-copy --cluster-replace help For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. [root @localhost bin]# |
启动集群,直接一个命令就OK:
01 | ./redis-cli --cluster create 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 127.0 . 0.1 : 7006 --cluster-replicas 1 |
从上面的运行结果看,默认给的 主节点就是7001 7002 7003 ,从节点分别是7004 7005 7006 (三主三从)
- 7001分配到的哈希槽是 0-5460
- 7002分配到的哈希槽是 5461-10922
- 7003分配到的哈希槽是 10923-16383
这样16384个卡槽全部分配完毕,集群创建成功,可以使用了。
5、添加主从节点到集群中
我们新建两个目录7007、7008用于给集群添加一个主从节点:
同样的方法修改7007、7008的 redis.conf 配置文件。然后启动它们:
启动成功。
①、添加Master主节点
注意:在启动集群的时候redis数据库必须是空的,否则会报错提示:[ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0。
解决方法:删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb。
01 | ./redis-cli --cluster add-node 127.0 . 0.1 : 7007 127.0 . 0.1 : 7001 |
然后查看redis集群信息:
01 | ./redis-cli --cluster check 127.0 . 0.1 : 7001 |
可以看到 7007端口作为master 主节点加入到redis集群中 ,但 7007 没有slots卡槽
使用下面命令为7007端口增加卡槽:
01 | ./redis-cli --cluster reshard 127.0 . 0.1 : 7007 |
然后查看分配卡槽的信息:
分配成功!
②、添加Slave节点
我们给Master主节点7007添加一个从节点7008:
01 02 03 04 05 06 07 | # 127.0 . 0.1 : 7008 节点的ip和端口 # 127.0 . 0.1 : 7001 已存在集群中的一个节点ip和端口 # add-node 添加一个节点 # --cluster-slave 从节点 # --cluster-master-id 该从节点的master节点id ./redis-cli --cluster add-node 127.0 . 0.1 : 7008 127.0 . 0.1 : 7001 --cluster-slave --cluster-master-id e3ed175cd38c9ea5b7a0827f2be7b8bfa9385ba2 |
然后查看集群的信息:
01 | ./redis-cli --cluster check 127.0 . 0.1 : 7001 |
可以发现7008端口已经成为了7007端口的从节点。
③、删除 slave从节点
01 | ./redis-cli --cluster del-node 127.0 . 0.1 : 7008 609e99ae01ce067323f8c44207f512b5cd3546e2 |
成功删除7008从节点。
④、删除Master主节点
要删除master节点,首先要将它的 slot卡槽全部提取到别的master节点上:
01 | ./redis-cli --cluster reshard 127.0 . 0.1 : 7001 |
查看一下集群信息:
此时7007节点上的slot卡槽已经是0个了:
如果想卡槽分配均匀,可以使用如下命令:
01 | ./redis-cli --cluster rebalance --cluster-threshold 1 127.0 . 0.1 : 7001 |
删除 7007 master节点
01 02 03 | ./redis-cli --cluster del-node 127.0 . 0.1 : 7007 73f19b384906113507b25f256a781ce184777162 ./redis-cli --cluster check 127.0 . 0.1 : 7001 |
删除成功。
6、集群数据测试
我们先连接Redis任意一个节点端口:
01 | ./redis-cli -c -p 7001 # -c 表示集群 -p是端口 |
这就是Redis Cluster值分配规则,所以分配key的时候,它会使用CRC16(‘k1’)%16384算法,来计算,将这个key 放到哪个节点,这里分配到了12706 slot 就分配到了7003这个节点上。
我们在其他的节点上也能获取到这个值。
7、集群宕机测试
我们来挂掉一个节点测试一下,如果将7001节点kill掉:
我们再来查看一下集群的信息(./redis-cli --cluster check 127.0.0.1:7002):
可以发现集群并没有挂掉,这是因为7006本来是7001的从节点,结果发现7001节点挂了,然后7006节点顶上去,变成了Master主节点。
那么我们把7006也给它干死,会怎么样呢?
再次查看集群节点信息;
这里发现出现了错误,说有一些 哈希槽没得分配,也说明了Redis集群必须要三个结点才能创建成功!
[ERR] Not all 16384 slots are covered by nodes. 没有安全覆盖;所以不能正常使用集群了;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构