千家信息网

学习Redis Cluster并手动搭建集群

发表于:2024-11-13 作者:千家信息网编辑
千家信息网最后更新 2024年11月13日,Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(key)&16383。槽是集群内数据管理和迁移的基本单位。采用大范围槽的主要
千家信息网最后更新 2024年11月13日学习Redis Cluster并手动搭建集群

Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(key)&16383。槽是集群内数据管理和迁移的基本单位。采用大范围槽的主要目的是为了方便数据拆分和集群扩展。每个节点会负责一定数据的槽,如下图所示:

当集群有5个节点,每个节点平均大约负载3276个槽。由于采用高质量的哈希算法,每个槽所映射的数据通常比较均匀,将数据平均划分到5个节点进行数据分区。每一个节点负责维护一部分槽以及槽所映射的键值数据,如下图所示:

Redis虚拟槽分区的特点:

解耦数据和节点之间的关系,简化了节点扩容和收缩难度。

节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据。

支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景。

数据分区是分布式存储的核心,理解和灵活运用数据分区规则对于掌握Redis Cluster非常有帮助。

集群功能限制

Redis集群相对单机的功能上存在一些限制,需要开发人页提前了解,在使用时做好规避。限制如下:

1)key批量操作支持有限。如mset、mget,目前只支持具有相同slot值的key执行批量操作。对于映射为不同slot值的key由于执行mget、mset等操作可能存在于多个节点上因此不被支持。

2)key事务操作支持有限。同理只支持多key在同一节点上的事务操作,当多个key分布在不同的节点上时无法使用事务功能。

3)key作为数据分区的最小粒度,因此不能将一个大的键值对象如hash、list等映射到不同的节点。

4)不支持多数据库空间。单机下的Redis可以支持16个数据库,集群模式下只能使用一个数据库空间,即db0。

5)复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。

搭建集群

下面开始搭建集群工作,需要以下三个步骤:

1)准备节点

2)节点握手

3)分配槽

准备节点

节点规划,使用三台机器,第台机器上部署两个Redis实例,分别为一主一从。

redis_1 192.168.56.120redis_2 192.168.56.121redis_3 192.168.56.122

Redis集群一般由多个节点组成,节点数据至少为6个才能保证组成完整高可用的集群。每个节点需要开启配置cluster-enabled yes,让Redis运行在集群模式下。建议为集群内所有节点统一目录,一般划分三个目录:conf、data、log,分别存放配置、数据和日志相关文件。把6个节点配置统一放在conf目录下,集群相关配置如下:

#节点端口port 6379#开启集群模式cluster-enabled yes#节点超时时间,单位毫秒cluster-node-timeout 15000#集群内部配置文件cluster-config-file "nodes-6379.conf"

其他配置和单机模式一致即可,配置文件命名规则redis-{port}.conf,准备好配置后启动所有节点,命令如下:

#redis_1redis-server conf/redis-6379.conf &redis-server conf/redis-6380.conf &#redis_2redis-server conf/redis-6379.conf &redis-server conf/redis-6380.conf &#redis_3redis-server conf/redis-6379.conf &redis-server conf/redis-6380.conf &

检查节点是日志是否正确,内容如下

5200:M 05 Apr 11:28:18.931 * No cluster configuration found, I'm 383261e3f0053f74c953bd07ceee36a4b5795bc3......                                             Redis 4.0.13 (00000000/0) 64 bitRunning in cluster modePort: 6380PID: 5200.......5200:M 05 Apr 11:28:18.943 * Ready to accept connections

redis_1上的6379节点启动成功,第一次启动时如果没有集群配置文件,它会自动创建一份,文件名称采用cluster-config-file参数项控制,建议采用node-{port}.conf格式定义,通过使用端口号区分不同节点,防止同一机器下多个节点彼此覆盖,造成集群信息异常。如果启动时存在集群配置文件,节点会使用配置文件内容初始化集群信息,启动过程如下图:

集群模式的Redis除了原有的配置文件之外又加了一份集群配置文件。当集群节点信息发生变化,如添加节点、节点下线、故障转移等。节点会自动保存集群状态到配置文件中。需要注意的是,Redis自动维护集群配置文件,不要手动修改,防止节点重启时产生集群信息错乱。

如redis_3的6379实例首次启动后生成集群配置如下:

[redis@redis_3 ~]$ cat data/nodes-6379.conf

275753d11365feabb366170b940bca4b8486bbd7 :0@0 myself,master - 0 0 0 connected

vars currentEpoch 0 lastVoteEpoch 0

文件内容记录了集群初始状态,这里最重要的是节点ID,它是一个40位16进制字符串,用于标准集群内一个节点,之后很多集群操作都要借助于节点ID来完成。需要注意的是,节点IDeas不同于运行IDeas。节点IDeas在集群初始化时只创建一次,节点重启时会加载集群配置文件进行重用,而Redis的运行IDeas每次重启都 会变化。在redis_3的6379节点上执行cluster nodes命令获取集群节点状态:

127.0.0.1:6380> cluster nodes

d54639285709a65bb8ca331f26d4fe1b1c8c73ca :6380@16380 myself,master - 0 0 0 connected

每个节点目前只能识别出自己的节点信息。我们启动6个节点,但每个节点彼此不知道对方的存在,下面通过节点握手让6个节点彼此建议联系从而组成一个集群。

节点握手

节点握手是批一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程。节点握手是集群彼此通信的第一步,由客户端发起命令:cluster meet {ip} {port},如下图所示

图中执行的命令是:cluster meet 127.0.0.1 6380让节点6379和6380进行握手通信。cluster meet命令是一个异步命令,执行之后立刻返回。内部发起与目标节点进行握手通信,如图所示

1)节点6379本地创建6380节点信息对象,并发送meet消息。

2)节点6380接受到meet消息后,保存6379节点信息并回复pong消息。

3)之后节点6379和6380彼此定期通过ping/pong消息进行正常的节点通信。

这里的meet、ping、pong消息是Gossip协议通信的载体,之后的节点通信部分做进一步介绍,它的主要作用是节点彼此交换状态数据信息。6379和6380节点通过meet命令彼此建议通信之后集群结构如图:

执行完cluster meet后,可以通过cluster nodes看到两个实例都检查到了对方的存在

[redis@redis_1 ~]$ redis-cli -h redis_1 -p 6379redis_1:6379> cluster meet 192.168.56.120 6380OKredis_1:6379> cluster nodes383261e3f0053f74c953bd07ceee36a4b5795bc3 192.168.56.120:6380@16380 master - 0 1554440139158 1 connectedceaf2ccb751978b7334ddeca474da3d6b7aac99b 192.168.56.120:6379@16379 myself,master - 0 0 0 connectedredis_1:6379> exit[redis@redis_1 ~]$ redis-cli -h redis_1 -p 6380redis_1:6380> cluster nodesceaf2ccb751978b7334ddeca474da3d6b7aac99b 192.168.56.120:6379@16379 master - 0 1554440152934 0 connected383261e3f0053f74c953bd07ceee36a4b5795bc3 192.168.56.120:6380@16380 myself,master - 0 0 1 connectedredis_1:6380>

使用如下命令把其他节点加入集群,只需要在集群内任意节点执行cluster meet命令加入新节点,握手状态会通过消息在集群内传播,这样其他节点会自动发现新节点并发起握手流程。最后执行cluster nodes命令确认6个节点都彼此感知并组成了集群:

[redis@redis_1 ~]$ redis-cli -h redis_1 -p 6379redis_1:6379> cluster meet 192.168.56.121 6379OKredis_1:6379> cluster meet 192.168.56.121 6380OKredis_1:6379> cluster meet 192.168.56.122 6379OKredis_1:6379> cluster meet 192.168.56.122 6380OKredis_1:6379> cluster nodes275753d11365feabb366170b940bca4b8486bbd7 192.168.56.122:6379@16379 master - 0 1554440316783 4 connected383261e3f0053f74c953bd07ceee36a4b5795bc3 192.168.56.120:6380@16380 master - 0 1554440316000 1 connectedceaf2ccb751978b7334ddeca474da3d6b7aac99b 192.168.56.120:6379@16379 myself,master - 0 1554440315000 5 connectedd54639285709a65bb8ca331f26d4fe1b1c8c73ca 192.168.56.122:6380@16380 master - 0 1554440316000 0 connectedca4f05809dc9a9eda4292a33b994b4e2aab13033 192.168.56.121:6380@16380 master - 0 1554440317000 3 connecteda85bbb17a3f559d18d7f5059f14ffd9f6ba48ee1 192.168.56.121:6379@16379 master - 0 1554440315000 2 connected

握手完成后集群的状态如下图:

节点建议握手之后集群还不能正常工作,这里集群处理下线状态,所有的数据读写都被禁止。通过如下命令可以看到:

redis_2:6379> set hello world(error) CLUSTERDOWN Hash slot not served

通过cluster info 命令可以获取集群当前状态:

redis_2:6379> cluster infocluster_state:failcluster_slots_assigned:0cluster_slots_ok:0cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:6cluster_size:0cluster_current_epoch:5cluster_my_epoch:2cluster_stats_messages_ping_sent:315cluster_stats_messages_pong_sent:314cluster_stats_messages_meet_sent:3cluster_stats_messages_sent:632cluster_stats_messages_ping_received:312cluster_stats_messages_pong_received:318cluster_stats_messages_meet_received:2cluster_stats_messages_received:632

从输出内容可以看到,被分配的槽(cluster_slots_assigned)是0,由于目前所有的槽没有分配节点,因此集群无法完成槽到节点的映射。只有当16384个槽全部分配给节点后,集群才进入在线状态。

分配槽

Redis集群把所有的数据映射到16384个槽中。每个key会映射为一个固定的槽,只有当节点分配了槽,才响应和这些槽相关联的键命令。通过cluster addslots命令为节点分配槽。这些利用bash特性批量设置槽(slots),命令如下:

[redis@redis_1 ~]$ redis-cli -h redis_1 -p 6379 cluster addslots {0..5461}OK[redis@redis_1 ~]$ redis-cli -h redis_2 -p 6379 cluster addslots {5462..10922}OK[redis@redis_1 ~]$ redis-cli -h redis_3 -p 6379 cluster addslots {10923..16383}OK

把16384个slot平均分配给redis_1/2/3的6379三个节点。执行cluster info查看集群状态如下所示:

[redis@redis_1 ~]$ redis-cli -h redis_2 -p 6379 cluster infocluster_state:okcluster_slots_assigned:16384cluster_slots_ok:16384cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:6cluster_size:3cluster_current_epoch:5cluster_my_epoch:2cluster_stats_messages_ping_sent:1062cluster_stats_messages_pong_sent:1067cluster_stats_messages_meet_sent:3cluster_stats_messages_sent:2132cluster_stats_messages_ping_received:1065cluster_stats_messages_pong_received:1065cluster_stats_messages_meet_received:2cluster_stats_messages_received:2132

当前集群状态是OK,集群进入在线状态。所有的槽都已经分配给节点,执行cluster nodes命令可以看到节点和槽的分配关系:

[redis@redis_1 ~]$ redis-cli -h redis_2 -p 6379 cluster nodesa85bbb17a3f559d18d7f5059f14ffd9f6ba48ee1 192.168.56.121:6379@16379 myself,master - 0 1554441448000 2 connected 5462-10922ceaf2ccb751978b7334ddeca474da3d6b7aac99b 192.168.56.120:6379@16379 master - 0 1554441448455 5 connected 0-5461ca4f05809dc9a9eda4292a33b994b4e2aab13033 192.168.56.121:6380@16380 master - 0 1554441449000 3 connected383261e3f0053f74c953bd07ceee36a4b5795bc3 192.168.56.120:6380@16380 master - 0 1554441450000 1 connectedd54639285709a65bb8ca331f26d4fe1b1c8c73ca 192.168.56.122:6380@16380 master - 0 1554441450491 0 connected275753d11365feabb366170b940bca4b8486bbd7 192.168.56.122:6379@16379 master - 0 1554441449470 4 connected 10923-16383

目前还有三个节点没有使用,作为一个完整的集群,每个负责处理槽的节点应该具有从节点,保证当它出现故障时可以自动进行故障转移。集群模式下,Redis节点角色分为主节点和从节点。首次启动的节点和被分配槽的节点都是主节点,从节点负责复制主节点槽信息和相关的数据。使用cluster replicate {nodeID}命令让一个节点成为从节点。其中命令执行必须在对应的从节点上执行,nodeID是要复制主节点的节点ID,命令如下:

[redis@redis_1 ~]$ redis-cli -h redis_1 -p 6380 cluster replicate a85bbb17a3f559d18d7f5059f14ffd9f6ba48ee1OK[redis@redis_1 ~]$ redis-cli -h redis_2 -p 6380 cluster replicate 275753d11365feabb366170b940bca4b8486bbd7OK[redis@redis_1 ~]$ redis-cli -h redis_3 -p 6380 cluster replicate ceaf2ccb751978b7334ddeca474da3d6b7aac99bOK

复制(replication)完成后,整个集群的结构如图

到此为止,我们依照Redis协议手动建立一个集群。它由6个节点构成,3个主节点负责处理槽和相关数据,3个从节点负责故障转移。


博文内容主要参考《Redis开发与运维》一书。

节点 集群 数据 命令 配置 文件 状态 分配 支持 信息 通信 模式 消息 内容 建议 不同 三个 多个 故障 结构 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 初中网络安全知识主题班会课 不动产数据库整合技术规范 内蒙古专业软件开发有哪些 软件开发年薪几千亿 创维电视无法解析服务器 致信服务器配置获取数据失败 税友软件开发面试 怀旧服魔兽服务器人数查询 网络安全研究方向论文 域名解析服务器教程 绝地求生2服务器错误怎么办 最早的服务器我的世界 新致软件开发面试 域名服务器 美国 网络安全 北京橡树网络技术有限公司 软件具有数据库的安全性 swith哪个服务器最便宜 啤酒节主题软件开发 数据库表fid是什么意思 网易土豆服务器有什么用 金华软件开发公司哪个好 我的世界最混乱的服务器谁拯救了 数据库维护要求 数据库管理系统设计报告 vue 应用服务器对公网开放 法律法规数据库查询官网 长沙千橙网络技术有限公司 软件开发项目思路 数据库查询空间方位查询语句 数据库下划线前端页面的处理
0