[微服务]redis主从集群搭建与优化

搭建主从集群

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。

1. 主从集群结构

下图就是一个简单的Redis主从集群结构:

如图所示,集群中有一个master节点、两个slave节点(现在叫replica)。当我们通过Redis的Java客户端访问主从集群时,应该做好路由:

  • 如果是写操作,应该访问master节点,master会自动将数据同步给两个slave节点
  • 如果是读操作,建议访问各个slave节点,从而分担并发压力

2. 搭建主从集群

我们会在同一个虚拟机中利用3个Docker容器来搭建主从集群,容器信息如下:

2.1. 启动多个Redis实例

利用资料提供的docker-compose配置文件来构建主从集群:

a. 文件内容说明:

version: "3.2"services:r1:image: rediscontainer_name: r1network_mode: "host"entrypoint: ["redis-server", "--port", "7001"]r2:image: rediscontainer_name: r2network_mode: "host"entrypoint: ["redis-server", "--port", "7002"]r3:image: rediscontainer_name: r3network_mode: "host"entrypoint: ["redis-server", "--port", "7003"]
  • redis官网建议在搭建集群时, 使用host网络模式, 让每个容器直接使用宿主机的网络
  • 此网络模式下, 容器会暴露在宿主机, 相当于成为宿主机的一个进程, 所以部署时也不需要端口映射
  • 直接使用宿主机的端口就可以了
  • entrypoint 入口配置, 用于修改容器的启动命令
  • "--port" 参数用于配置容器的默认端口

b. 把镜像文件上传至root目录下, 然后加载镜像文件

c. 在虚拟机的root目录下新建redis目录, 上传配置文件包

d. 执行命令,运行集群

docker compose up -d

执行结果:

查看docker容器,发现都正常启动了:

由于采用的是host模式,我们看不到端口映射。不过能直接在宿主机通过ps命令查看到Redis进程:

2.2. 建立集群

虽然我们启动了3个Redis实例,但是它们并没有形成主从关系。我们需要通过命令来配置主从关系:

# 参数说明
# masterip 主节点IP
# masterport 主节点端口# 两个命令都能用
# Redis5.0以前
slaveof <masterip> <masterport>
# Redis5.0以后
replicaof <masterip> <masterport>

有临时和永久两种模式:

  • 永久生效:在redis.conf文件中利用slaveof命令指定master节点
  • 临时生效:直接利用redis-cli控制台输入slaveof命令,指定master节点

我们测试临时模式,首先连接r2,让其以r1为master

# 连接r2
docker exec -it r2 redis-cli -p 7002
# 认r1主,也就是7001
slaveof 192.168.150.101 7001
# 退出连接
exit

然后连接r3,让其以r1为master

# 连接r3
docker exec -it r3 redis-cli -p 7003
# 认r1主,也就是7001
slaveof 192.168.150.101 7001

然后连接r1,查看集群状态:

# 连接r1
docker exec -it r1 redis-cli -p 7001
# 查看集群状态
info replication

可以看到,当前节点r1:7001的角色是master,有两个slave与其连接:

  • slave0port7002,也就是r2节点
  • slave1port7003,也就是r3节点

其中重要的信息有:

  • master_replid: 主节点的唯一id
  • offset=672: 偏移量

2.3. 测试

依次在r1r2r3节点上执行下面命令:

set num 123get num
  • 只有在r1这个节点上可以执行set命令(写操作), 其它两个节点只能执行get命令(读操作)。
  • 也就是说读写操作已经分离了。

主从同步原理

主从同步原理时序图

  1. 当主从第一次同步连接或断开重连时,从节点都会发送psync请求,尝试数据同步
  2. 主节点判断从节点是否第一次连接
  • 每个节点默认都是主节点, 每个主节点都有唯一id属性replicationID, 简称replid
  • 第一次paync, 从节点携带自己的replid
  • 所以, 主节点只需要判断, 从节点的replid是否与自己一致就可以了
  1. 如果是第一次连接, 主节点把自己所有数据全部发送给子节点
  • replid不一致, 属于第一次同步, 进行全量同步
  • 主节点将完整内存数据生成RDB,发送到从节点
  • 从节点清空本地数据, 加载RDBD到内存
  • 从节点把自己的replid 改成 主节点的replid
  1. 如果是重新连接, 主节点把子节点缺少的数据发给子节点
  • 全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了
  • 大多数时候从节点与主节点都是做增量同步
  • 增量同步就是只更新主从节点存在差异的数据。
  • 主节点会维护repl backlog文件, 其中会记录Redis处理过的命令及offset,包括主节点当前的offset,和子节点已经拷贝到的offset
  • 只要主从的offset一致, 代表数据一致, 如果offset存在差异, 那差异的部分,就是子节点需要增量拷贝的数据
  • repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于repl_baklog做增量同步,只能再次全量同步。
  1. 每次主节点写数据时, 都把命令传播给子节点, 保持数据实时同步

主从集群优化

可以从以下几个方面来优化Redis主从集群:

  1. 在master中配置repl-diskless-syncyes启用无磁盘复制,避免全量同步时的磁盘IO。
  2. Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO, 一般建议不超过8G
  3. 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  4. 限制master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

哨兵原理

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的具体作用如下:

  1. 监控: Sentinel会不断检查您的master和slave是否按预期工作
  2. 自动故障切换: 如果master故障,Sentinel会将-个slave提升为master。当故障实例恢复后也以新的master为主
  3. 通知: 当集群发生故障转移时,Sentinel会将最新节点角色信息推送给Redis的客户端

服务状态监控

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  1. 主观下线: 如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
  2. 客观下线: 若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。
  3. quorum值最好超过Sentinel实例数量的一半

选举新的master

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  1. 首先会判断slave节点与master节点断开时间长短, 如果超过指定值 (down-after-milliseconds*10) 则会排除该slave节点
  2. 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举, 默认都是1
  3. 如果slave-prority一样,则判断slave节点的offset值, 越大说明数据越新,优先级越高
  4. 最后是判断slave节点的运行id大小,越小优先级越高

如何实现故障转移

当选中了其中一个slave为新的master后(例如slave1),故障的转移的步骤如下:

  1. sentinel给备选的slave1节点发送 slaveof no one 命令,让该节点成为master
  2. sentinel给所有其它slave发送 slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  3. 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

搭建哨兵集群

首先, 停掉之前的redis集群:

# 老版本DockerCompose
docker-compose down# 新版本Docker
docker compose down

然后,我们找到课前资料提供的sentinel.conf文件:

其内容如下:

sentinel announce-ip "192.168.150.101"
sentinel monitor hmaster 192.168.150.101 7001 2
sentinel down-after-milliseconds hmaster 5000
sentinel failover-timeout hmaster 60000

说明:

  • sentinel announce-ip "192.168.150.101":声明当前sentinel的ip
  • sentinel monitor hmaster 192.168.150.101 7001 2:指定集群的主节点信息
    • hmaster:主节点名称,自定义,任意写
    • 192.168.150.101 7001:主节点的ip和端口
    • 2:认定master下线时的quorum
  • sentinel down-after-milliseconds hmaster 5000:声明master节点超时多久后被标记下线
  • sentinel failover-timeout hmaster 60000:在第一次故障转移失败后多久再次重试
  • 把配置文件中的信息修改为自己虚拟机的地址

我们在虚拟机的/root/redis目录下新建3个文件夹:s1s2s3:

  1. 将课前资料提供的sentinel.conf文件上传到s1文件夹中, 再拷贝到其他文件夹中。

  1. 接着修改docker-compose.yaml文件, 注意ip地址,内容如下:
version: "3.2"services:r1:image: rediscontainer_name: r1network_mode: "host"entrypoint: ["redis-server", "--port", "7001"]r2:image: rediscontainer_name: r2network_mode: "host"entrypoint: ["redis-server", "--port", "7002", "--slaveof", "192.168.150.101", "7001"]r3:image: rediscontainer_name: r3network_mode: "host"entrypoint: ["redis-server", "--port", "7003", "--slaveof", "192.168.150.101", "7001"]s1:image: rediscontainer_name: s1volumes:- /root/redis/s1:/etc/redisnetwork_mode: "host"entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]s2:image: rediscontainer_name: s2volumes:- /root/redis/s2:/etc/redisnetwork_mode: "host"entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]s3:image: rediscontainer_name: s3volumes:- /root/redis/s3:/etc/redisnetwork_mode: "host"entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]
  1. 直接运行命令,启动集群:
docker-compose up -d
  1. 运行结果:

我们以s1节点为例,查看其运行日志:

可以看到sentinel已经联系到了7001这个节点,并且与其它几个哨兵也建立了链接。哨兵信息如下:

  • 27001Sentinel ID8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf
  • 27002Sentinel ID5bafeb97fc16a82b431c339f67b015a51dad5e4f
  • 27003Sentinel ID56546568a2f7977da36abd3d2d7324c6c3f06b8d

演示failover

接下来,我们演示一下当主节点故障时,哨兵是如何完成集群故障恢复(failover)的。

我们连接7001这个master节点,然后通过命令让其休眠60秒,模拟宕机:

# 连接7001这个master节点,通过sleep模拟服务宕机,60秒后自动恢复
docker exec -it r1 redis-cli -p 7001 DEBUG sleep 60

稍微等待一段时间后,会发现sentinel节点触发了failover

RedisTemplate连接哨兵集群

分为三步:

  • 1)引入依赖
  • 2)配置哨兵地址
  • 3)配置读写分离

1.引入依赖

就是SpringDataRedis的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.配置哨兵地址

连接哨兵集群与传统单点模式不同,不再需要设置每一个redis的地址,而是直接指定哨兵地址:

spring:redis:sentinel:master: hmaster # 集群名nodes: # 哨兵地址列表- 192.168.150.101:27001- 192.168.150.101:27002- 192.168.150.101:27003

3.配置读写分离

最后,还要配置读写分离,让java客户端将写请求发送到master节点,读请求发送到slave节点。定义一个bean即可:

@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

这个bean中配置的就是读写策略,包括四种:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
  • REPLICA:从slave节点读取
  • REPLICA_PREFERRED:优先从slave节点读取,所有的slave都不可用才读取master

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化立体仓库堆垛机SRM控制系统自动控制功能块开发

1、堆垛机SRM控制系统硬件组态如下图 2、堆垛机SRM控制系统HMI屏幕页面如下图 驱动状态显示、堆垛机状态 3、堆垛机SRM控制系统中相关变量定义如下图 其中包含系统控制相关变量:系统急停、系统手动、复位、货叉左极限、货叉左居中 货叉右极限 货叉右居中 货叉编码器位置反…

【数据结构】栈与队列(FIFO)

在阅读该篇文章之前&#xff0c;可以先了解一下堆栈寄存器和栈帧的运作原理&#xff1a;<【操作系统】堆栈寄存器sp详解以及栈帧>。 栈(FILO) 特性: 栈区的存储遵循着先进后出的原则。 例子: 枪的弹夹&#xff0c;最先装进去的子弹最后射出来&#xff0c;最后装入的子弹…

黑马JavaWeb开发跟学(十五).Maven高级

黑马JavaWeb开发跟学.十五.Maven高级 Maven高级1. 分模块设计与开发1.1 介绍1.2 实践1.2.1 分析1.2.2 实现 1.3 总结 2. 继承与聚合2.1 继承2.1.1 继承关系2.1.1.1 思路分析2.1.1.2 实现 2.1.2 版本锁定2.1.2.1 场景2.1.2.2 介绍2.1.2.3 实现2.1.2.4 属性配置 2.2 聚合2.2.1 介…

入门级容器技术解析:Docker和K8s的区别与关系

目录 &#x1f3af;学习小目标&#xff1a; 关于容器 传统物理机&#x1f5a5;️ 虚拟机&#x1f4bb; 为什么使用容器技术呢&#xff1f;&#x1f914; 容器技术&#x1f943; Docker—容器化平台 K8s(Kubernetes)—容器编排系统​ Docker和K8s有什么关系和区别&#…

凌鸥电机开发学习记录

文章目录 9、凌鸥库函数软件过流点设定值BUG8、系统初始化7、ADC触发周期设定6、电机参数测量5、有感HALL相序问题4、电机参数问题3、PWM频率设置2、IO口对应问题1、供电问题 9、凌鸥库函数软件过流点设定值BUG 在软件过流点的判断中&#xff0c;是以当前三相电流和经过了内部…

怎样修改el-table主题样式

起因&#xff1a;el-table有主题样式&#xff0c;部分需要单独设置 环境&#xff1a;ideanodejs插件谷歌浏览器 第一步&#xff1a;找到scss文件&#xff1a; 谷歌浏览器打开表格页面&#xff0c;ctrlshifti打开开发者工具&#xff0c;点击后鼠标移动到表格单元格上单击一下…

Flink operator实现自动扩缩容

官网文档位置&#xff1a; 1.Autoscaler | Apache Flink Kubernetes Operator 2.Configuration | Apache Flink Kubernetes Operator 1.部署K8S集群 可参照我之前的文章k8s集群搭建 2.Helm安装Flink-Operator helm repo add flink-operator-repo https://downloads.apach…

从入门到精通:Ansible Shell 模块的应用与最佳实践

Ansible是一款强大的自动化运维工具&#xff0c;通过其模块化的设计&#xff0c;可以方便地管理和配置远程主机。作为Ansible的一个常用模块&#xff0c;shell 模块使得我们可以在目标主机上执行复杂的命令或脚本。无论是单一的命令&#xff0c;还是复杂的Shell脚本&#xff0c…

Linux应用软件编程--网络通信(传输层:udp协议,tcp协议,应用层:http协议)

网络通信&#xff1a;不同主机&#xff0c;进程间通信&#xff0c;分为广域网和局域网 OSI 七层模型&#xff1a;是一种理论模型 应用层&#xff1a;通信传输的数据内容 http、FTP、TFTP、MQTT 表述层&#xff1a;数据加密&#xff0c;解密操作&#xff0c;压缩&#xff…

鸿蒙的APP真机调试以及发布

目录&#xff1a; 1、创建好鸿蒙项目2、创建AGC项目3、实现自动签名3.1、手动方式创建签名文件和密码 4、运行项目5、无线真机调试 1、创建好鸿蒙项目 2、创建AGC项目 &#xff08;1&#xff09;在File->Project Structure->Project->Signing Configs中进行登录。(未…

n8n - AI自动化工作流

文章目录 一、关于 n8n关键能力n8n 是什么意思 二、快速上手 一、关于 n8n n8n是一个具有原生AI功能的工作流自动化平台&#xff0c;它为技术团队提供了代码的灵活性和无代码的速度。凭借400多种集成、原生人工智能功能和公平代码许可证&#xff0c;n8n可让您构建强大的自动化…

【Shell脚本】Docker构建Java项目,并自动停止原镜像容器,发布新版本

本文简述 经常使用docker部署SpringBoot 项目&#xff0c;因为自己的服务器小且项目简单&#xff0c;因此没有使用自动化部署。每次将jar包传到服务器后&#xff0c;需要手动构建&#xff0c;然后停止原有容器&#xff0c;并使用新的镜像启动&#xff0c;介于AI时代越来越懒的…

jmeter 中 BeanShell 预处理程序、JSR223后置处理程序使用示例

1. 各个组件如何新建的&#xff1f; 2. "http请求" 组件内容样例&#xff1a; "消息体数据" 源码&#xff1a; {"task_tag": "face_detect","image_type": "base64","extra_args": [{"model"…

K8s高可用集群之Kubernetes集群管理平台、命令补全工具、资源监控工具部署及常用命令

K8s高可用集群之Kubernetes管理平台、补全命令工具、资源监控工具部署及常用命令 1.Kuboard可视化管理平台2.kubectl命令tab补全工具3.MetricsServer资源监控工具4.Kubernetes常用命令 1.Kuboard可视化管理平台 可以选择安装k8s官网的管理平台&#xff1b;我这里是安装的其他开…

Centos源码安装MariaDB 基于GTID主从部署(一遍过)

MariaDB安装 安装依赖 yum install cmake ncurses ncurses-devel bison 下载源码 // 下载源码 wget https://downloads.mariadb.org/interstitial/mariadb-10.6.20/source/mariadb-10.6.20.tar.gz // 解压源码 tar xzvf mariadb-10.5.9.tar.gz 编译安装 cmake -DCMAKE_INSTA…

github gitbook写书

github创建新的仓库 在仓库中添加目录 ‘SUMMARY.md # Summary * [简介](README.md)gitbook 新建一个site https://www.gitbook.com/ 注册账号 取名字 一路 next&#xff0c;注意选免费版 最后 gitbook同步到github 你在主页可以看到 刚刚的test网站 点击右上角圈出来…

colnames看似简单,却能优化数据处理流程

引言 在数据处理和分析中&#xff0c;变量名称是至关重要的&#xff0c;它们决定了数据的可读性和操作的简便性。在R语言中&#xff0c;colnames 函数以其简单的语法设计&#xff0c;提供了高效管理数据框列名的能力&#xff0c;尤其是在复杂的爬虫任务中显得尤为重要。本篇文…

2025新春烟花代码(一)HTML5夜景放烟花绽放动画效果

标题预览效果 标题HTML代码 <!DOCTYPE html> <html lang"en"> <script>var _hmt _hmt || [];(function () {var hm document.createElement("script");hm.src "https://hm.baidu.com/hm.js?45f95f1bfde85c7777c3d1157e8c2d34&…

软件项目体系建设文档,项目开发实施运维,审计,安全体系建设,验收交付,售前资料(word原件)

软件系统实施标准化流程设计至关重要&#xff0c;因为它能确保开发、测试、部署及维护等各阶段高效有序进行。标准化流程能减少人为错误&#xff0c;提升代码质量和系统稳定性。同时&#xff0c;它促进了团队成员间的沟通与协作&#xff0c;确保项目按时交付。此外&#xff0c;…

通过shell脚本定时采集数据到HDFS

第一步&#xff1a;创建shell脚本&#xff08;在虚拟机1下的/export/data目录下执行vi uploadHDFS.sh命令&#xff0c;编辑shell脚本文件&#xff0c;具体代码如下&#xff1a;&#xff09; 第二步&#xff1a;执行shell脚本&#xff08;确保Hadoop集群处于启动状态&#xff0c…