Redis搭建集群

功能概述

Redis Cluster是Redis的自带的官方分布式解决方案,提供数据分片、高可用功能,在3.0版本正式推出。

使用Redis Cluster能解决负载均衡的问题,内部采用哈希分片规则:

基础架构图如下所示:

image-20210401200112675

图中最大的虚线部分为一个Cluster集群,由6个Redis实例组成。

集群分片

整个Cluster集群中有16384个槽位,必须要将这些槽位分别规划在3台Master中。

如果有任意1个槽位没有被分配,则集群创建不成功。

当集群中任意一个Master尝试进行写入操作后,会通过Hash算法计算出该条数据应该落在哪一个Master节点上。

如下图所示:

image-20210401203018467

情况1:如果你未指定任何参数就进行写入,如在Master1上写入数据,经过内部计算发现该数据应该在Master2上写入时,会提示你应该进入Master2写入该条数据,执行并不会成功

情况2:如果你指定了一个特定参数进行写入,如在Master1上写入数据,经过内部计算发现该数据应该在Master2上写入时,会自动将写入环境重定向至Master2,执行成功

同理,读取数据也是这样,这个过程叫做MOVED重定向,如果你是情况1进行操作则必须手动进行重定向,情况2则会自动进行重定向。

集群通信

集群中各个节点的信息是互通的,这种现象由Gossip(流言)协议产生。

Gossip协议规定每个集群节点之间互相交换信息,使其能够彼此知道对方的状态。

在通信建立时,集群中的每一个节点都会单独的开辟一个TCP通道,用于与其他节点进行通信,这个通信端口会在基础端口上+10000。

通信建立成功后,每个节点在固定周期内通过特定规则选择节点来发送ping消息(心跳机制)。

当收到ping消息的节点则会使用pong消息作为回应,也就是说,当有一个新节点加入后,一瞬间集群中所有的其他节点也能够获取到该信息。

Gossip协议的主要职责就是进行集群中节点的信息交换,常见的Gossip协议消息有以下几点区分:

  • meet:用于通知新节点加入,消息发送者通知接受者加入到当前集群
  • ping:集群内每个节点与其他节点进行心跳检测的命令,用于检测其他节点是否在线,除此之外还能交换其他额外信息
  • pong:用于回复meet以及ping信息,表示已收到,能够正常通行。此外还能进行群发更新节点状态
  • fail:当其他节点收到fail消息后立马把对应节点更新为下线状态,此时集群开始进行故障转移

image-20210401204007415

初步搭建

地址规划

3台服务器,每台服务器开启2台实例构建基础主从。

服务器采用centos7.3,Redis版本为6.2.1

地址规划与结构图如下:

image-20210401213843708

在每个节点hosts文件中加入以下内容;

$ vim /etc/hosts

192.168.0.120 node1
192.168.0.130 node2
192.168.0.140 node3

集群准备

为所有节点下载Redis:

$ cd ~
$ wget https://download.redis.io/releases/redis-6.2.1.tar.gz

为所有节点配置目录:

$ mkdir -p /usr/local/redis_cluster/redis_63{79,80}/{conf,pid,logs}

所有节点进行解压:

$ tar -zxvf redis-6.2.1.tar.gz -C /usr/local/redis_cluster/

所有节点进行编译安装Redis:

$ cd /usr/local/redis_cluster/redis-6.2.1/
$ make && make install 

书写集群配置文件,注意!Redis普通服务会有2套配置文件,一套为普通服务配置文件,一套为集群服务配置文件,我们这里是做的集群,所以书写的集群配置文件,共6份:

$ vim /usr/local/redis_cluster/redis_6379/conf/redis.cnf

# 快速修改::%s/6379/6380/g

# 守护进行模式启动
daemonize yes

# 设置数据库数量,默认数据库为0
databases 16

# 绑定地址,需要修改
bind 192.168.0.120

# 绑定端口,需要修改
port 6379

# pid文件存储位置,文件名需要修改
pidfile /usr/local/redis_cluster/redis_6379/pid/redis_6379.pid

# log文件存储位置,文件名需要修改
logfile /usr/local/redis_cluster/redis_6379/logs/redis_6379.log

# RDB快照备份文件名,文件名需要修改
dbfilename redis_6379.rdb

# 本地数据库存储目录,需要修改
dir /usr/local/redis_cluster/redis_6379

# 集群相关配置
# 是否以集群模式启动
cluster-enabled yes

# 集群节点回应最长时间,超过该时间被认为下线
cluster-node-timeout 15000

# 生成的集群节点配置文件名,文件名需要修改
cluster-config-file nodes_6379.conf

# redis密码
masterauth Esb@123
requirepass Esb@123

启动集群

启动集群

在启动集群时,会按照Redis服务配置文件的配置项判断是否启动集群模式,如图所示:

image-20210401221228929

每个节点上执行以下2条命令进行服务启动:

$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf
$ redis-server /usr/local/redis_cluster/redis_6380/conf/redis.cnf


集群模式启动,进程后会加上[cluster]的字样:

$ ps -ef | grep redis
root      51311      1  0 11:30 ?        00:00:00 redis-server 192.168.0.120:6379 [cluster]
root      51329      1  0 11:30 ?        00:00:00 redis-server 192.168.0.120:6380 [cluster]
root      51396 115516  0 11:31 pts/1    00:00:00 grep --color=auto redis

同时,查看一下集群节点配置文件,会发现生成了一组集群信息,每个Redis服务都是不同的:

$ cat /usr/local/redis_cluster/redis_6379/nodes_6379.conf
c8a8c7d52e6e7403e799c75302b6411e2027621b :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

$ cat /usr/local/redis_cluster/redis_6380/nodes_6380.conf
baa10306639fcaca833db0d521235bc9593dbeca :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

# 第一段信息是这个Redis服务作为集群节点的一个身份编码
# 别名为集群的node-id

加入集群

现在虽然说每个服务都成功启动了,但是彼此之间并没有任何联系。

所以下一步要做的就是将6个服务加入至一个集群中,如下操作示例:

$ redis-cli -h node1 -p 6379 -a Esb@123

node1:6379> cluster meet 192.168.0.130 6379
node1:6379> cluster meet 192.168.0.140 6379
node1:6379> cluster meet 192.168.0.120 6380
node1:6379> cluster meet 192.168.0.130 6380
node1:6379> cluster meet 192.168.0.140 6380

查看当前集群所有的节点:

node1:6379> cluster nodes

214dc5a10149091047df1c61fd3415d91d6204ea 192.168.0.130:6379@16379 master - 0 1617291123000 1 connected
baa10306639fcaca833db0d521235bc9593dbeca 192.168.0.120:6380@16380 master - 0 1617291120000 3 connected
7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 192.168.0.140:6379@16379 master - 0 1617291123000 2 connected
bae708f7b8df32edf4571c72bbf87715eb45c169 192.168.0.130:6380@16380 master - 0 1617291124175 4 connected
fd1dde2a641727e52b4e82cfb351fe3c17690a17 192.168.0.140:6380@16380 master - 0 1617291124000 0 connected
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 myself,master - 0 1617291121000 5 connected

查看端口监听,可以发现Gossip监听的1000+端口出现了,此时代表集群各个节点之间已经能互相通信了:

$ netstat -lnpt | grep redis
tcp        0      0 192.168.0.120:6379      0.0.0.0:*               LISTEN      51311/redis-server
tcp        0      0 192.168.0.120:6380      0.0.0.0:*               LISTEN      51329/redis-server
tcp        0      0 192.168.0.120:16379     0.0.0.0:*               LISTEN      51311/redis-server
tcp        0      0 192.168.0.120:16380     0.0.0.0:*               LISTEN      51329/redis-server

主从配置

6个服务之间并没有任何主从关系,所以现在进行主从配置,记录下上面cluster nodes命令输出的node-id信息,只记录主节点:

hostname节点node-id
node1192.168.0.120:6379c8a8c7d52e6e7403e799c75302b6411e2027621b
node2192.168.0.130:6379214dc5a10149091047df1c61fd3415d91d6204ea
node3192.168.0.140:63797a151f97ee9b020a3c954bbf78cd7ed8a674aa70

首先是node1的6380,将它映射到node2的6379:

$ redis-cli -h node1 -p 6380
node1:6380> cluster replicate 214dc5a10149091047df1c61fd3415d91d6204ea

然后是node2的6380,将它映射到node3的6379:

$ redis-cli -h node2 -p 6380  -a Esb@123
node2:6380> cluster replicate 7a151f97ee9b020a3c954bbf78cd7ed8a674aa70

最后是node3的6380,将它映射到node1的6379:

$ redis-cli -h node3 -p 6380  -a Esb@123
node3:6380> cluster replicate c8a8c7d52e6e7403e799c75302b6411e2027621b

查看集群节点信息,内容有精简:

$ redis-cli -h node1 -p 6379  -a Esb@123
 
node1:6379> cluster nodes
192.168.0.130:6379@16379 master 
192.168.0.120:6380@16380 slave 
192.168.0.140:6379@16379 master 
192.168.0.130:6380@16380 slave
192.168.0.140:6380@16380 slave
192.168.0.120:6379@16379 myself,master 

# myself表示当前登录的是那个服务

分配槽位

接下来我们要开始分配槽位了,为了考虑今后的写入操作能分配均匀,槽位也要进行均匀分配。

仅在Master上进行分配,从库不进行分配,仅做主库的备份和读库使用。

使用python计算每个master节点分多少槽位:

$ python3

>>> divmod(16384,3)
(5461, 1)

槽位分配情况如下,槽位号从0开始,到16383结束,共16384个槽位:

节点槽位数量
node1:63790 - 5461
node2:63795461 - 10922
node3:637910922 - 16383

开始分配:

$ redis-cli -h node1 -p 6379  -a Esb@123 cluster addslots {0..5461}
$ redis-cli -h node2 -p 6379  -a Esb@123cluster addslots {5462..10922}
$ redis-cli -h node3 -p 6379 -a Esb@123 cluster addslots {10923..16383}

检查槽位是否分配正确,这里进行内容截取:

$ redis-cli -h node1 -p 6379  -a Esb@123

node1:6379> CLUSTER nodes
192.168.0.130:6379@16379 master - 0 1617292240544 1 connected 5462-10922
192.168.0.140:6379@16379 master - 0 1617292239000 2 connected 10923-16383
192.168.0.120:6379@16379 myself,master - 0 1617292238000 5 connected 0-5461

# 看master节点的最后

检查状态

使用以下命令检查集群状态是否ok,如果槽位全部分配完毕应该是ok,不然的话就检查你分配槽位时是否输错了数量:

$ redis-cli -h node1 -p 6379  -a Esb@123

node1:6379> CLUSTER info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:5
cluster_stats_messages_ping_sent:2825
cluster_stats_messages_pong_sent:2793
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:5623
cluster_stats_messages_ping_received:2793
cluster_stats_messages_pong_received:2830
cluster_stats_messages_received:5623

MOVED重定向

现在我们在node1的master节点上进行写入:

$ redis-cli -h node1 -p 6379  -a Esb@123

node1:6379> set k1 "v1"
(error) MOVED 12706 192.168.0.140:6379

它会提示你去node2的master上进行写入。

这个就是MOVED重定向。

-c参数

如何解决这个问题?其实在登录的时候加上参数-c即可,-c参数无所谓你的Redis是否是集群模式,建议任何登录操作都加上,这样即使是Redis集群也会自动进行MOVED重定向:

$ redis-cli -c -h node1 -p 6379  -a Esb@123

node1:6379> set k1 "v1"
-> Redirected to slot [12706] located at 192.168.0.140:6379
OK	

一并对主从进行验证,这条数据是写入至了node3的Master中,我们登录node2的Slave中进行查看:

$ redis-cli -h node2 -p 6380  -a Esb@123 -c

node2:6380> keys *
1) "k1"

故障转移

故障模拟

模拟node1的6379下线宕机,此时应该由node3的6380接管它的工作:

$ redis-cli -h node1 -p 6379  -a Esb@123 shutdown

登录集群任意节点查看目前的集群节点信息:

node2:6379> cluster nodes

214dc5a10149091047df1c61fd3415d91d6204ea 192.168.0.130:6379@16379 myself,master - 0 1617294532000 1 connected 5462-10922
bae708f7b8df32edf4571c72bbf87715eb45c169 192.168.0.130:6380@16380 slave 7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 0 1617294533000 2 connected

# 已下线
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 master,fail - 1617294479247 1617294475173 5 disconnected

7a151f97ee9b020a3c954bbf78cd7ed8a674aa70 192.168.0.140:6379@16379 master - 0 1617294536864 2 connected 10923-16383

# 自动升级为主库,并且插槽也转移了
fd1dde2a641727e52b4e82cfb351fe3c17690a17 192.168.0.140:6380@16380 master - 0 1617294536000 6 connected 0-5461

baa10306639fcaca833db0d521235bc9593dbeca 192.168.0.120:6380@16380 slave 214dc5a10149091047df1c61fd3415d91d6204ea 0 1617294535853 1 connected

恢复工作

重启node1的6379:

$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf

登录node1的6379,发现他已经自动的进行上线了,并且作为node3中6380的从库:

$ redis-cli -h node1 -p 6379  -a Esb@123

node1:6379> cluster nodes
# 自动上线
c8a8c7d52e6e7403e799c75302b6411e2027621b 192.168.0.120:6379@16379 myself,slave fd1dde2a641727e52b4e82cfb351fe3c17690a17 0 1617294746000 6 connected

cluster命令

以下是集群中常用的可执行命令,命令执行格式为:

cluster 下表命令

命令如下,未全,如果想了解更多请执行cluster help操作:

命令描述
INFO返回当前集群信息
MEET <ip> <port> [<bus-port>]添加一个节点至当前集群
MYID返回当前节点集群ID
NODES返回当前节点的集群信息
REPLICATE <node-id>将当前节点作为某一集群节点的从库
FAILOVER [FORCE|TAKEOVER]将当前从库升级为主库
RESET [HARD|SOFT]重置当前节点信息
ADDSLOTS <slot> [<slot> ...]为当前集群节点增加一个或多个插槽位,推荐在bash shell中执行,可通过{int..int}指定多个插槽位
DELSLOTS <slot> [<slot> ...]为当前集群节点删除一个或多个插槽位,推荐在bash shell中执行,可通过{int..int}指定多个插槽位
FLUSHSLOTS删除当前节点中所有的插槽信息
FORGET <node-id>从集群中删除某一节点
COUNT-FAILURE-REPORTS <node-id>返回当前集群节点的故障报告数量
COUNTKEYSINSLOT <slot>返回某一插槽中的键的数量
GETKEYSINSLOT <slot> <count>返回当前节点存储在插槽中的key名称。
KEYSLOT <key>返回该key的哈希槽位
SAVECONFIG保存当前集群配置,进行落盘操作
SLOTS返回该插槽的信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/875402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux的历史,版本,Linux的环境安装、简单学习4个基本的Linux指令、创建普通用户等的介绍

文章目录 前言一、Linux的历史二、版本三、Linux的环境安装1. 腾讯云服务器的申请2. xshell的安装与使用 四、 简单学习4个基本的Linux指令1. ls2. pwd3. mkdir4. cd 五、创建普通用户总结 前言 Linux的历史&#xff0c;版本&#xff0c;Linux的环境安装、简单学习4个基本的Li…

PHP随时随地预订民宿酒店预订系统小程序源码

随时随地预订&#xff0c;民宿酒店预订系统让旅行更自由&#xff01; &#x1f30d; 说走就走的旅行&#xff0c;从预订开始 旅行&#xff0c;总是让人心生向往&#xff0c;但繁琐的预订流程却常常让人望而却步。不过&#xff0c;现在有了“随时随地预订民宿酒店预订系统”&am…

RK3588九鼎创展方案在Arm集群服务器的项目中的应用分析​​

RK3588九鼎创展核心板&#xff0c;搭载8核瑞芯微3588芯片&#xff0c;具备高性能、低功耗以及强大的多媒体和AI处理能力。在Arm集群服务器项目中&#xff0c;RK3588系列芯片用有明显的性能优势。本文将结合RK3588芯片的性能特征以及九鼎创展的项目经验来分析RK3588在集群服务器…

【JAVA入门】Day34 - Stream流

【JAVA入门】Day34 - Stream流 文章目录 【JAVA入门】Day34 - Stream流一、Stream 流的作用和使用步骤1.Stream流的创建&#xff0c;数据的添加2. Stream流的中间方法3. Stream流的终结方法 Stream 流有什么作用&#xff1f;我们看一个例子&#xff1a; 【练习】需求&#xff…

swift qwen2-vl推理及加载lora使用案例

参考: https://swift.readthedocs.io/zh-cn/latest/Instruction/LLM%E5%BE%AE%E8%B0%83%E6%96%87%E6%A1%A3.html#%E5%BE%AE%E8%B0%83%E5%90%8E%E6%A8%A1%E5%9E%8B https://blog.csdn.net/weixin_42357472/article/details/142150209 SWIFT支持300+ LLM和50+ MLLM(多模态大模型…

利用高德+ArcGIS优雅获取任何感兴趣的矢量边界

荷花十里&#xff0c;清风鉴水&#xff0c;明月天衣。 四时之景不同&#xff0c;乐亦无穷尽也。今天呢&#xff0c;梧桐君给大家讲解一下&#xff0c;如何利用高德地图&#xff0c;随机所欲的获取shp边界数据。 文章主要分成以下几个步骤&#xff1a; 首先搜索你想获取的矢量…

发送成绩的app或小程序推荐

老师们&#xff0c;新学期的第一次月考马上开始&#xff0c;是不是还在为如何高效、便捷地发布成绩而头疼呢&#xff1f;别担心&#xff0c;都2024年了&#xff0c;我们有更智能的方式来解决这个问题&#xff01; 给大家安利一个超级实用的工具——易查分小程序。这个小程序简…

element ui form 表单出现英文提示的解决方案

场景再现&#xff1a; 在使用 form 表单的时候&#xff0c;一般都需要对表单元素进行验证&#xff0c;错误就出现在了这里&#xff0c;除了配置的错误信息&#xff0c;还会出现一个 英文校验提示&#xff0c;如下图&#xff1a; 解决方案 出现的原因是在el-form-item中使用…

把设计模式用起来(3)用不好的原因之时机不对

上一篇&#xff1a;《把设计模式用起来&#xff08;3&#xff09;——用不好的原因 之 实践不足》https://blog.csdn.net/nanyu/article/details/141939342 本篇继续讲设计模式用不好的常见原因&#xff0c;这是第二个&#xff1a;使用设计模式的时机不对。 二、时机不对 这里…

望繁信科技与华恒生物正式签约,共同开启流程数字化转型新篇章

近日&#xff0c;上海望繁信科技有限公司&#xff08;简称“望繁信科技”&#xff09;与安徽华恒生物科技股份有限公司&#xff08;简称“华恒生物”&#xff09;成功举行了战略合作签约仪式。作为全球领先的合成生物制造企业&#xff0c;华恒生物将引入望繁信科技的流程智能管…

3分钟带你了解什么是数据目录

什么是数据目录&#xff1f; 数据目录&#xff0c;顾名思义就是“数据的目录”。这里的“数据”指的是元数据。数据目录通过管理这些元数据&#xff0c;形成一个可用的数据清单&#xff0c;使数据开发者、数据分析师等人员能够通过查阅和搜索等操作&#xff0c;快速找到所需的数…

4052A/4052B/4052C/4052D/4052E/4052F/4052G /4052H信号/频谱分析仪

4052A/4052B/4052C/4052D/4052E/4052F/4052G /4052H信号/频谱分析仪 苏州新利通 Ceyear 4052具备出色的测试动态范围、相位噪声、幅度精度和测试速度&#xff0c;具备频谱分析、I/Q分析、实时频谱分析、瞬态分析、矢量信号分析、脉冲分析、音频分析等丰富的测试功能。 Ceyear…

长沙自闭症寄宿学校推荐,为孩子开启光明未来

在长沙这座历史悠久而又充满活力的城市中&#xff0c;自闭症儿童的成长与教育问题牵动着无数家庭的心。家长们渴望为孩子找到一所能够提供专业康复、温馨关怀与全面教育的学校&#xff0c;为他们的未来铺设一条光明之路。虽然本文起始于长沙的期盼&#xff0c;但我们的目光已跨…

SpringSecurity原理解析(二):认证流程

1、SpringSecurity认证流程包含哪几个子流程&#xff1f; 1&#xff09;账号验证 2&#xff09;密码验证 3&#xff09;记住我—>Cookie记录 4&#xff09;登录成功—>页面跳转 2、UsernamePasswordAuthenticationFilter 在SpringSecurity中处理认证逻辑是在UsernamePas…

Windows10 如何配置python IDE

Windows10 如何配置python IDE 前言Python直接安装&#xff08;快速上手&#xff09;Step1.找到网址Step2.选择版本&#xff08;非常重要&#xff09;Step3. 安装过程Step4. python测试 Anaconda安装&#xff08;推荐&#xff0c;集成了Spyder和Pycharm的安装&#xff09;Step1…

使用功率分析仪测量和分析电抗器(电感器)的方法

高频电抗器用于电动汽车 (EV) 和混合动力汽车 (HEV) 的各种位置。例如&#xff0c;电池和逆变器之间的升压 DC/DC 转换器以及电池充电电路中的 AC/DC 转换器。为了提高整个系统的效率&#xff0c;必须提高每个组成电路的效率&#xff0c;而电抗器是造成这些电路大量损耗的元件之…

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 目录 Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 一、简单介绍 二、FBO 简单介绍 三、案例实现原理 四、注意事项 五、简…

03 Flask-添加配置信息

回顾之前学习的内容 02 Flask-快速上手 Flask 中最简单的web应用组成 1. 导入核心库 Flask from flask import Flask2. 实例化 web应用 注意&#xff1a;不要漏了 app Flask(__name__) 中的 __name__ 表示&#xff1a;是从当前的py文件实例化 app Flask(__name__)3. 创…

力扣每日一题:1372.二叉树中的最长交错路径

题目 给你一棵以 root 为根的二叉树&#xff0c;二叉树中的交错路径定义如下&#xff1a; 选择二叉树中 任意 节点和一个方向&#xff08;左或者右&#xff09;。如果前进方向为右&#xff0c;那么移动到当前节点的的右子节点&#xff0c;否则移动到它的左子节点。改变前进方…

力扣213-打家劫舍 II(Java详细题解)

题目链接&#xff1a;213. 打家劫舍 II - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 本体是打家劫舍的一个变形题&#xff0c;希望大家能先做198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09;&#xff0c;并看一下我上题的讲解力扣198-打家劫舍&…