Redis集群实战搭建

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: redis3 到 redis5 开始支持集群,用的是 `ruby` 写的一个脚本,所以你需要先安装 ruby。然后根据官方提供了一个工具:redis-trib.rb(/redis-3.2.1/src/redis-trib.rb) 进行敲命令,一个个安装集群扩展。redis5以后的开发者们比较幸福了,redis直接支持了命令集群,在redis的 `redis-cli` 客户端直接配置集群

相关链接

redis集群演示服务分布图:https://www.kdocs.cn/view/l/sfN4qFXA2SyN

作者的docker-compose的redis集群:https://github.com/mailjobblog/dev_redis/tree/master/clusters/%E9%9B%86%E7%BE%A4

docker-compose 文件说明

该演示示例,使用 redis6.0.10 版本进行演示

文件中容器对应关系

容器名称 IP 客户端连接端口映射 集群端口映射 预想角色
redis-c1 172.31.0.11 6301->6379 16301->16379 master
redis-c2 172.31.0.12 6302->6379 16302->16379 master
redis-c3 172.31.0.13 6303->6379 16303->16379 master
redis-c4 172.31.0.14 6304->6379 16304->16379 slave
redis-c5 172.31.0.15 6305->6379 16305->16379 slave
redis-c6 172.31.0.16 6306->6379 16306->16379 slave
redis-c7 172.31.0.17 6307->6379 16307->16379 master (演示集群伸缩中使用)
redis-c8 172.31.0.18 6308->6379 16308->16379 slave (演示集群伸缩中使用)

初始服务分布如下

集群主要配置文件说明

# 端口
port 6379
# 是否开启集群
cluster-enabled yes
# 集群超时时间
cluster-node-timeout 5000
# 更新操作后进行日志记录
appendonly yes
# 集群配置文件
cluster-config-file "/redis/log/nodes.conf"
# 是否开启外部连接
protected-mode no
# redis守护进程
daemonize no
# 本地数据库存放目录
dir "/redis/data"
# redis日志文件
logfile "/redis/log/redis.log"
daemonize 设置yes或者no区别(默认:no)

daemonize:yes:redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
daemonize:no: 当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。

开始搭建集群

在宿主机 /data 上传 j_cluster

如果上传到了其他目录需要更改 yml 里面的数据卷映射条件

启动项目

# 进入到项目目录
cd /data/j_cluster

# 启动项目
docker-compose up -d

查看一下各个节点的ip

docker container inspect redis-c1 redis-c2 redis-c3 redis-c4 redis-c5 redis-c6 | grep IPv4Address

可以看到和我在 yam 中定义的ip一致

开始搭建集群

这里以进入 redis-c1 为例

docker exec -it redis-c1 /bin/bash

浏览一下redis的集群命令

以下命令只有 redis5 以后才有,redis5 以后redis发布了集群搭建命令
redis5 以前如果你要搭建的话,可以采用 Ruby 脚本

# 查看集群帮助文档
root@e4d19717bbed:/redis# 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                     #指定集群的任意一节点进行迁移slot,重新分slots
                 --cluster-from <arg>          #需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入
                 --cluster-to <arg>            #slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入
                 --cluster-slots <arg>         #需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
                 --cluster-yes                 #指定迁移时的确认输入
                 --cluster-timeout <arg>       #设置migrate命令的超时时间
                 --cluster-pipeline <arg>      #定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
                 --cluster-replace             #是否直接replace到目标节点
  rebalance      host:port                                      #指定集群的任意一节点进行平衡集群节点slot数量 
                 --cluster-weight <node1=w1...nodeN=wN>         #指定集群节点的权重
                 --cluster-use-empty-masters                    #设置可以让没有分配slot的主节点参与,默认不允许
                 --cluster-timeout <arg>                        #设置migrate命令的超时时间
                 --cluster-simulate                             #模拟rebalance操作,不会真正执行迁移操作
                 --cluster-pipeline <arg>                       #定义cluster getkeysinslot命令一次取出的key数量,默认值为10
                 --cluster-threshold <arg>                      #迁移的slot阈值超过threshold,执行rebalance操作
                 --cluster-replace                              #是否直接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                         #设置cluster-node-timeout
  import         host:port                                      #将外部redis数据导入集群
                 --cluster-from <arg>                           #将指定实例的数据导入到集群
                 --cluster-copy                                 #migrate时指定copy
                 --cluster-replace                              #migrate时指定replace
  help           

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

注意:Redis Cluster最低要求是3个主节点

创建集群主从节点

redis-cli --cluster create 172.31.0.11:6379  172.31.0.12:6379  172.31.0.13:6379 172.31.0.14:6379 172.31.0.15:6379 172.31.0.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.31.0.15:6379 to 172.31.0.11:6379
Adding replica 172.31.0.16:6379 to 172.31.0.12:6379
Adding replica 172.31.0.14:6379 to 172.31.0.13:6379
M: 50fa88c4a01f968df6ab7e8bd02e1bb51c85f13f 172.31.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 04a2118b3f7b7521a55cf77171f1c50fe1a80f4d 172.31.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: b83a282329830e2ea686889cb8aa9eafa3441b8f 172.31.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: 9b0a2284c341efa7055dd2046aec2e1c43ee6f9b 172.31.0.14:6379
   replicates b83a282329830e2ea686889cb8aa9eafa3441b8f
S: 09aca472595a229e7ceda2792aed98f88d757d45 172.31.0.15:6379
   replicates 50fa88c4a01f968df6ab7e8bd02e1bb51c85f13f
S: 2ce485e6a5bc5a3f300347c123ce911e605bf164 172.31.0.16:6379
   replicates 04a2118b3f7b7521a55cf77171f1c50fe1a80f4d
Can I set the above configuration? (type 'yes' to accept):

--cluster create : 表示创建集群
--cluster-replicas 0 : 表示只创建n个主节点,不创建从节点
--cluster-replicas 1 : 表示为集群中的每个主节点创建一个从节点(例:master[172.31.0.11:6379] -> slave[172.31.0.14:6379])

查看集群

# 查看节点主从关系
127.0.0.1:6379> cluster nodes
b83a282329830e2ea686889cb8aa9eafa3441b8f 172.31.0.13:6379@16379 master - 0 1612778025467 3 connected 10923-16383
04a2118b3f7b7521a55cf77171f1c50fe1a80f4d 172.31.0.12:6379@16379 master - 0 1612778025000 2 connected 5461-10922
50fa88c4a01f968df6ab7e8bd02e1bb51c85f13f 172.31.0.11:6379@16379 myself,master - 0 1612778024000 1 connected 0-5460
9b0a2284c341efa7055dd2046aec2e1c43ee6f9b 172.31.0.14:6379@16379 slave b83a282329830e2ea686889cb8aa9eafa3441b8f 0 1612778024565 3 connected
2ce485e6a5bc5a3f300347c123ce911e605bf164 172.31.0.16:6379@16379 slave 04a2118b3f7b7521a55cf77171f1c50fe1a80f4d 0 1612778024465 2 connected
09aca472595a229e7ceda2792aed98f88d757d45 172.31.0.15:6379@16379 slave 50fa88c4a01f968df6ab7e8bd02e1bb51c85f13f 0 1612778024000 1 connected

# 列出槽和节点信息
127.0.0.1:6379> cluster slots
1) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "172.31.0.13"
      2) (integer) 6379
      3) "b83a282329830e2ea686889cb8aa9eafa3441b8f"
   4) 1) "172.31.0.14"
      2) (integer) 6379
      3) "9b0a2284c341efa7055dd2046aec2e1c43ee6f9b"
2) 1) (integer) 5461
   2) (integer) 10922
   3) 1) "172.31.0.12"
      2) (integer) 6379
      3) "04a2118b3f7b7521a55cf77171f1c50fe1a80f4d"
   4) 1) "172.31.0.16"
      2) (integer) 6379
      3) "2ce485e6a5bc5a3f300347c123ce911e605bf164"
3) 1) (integer) 0
   2) (integer) 5460
   3) 1) "172.31.0.11"
      2) (integer) 6379
      3) "50fa88c4a01f968df6ab7e8bd02e1bb51c85f13f"
   4) 1) "172.31.0.15"
      2) (integer) 6379
      3) "09aca472595a229e7ceda2792aed98f88d757d45"

数据存储

# 直接存储提示槽信息不对
127.0.0.1:6379> set name libin
(error) MOVED 5798 172.31.0.12:6379

# 客户端连接加入 -c 数据可以直接被重定向到槽服务器
root@00bfb4f9402a:/redis# redis-cli -c
127.0.0.1:6379> set name libin
-> Redirected to slot [5798] located at 172.31.0.12:6379
OK

# 存储多个key的时候,由于不同的槽服务器,报错问题
172.31.0.12:6379> mset k1 v1 k2 v2
(error) CROSSSLOT Keys in request don't hash to the same slot

# 加入一个 tag 即可解决
172.31.0.12:6379> mset {
   
   r}k1 v1 {
   
   r}k2 v2
OK

集群伸缩

1、准备新的redis节点服务器
2、加入到集群中
3、分配数据槽和迁移数据

加入一个新的 master 节点

redis-cli -h 172.31.0.17 --cluster add-node 172.31.0.17:6379 172.31.0.11:6379
  • 这里的新加入的master节点是 172.31.0.17
  • 172.31.0.11 代表的事现在存在的集群中的任意一个 master 节点

为新加入的 master 节点添加一个 slave 节点

redis-cli -h 172.31.0.17 --cluster add-node 172.31.0.18:6379 172.31.0.17:6379 --cluster-slave
  • 172.31.0.17 代表上面行加入的 master 节点
  • 172.31.0.18 代表为 master(172.31.0.17)加入的从节点
  • --cluster-slave 代表是 slave(从节点)的身份

删除 slave 节点

redis-cli -h 172.31.0.18 --cluster del-node 172.31.0.18:6379 3a12f6b4ed5f26b83525681e73ee23750bcbcfbf
  • 3a12f6b4ed5f26b83525681e73ee23750bcbcfbf 是通过 cluster nodes 命令得到的节点ID
  • 如果上面有数据的话,无法删除,需要先迁移数据

为节点分配槽

# 指定分配
redis-cli -h 172.31.0.11 --cluster reshard 172.31.0.11:6379

# 平均分配
redis-cli -h 172.31.0.11 --cluster rebalance 172.31.0.11:6379
  • 172.31.0.11 这个只要是随便一个 master 节点都可以操作集群

分配槽演示

# 可以先看到节点信息

>>> Performing Cluster Check (using node 172.31.0.11:6379)
M: 9af405be84c1d448988117f88f78fa588d49a196 172.31.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 3a12f6b4ed5f26b83525681e73ee23750bcbcfbf 172.31.0.18:6379
   slots: (0 slots) slave
   replicates 34a33c9df9d909e69e5cad8965d905b72959c677
S: 7c35cf01519c5747ca262769ed47dbbe44eeb830 172.31.0.14:6379
   slots: (0 slots) slave
   replicates 780d17c7c9ca86f68b6119762f0958f00093702a
M: 780d17c7c9ca86f68b6119762f0958f00093702a 172.31.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 34a33c9df9d909e69e5cad8965d905b72959c677 172.31.0.17:6379
   slots: (0 slots) master
   1 additional replica(s)
S: a4956784b0221598c23d18fbcad844e18eefab63 172.31.0.15:6379
   slots: (0 slots) slave
   replicates 9af405be84c1d448988117f88f78fa588d49a196
M: ddf46bbdf6794d12debe824ce4e30ea96cd70212 172.31.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: a2820f32aa18e7ec2d880aedc8d91c9db840dcd9 172.31.0.16:6379
   slots: (0 slots) slave
   replicates ddf46bbdf6794d12debe824ce4e30ea96cd70212
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
  • 可以看到这里新加入的master 172.31.0.17 没有数据槽
# 询问要迁移的槽的数量(我在这里迁移了500个)
How many slots do you want to move (from 1 to 16384)? 500
# 询问被迁移的槽的ID(我这里迁移的是:172.31.0.11)
What is the receiving node ID? 34a33c9df9d909e69e5cad8965d905b72959c677
# 请输入所有源节点ID
Please enter all the source node IDs.
   # 键入“all”将所有节点用作哈希槽的源节点
  Type 'all' to use all the nodes as source nodes for the hash slots.
   # 输入所有源节点ID后键入“done”。
  Type 'done' once you entered all the source nodes IDs.
# 输入源的ID后,进行迁移
Source node #1: 9af405be84c1d448988117f88f78fa588d49a196
Source node #2: done
  • 用这个方法,也可以把某一个源的槽都迁移后。那么该槽就可以进行删除了

搭建问题

创建集群主从节点报错

[ERR] Node 172.31.0.11:6379 is not configured as a cluster node
查看配置文件的配置问题

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
存储 NoSQL 算法
09- Redis分片集群中数据是怎么存储和读取的 ?
Redis分片集群使用哈希槽分区算法,包含16384个槽(0-16383)。数据存储时,通过CRC16算法对key计算并模16383,确定槽位,进而分配至对应节点。读取时,根据槽位找到相应节点直接操作。
66 12
|
1月前
|
NoSQL Linux Redis
06- 你们使用Redis是单点还是集群 ? 哪种集群 ?
**Redis配置:** 使用哨兵集群,结构为1主2从,加上3个哨兵节点,总计分布在3台Linux服务器上,提供高可用性。
368 0
|
2天前
|
存储 NoSQL Redis
Redis数据结构精讲:选择与应用实战指南
Redis数据结构精讲:选择与应用实战指南
11 0
|
2天前
|
存储 监控 NoSQL
Redis哨兵&分片集群
Redis哨兵&分片集群
7 0
|
3天前
|
NoSQL 算法 Java
深入浅出Redis(八):Redis的集群模式
深入浅出Redis(八):Redis的集群模式
|
9天前
|
NoSQL Redis
透视Redis集群:心跳检测如何维护高可用性
Redis心跳检测保障集群可靠性,通过PING命令检测主从连接状态,预防数据丢失。当连接异常时,自动触发主从切换。此外,心跳检测辅助实现`min-slaves-to-write`和`min-slaves-max-lag`策略,避免不安全写操作。还有重传机制,确保命令无丢失,维持数据一致性。合理配置心跳检测,能有效防止数据问题,提升Redis集群的高可用性。关注“软件求生”获取更多Redis知识!
115 10
透视Redis集群:心跳检测如何维护高可用性
|
10天前
|
监控 NoSQL 算法
探秘Redis分布式锁:实战与注意事项
本文介绍了Redis分区容错中的分布式锁概念,包括利用Watch实现乐观锁和使用setnx防止库存超卖。乐观锁通过Watch命令监控键值变化,在事务中执行修改,若键值被改变则事务失败。Java代码示例展示了具体实现。setnx命令用于库存操作,确保无超卖,通过设置锁并检查库存来更新。文章还讨论了分布式锁存在的问题,如客户端阻塞、时钟漂移和单点故障,并提出了RedLock算法来提高可靠性。Redisson作为生产环境的分布式锁实现,提供了可重入锁、读写锁等高级功能。最后,文章对比了Redis、Zookeeper和etcd的分布式锁特性。
114 16
探秘Redis分布式锁:实战与注意事项
|
11天前
|
监控 NoSQL 算法
Redis集群模式:高可用性与性能的完美结合!
小米探讨Redis集群模式,通过一致性哈希分散负载,主从节点确保高可用性。节点间健康检测、主备切换、数据复制与同步、分区策略和Majority选举机制保证服务可靠性。适合高可用性及性能需求场景,哨兵模式则适用于简单需求。一起学习技术的乐趣!关注小米微信公众号“软件求生”获取更多内容。
46 11
Redis集群模式:高可用性与性能的完美结合!
|
12天前
|
监控 NoSQL Redis
|
12天前
|
消息中间件 监控 NoSQL
【亮剑】如何排查和解决Redis高负载问题
【4月更文挑战第30天】本文介绍了如何排查和解决Redis高负载问题。通过监控CPU、内存、网络IO和命令处理速度,可识别性能瓶颈。排查包括:分析慢查询、内存使用、网络连接和命令执行。优化措施涉及优化查询、减少复杂命令、使用连接池、调整数据结构等。建立监控系统、定期性能测试和持续优化是关键。