前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis 集群操作实战

Redis 集群操作实战

作者头像
BUG弄潮儿
发布于 2021-04-12 03:14:16
发布于 2021-04-12 03:14:16
39500
代码可运行
举报
文章被收录于专栏:JAVA乐园JAVA乐园
运行总次数:0
代码可运行
0x01:Redis 集群简介

Redis 是一个开源的 key-value 存储系统,由于出众的性能,大部分互联网企业都用来做服务器端缓存。Redis 在 3.0 版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决单点故障,但是互联网企业动辄大几百G的数据,可这些模式没法满足业务的需求,所以 Redis 在 3.0 版本以后就推出了集群模式。

Redis 集群采用了 P2P 的模式,完全去中心化。Redis 把所有的 Key 分成了 16384 个哈希槽(slot),每个 Redis 实例负责其中一部分 slot 。集群中的所有信息(节点、端口、slot等),都通过节点之间定期的数据交换而更新。

Redis 客户端可以在任意一个 Redis 实例发出请求,如果所需数据不在该实例中,通过重定向命令引导客户端访问所需的实例。

集群要点:

  • Redis 是一个开源的 key-value 存储系统,受到了广大互联网公司的青睐。Redis 3.0 版本之前只支持单例模式,在 3.0 版本及以后才支持集群;
  • Redis 集群采用 P2P 模式,是完全去中心化的,不存在中心节点或者代理节点;
  • Redis 集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG 机制),每个节点都是一个 Redis 实例;
  • 为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster 有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的算法;
  • 如何判断集群是否挂了呢?

如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的算法;

  • 那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢?

因为集群内置了 16384 个 slot(哈希槽),并且把所有的物理节点映射到了这16384 [ 0-16383 ]个 slot 上,或者说把这些 slot 平均的分配给了各个节点。当需要在 Redi s集群存放一个数据(key-value)时,Redis 会先对这个 key 进行 crc16 算法,然后得到一个结果。再把这个结果对 16384 进行求余,这个余数会对应[ 0-16383 ]其中一个槽,进而决定 key-value 存储到哪个节点中。所以一旦某个节点挂了,该节点对应的 slot 就无法使用,那么就会导致集群无法正常工作。

0x02:环境说明

  • Redis 集群至少需要 3 个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以 2 个节点无法构成集群。
  • 要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以 Redis 集群至少需要 6 台服务器。因为没有那么多服务器,也无法在一台 widows 启动不了那么多虚拟机,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行 6个 Redis 实例,修改端口号为(7001-7006),当然实际生产环境的Redis集群搭建和这里也是大同小异的。
  • 安装 Ruby 环境

0x03:集群搭建

在搭建集群前,先了解单机的安装:Redis系列:Linux下部署Redis 6.x 版本

  • 在 /usr/local 目录下新建 redis-cluster 目录,用于存放集群节点的所有Redis 实例
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir /usr/local/redis-cluster
  • 单机版安装的好的redis拷贝到 /usr/local/redis-cluster 目录
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cp -r /usr/local/redis /usr/local/redis-cluster/

目录结构如下

  • 基于该 Redis 复制出 6 个节点
  • 修改配置文件,主要配置点如下
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bind 127.0.0.1 #绑定当前机器 IP
port 6379 #每个节点的端口号
daemonize no #是否后台启动
dir ./ #数据文件存放位置
dbfilename dump.rdb
pidfile /var/run/redis_6379.pid # pid 6379和port要对应
cluster-enabled yes #启动集群模式
cluster-config-file nodes-6379.conf # 6379和port要对应
cluster-node-timeout 15000 #集群节点超时时间
appendonly yes #是否启动 aof 模式

比如 7001 节点配置,主要是标识的地方有所不一致(其他节点请按照端口修改即可

集群配置参数主要有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cluster-enabled <yes/no>
cluster-config-file <filename>
cluster-node-timeout <milliseconds>
cluster-slave-validity-factor <factor>
cluster-migration-barrier <count>
cluster-require-full-coverage <yes/no>

详细解释如下:

  1. cluster-enabled <yes/no>: 该项如果设置成yes,该实例支持redis集群;否则该实例会像往常一样以独立模式启动。
  2. cluster-config-file <filename>: 必须注意到尽管该项是可选的,这并不是一个用户可以编辑的配置文件,这是redis集群节点自动生成的配置文件,每次一旦配置有修改它都通过该配置文件来持久化配置(基本上都是状态),这样在下次启动的时候可以重新读取这些配置。该文件中列出了该集群中的其他节点的状态,持久化变量等信息。当节点收到一些信息的时候该文件就会被冲重写。
  3. cluster-node-timeout <milliseconds>: redis集群节点的最大超时时间。响应超过这个时间的话该节点会被认为是挂掉了。如果一个master节点超过一定的时候无法访问,它会被它的slave取代。该参数在redis集群配置中很重要。很明显,当节点无法访问大部分master节点超过一定时间后,它会停止接受查询请求。
  4. cluster-slave-validity-factor <factor>:如果将该项设置为0,不管slave节点和master节点间失联多久都会一直尝试failover(设为正数,失联大于一定时间(factor*节点TimeOut),不再进行FailOver)。比如,如果节点的timeout设置为5秒,该项设置为10,如果master跟slave之间失联超过50秒,slave不会去failover它的master(意思是不会去把master设置为挂起状态,并取代它)。注意:任意非0数值都有可能导致当master挂掉又没有slave去failover它,这样redis集群不可用。在这种情况下只有原来那个master重新回到集群中才能让集群恢复工作。
  5. cluster-migration-barrier <count>: 一个master可以拥有的最小slave数量。该项的作用是,当一个master没有任何slave的时候,某些有富余slave的master节点,可以自动的分一个slave给它。具体参见手册中的replica migration章节
  6. cluster-require-full-coverage <yes/no>: 如果该项设置为yes(默认就是yes) 当一定比例的键空间没有被覆盖到(就是某一部分的哈希槽没了,有可能是暂时挂了)集群就停止处理任何查询炒作。如果该项设置为no,那么就算请求中只有一部分的键可以被查到,一样可以查询(但是有可能会查不全)
  • 启动所有节点
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/usr/local/redis-cluster/redis-7001/bin/redis-server /usr/local/redis-cluster/redis-7001/etc/redis.conf 
/usr/local/redis-cluster/redis-7002/bin/redis-server /usr/local/redis-cluster/redis-7002/etc/redis.conf 
/usr/local/redis-cluster/redis-7003/bin/redis-server /usr/local/redis-cluster/redis-7003/etc/redis.conf 
/usr/local/redis-cluster/redis-7004/bin/redis-server /usr/local/redis-cluster/redis-7004/etc/redis.conf 
/usr/local/redis-cluster/redis-7005/bin/redis-server /usr/local/redis-cluster/redis-7005/etc/redis.conf 
/usr/local/redis-cluster/redis-7006/bin/redis-server /usr/local/redis-cluster/redis-7006/etc/redis.conf 

启动结果如下

可以创建一个启动所有节点的 Shell 脚本 start-all.sh,然后授权 chmod +x start-all.sh,脚本的内容如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/usr/local/redis-cluster/redis-7001/bin/redis-server /usr/local/redis-cluster/redis-7001/etc/redis.conf 
/usr/local/redis-cluster/redis-7002/bin/redis-server /usr/local/redis-cluster/redis-7002/etc/redis.conf 
/usr/local/redis-cluster/redis-7003/bin/redis-server /usr/local/redis-cluster/redis-7003/etc/redis.conf 
/usr/local/redis-cluster/redis-7004/bin/redis-server /usr/local/redis-cluster/redis-7004/etc/redis.conf 
/usr/local/redis-cluster/redis-7005/bin/redis-server /usr/local/redis-cluster/redis-7005/etc/redis.conf 
/usr/local/redis-cluster/redis-7006/bin/redis-server /usr/local/redis-cluster/redis-7006/etc/redis.conf 
  • 测试

随便找一个接口测试一下,发现如下错误

虽然是连接成功了,但设置值时报错了???

(error) CLUSTERDOWN Hash slot not served(不提供集群的散列槽),这是什么鬼?这是因为虽然配置并启动了 Redis 集群服务,但是他们暂时还并不在一个集群中,互相直接发现不了,而且还没有可存储的位置,就是所谓的 slot(槽)。

0x04:安装集群所需软件

由于 Redis 集群需要使用 Ruby 命令,所以需要安装 Ruby 和相关软件包。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yum install ruby
yum install rubygems
gem install redis 

因为 CentOS 系统自带的 ruby 版本为 2.0.0,所以执行最后一条命令出现以下错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost bin]# gem install redis
Fetching: redis-4.2.5.gem (100%)
ERROR:  Error installing redis:
    redis requires Ruby version >= 2.3.0.

卸载系统自带 Ruby,安装 ruby 2.3.0版本

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# yum remove ruby
# yum install centos-release-scl-rh //会在/etc/yum.repos.d/目录下多出一个CentOS-SCLo-scl-rh.repo源
# yum install rh-ruby23  -y //直接yum安装即可
# scl  enable  rh-ruby23 bash //必要一步
# ruby -v

安装完 ruby 2.3.0 版本后在执行如下命令

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yum install rubygems
gem install redis 

0x05:创建集群

在单机版的安装目录的 bin 目录下找到 redis-trib.rb 可执行命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/usr/local/redis-cluster/redis-7001/bin/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-trib.rb 命令已经至少6.0后版本被废弃了(具体哪个版本开始使用 redis-cli 可以去官网寻找下答案),可以推断 Ruby 环境的搭建有点多余了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /usr/local/redis-cluster/redis-7001/bin/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

执行命令后输入如下信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost redis-cluster]#  /usr/local/redis-cluster/redis-7001/bin/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
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7006 to 127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 35059b475861367c728e38cb6219285c8ee690ce 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
M: bd8901584958443a44e97455bf2a0e6be6d9cd2a 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
M: 4d9bf1375da15ba3a42ec36da38d7d4d4efc99a8 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
S: f7df7df06237243c6604db6ba91f18bc0d1e8960 127.0.0.1:7004
   replicates 4d9bf1375da15ba3a42ec36da38d7d4d4efc99a8
S: cdac10f680eb00164360f0a9dbe38263db089fe7 127.0.0.1:7005
   replicates 35059b475861367c728e38cb6219285c8ee690ce
S: b2f8a3586e5ffa2d9037cc0b1226b5b0a003ec62 127.0.0.1:7006
   replicates bd8901584958443a44e97455bf2a0e6be6d9cd2a
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join

>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 35059b475861367c728e38cb6219285c8ee690ce 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: f7df7df06237243c6604db6ba91f18bc0d1e8960 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 4d9bf1375da15ba3a42ec36da38d7d4d4efc99a8
M: 4d9bf1375da15ba3a42ec36da38d7d4d4efc99a8 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: cdac10f680eb00164360f0a9dbe38263db089fe7 127.0.0.1:7005
   slots: (0 slots) slave
   replicates 35059b475861367c728e38cb6219285c8ee690ce
M: bd8901584958443a44e97455bf2a0e6be6d9cd2a 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: b2f8a3586e5ffa2d9037cc0b1226b5b0a003ec62 127.0.0.1:7006
   slots: (0 slots) slave
   replicates bd8901584958443a44e97455bf2a0e6be6d9cd2a
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

至此,Redi集群搭建成功!大家注意最后一段信息

显示了每个节点所分配的 slots(哈希槽),这里总共6个节点,其中3个是从节点,所以3个主节点分别映射了0-5460、5461-10922、10933-16383 solts。

0x06:测试验证

连接集群节点,连接任意一个即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bin/redis-cli -h 127.0.0.1 -p 7001 -c 

注意:一定要加上 -c 参数,否则节点之间是无法自动跳转。如下图可以看到,存储的数据(key-value)被均匀分配到不同的节点。

另外,如果没有加上 -c 参数,出现如下错误

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BUG弄潮儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
ASP.NET Core+Quartz.Net实现web定时任务
作为一枚后端程序狗,项目实践常遇到定时任务的工作,最容易想到的的思路就是利用Windows计划任务/wndows service程序/Crontab程序等主机方法在主机上部署定时任务程序/脚本。
有态度的马甲
2020/04/16
2.8K0
ASP.NET Core+Quartz.Net实现web定时任务
手把手教你用.NET Core写爬虫
自从上一个项目58HouseSearch从.NET迁移到.NET core之后,磕磕碰碰磨蹭了一个月才正式上线到新版本。
李国宝
2018/05/23
2.2K0
手把手教你用.NET Core写爬虫
一行代码完成定时任务调度,基于Quartz的UI可视化操作组件 GZY.Quartz.MUI
NET Core 基于Quartz的UI可视化操作组件 GZY.Quartz.MUI 简介
GuZhenYin
2022/05/11
1.3K0
一行代码完成定时任务调度,基于Quartz的UI可视化操作组件 GZY.Quartz.MUI
记录Quartz定时任务框架的学习过程(一)
拿火车票购票来说,当你下单后,后台就会插入一条待支付的task(job),一般是30分钟,超过30min后就会执行这个job,去判断你是否支付,未支付就会取消此次订单;当你支付完成之后,后台拿到支付回调后就会再插入一条待消费的task(job),Job触发日期为火车票上的出发日期,超过这个时间就会执行这个job,判断是否使用等。
青衫染红尘
2021/04/28
8190
.net core下定时任务的实现
Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库。在 .net core的环境中,由Core自带的DI管理着生命周期,免去了在NF4.X环境中配置always running的麻烦,真正做到开箱即用。
Bug生活2048
2018/08/31
1.4K0
.net core下定时任务的实现
Quartz定时任务框架使用教程详解
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:
大忽悠爱学习
2021/12/07
2.3K0
Quartz定时任务框架使用教程详解
手把手教你写dotnet core(MVC)
上一篇手把手教你写dotnet core(入门篇)我们已经简单在dotnet core里面跑了个”hello world!”和累加程序.
李国宝
2020/01/02
1.1K0
手把手教你写dotnet core(MVC)
第三十九章:基于SpringBoot & Quartz完成定时任务分布式单节点持久化
定时任务在企业项目比较常用到,几乎所有的项目都会牵扯该功能模块,定时任务一般会处理指定时间点执行某一些业务逻辑、间隔时间执行某一些业务逻辑等。我们在之前有讲过SpringBoot是已经集成了定时任务的,详见:第二十六章:SpringBoot使用@Scheduled创建定时任务,那么我们本章将会采用外置的quartz定时任务框架来完成定时任务的分布式单节点持久化,我们为什么要持久化定时任务呢? 在一些项目中定时任务可能是必不可少的,由于某种特殊的原因定时任务可能丢失,如重启定时任务服务项目后,原内存中的定时任
恒宇少年
2018/06/27
2.4K0
.NET有哪些好用的定时任务调度框架
定时任务调度的相关业务在日常工作开发中是一个十分常见的需求,经常有小伙伴们在技术群提问:有什么好用的定时任务调度框架推荐的?今天大姚给大家分享5个.NET开源、简单、易用、免费的任务调度框架,帮助大家在做定时任务调度框架技术选型的时候有一个参考。
追逐时光者
2024/05/09
4200
.NET有哪些好用的定时任务调度框架
ASP.NET Core快速入门(第2章:配置管理)--学习笔记
课程链接:http://video.jessetalk.cn/course/explore
郑子铭
2021/01/13
7290
ASP.NET Core快速入门(第2章:配置管理)--学习笔记
在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度
在这篇文章中,我将介绍如何使用ASP.NET Core托管服务运行Quartz.NET作业。这样的好处是我们可以在应用程序启动和停止时很方便的来控制我们的Job的运行状态。接下来我将演示如何创建一个简单的 IJob,一个自定义的 IJobFactory和一个在应用程序运行时就开始运行的QuartzHostedService。我还将介绍一些需要注意的问题,即在单例类中使用作用域服务。
依乐祝
2020/04/09
3.1K0
在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度
《SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战》​
新手常见困惑: 刚学SpringBoot时,我发现用@Scheduled写定时任务特别简单。但当我看到同事在项目里用Quartz时,代码突然变得复杂起来——为什么要用这些复杂的配置?难道注解不香吗?
摘星.
2025/05/20
780
Quartz定时任务框架:原理、应用与实战
今日推荐 《TCP/IP 协议职责和常见的三种模型介绍》这篇文章介绍了了如何使用Python构建一个智能食品包装设计的深度学习模型。从数据准备、模型构建、训练、评估到实际应用,每一步都有详细的代码说明。这样的技术不仅能够提高食品包装设计的效率和质量,还能根据市场需求实现个性化和智能化设计,为消费者带来更好的体验。
Front_Yue
2024/11/25
7840
Quartz定时任务框架:原理、应用与实战
3分钟掌握Quartz.net分布式定时任务的姿势
细心朋友稍一分析,就知道还有问题: 水平扩展后的WebApp的Quartz.net定时任务会多次触发, 因为webapp实例使用的是默认的RAMJobStore, 多实例在内存中都维护了Job和Trigger的副本.
有态度的马甲
2020/05/01
2.1K0
再见 Spring Task,这个定时任务框架真香!
于是,我简单写了一篇文章总结一下定时任务的一些概念以及一些常见的定时任务技术选型。希望能对小伙伴们有帮助!
Guide哥
2021/10/11
2.9K0
.Net5下定时任务Quartz的使用
关于Quartz的使用在《项目实战|C#Socket通讯方式改造(二)--利用Quartz实现定时任务处理》中已经写过一篇,不过那个是在.net framework中的使用,在.net5下使用起来还是有一些差别的,所以这篇主要就是介绍一下Quartz在.net5下的使用。
Vaccae
2021/01/06
1.7K0
.Net5下定时任务Quartz的使用
SpringBoot入门建站全系列(十五)内置定时任务及Quartz定时任务使用
2.ScheduledExecutorService,线程池版的TimerTask。
品茗IT
2019/08/19
1.3K0
C#/.NET/.NET Core定时任务调度的方法或者组件有哪些--Timer,FluentScheduler还是...
原文由Rector首发于 码友网 之 《C#/.NET/.NET Core应用程序编程中实现定时任务调度的方法或者组件有哪些,Timer,FluentScheduler,TaskScheduler,Gofer.NET,Coravel,Quartz.NET还是Hangfire》
Rector
2020/06/19
3.8K0
Hangfire Redis 实现秒级定时任务、使用 CQRS 实现动态执行代码
本文示例项目仓库:https://github.com/whuanle/HangfireDemo
痴者工良
2025/04/19
1280
Hangfire Redis 实现秒级定时任务、使用 CQRS 实现动态执行代码
dotNET Core:配置
在dotNET Core中默认情况下没有了之前版本的App.config和Web.Config文件,换成了新的json格式的配置文件。当然,如果想使用之前的方式也是可以的。下面说说在dotNET Core中各种使用配置的方法。
oec2003
2019/07/19
6460
dotNET Core:配置
推荐阅读
相关推荐
ASP.NET Core+Quartz.Net实现web定时任务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档