当前位置: 首页 > article >正文

Redis主从集群和哨兵集群

为什么要搭建Redis主从集群?

单节点的Redis的并发能力是有上限的,如果想要提高Redis并发能力,需要搭建主从集群。

主从集群 

主从集群结构图: 

当客户端向Redis数据时,会写到master,然后master同步数据到slave;

当客户端向Redis数据时,会优先从slave读取数据。

搭建主从集群 

1.启动多个redis容器

 基于Linux环境,使用Docker Compose进行多容器启动。

Docker 是 Docker Compose 的前提,Docker Compose 是为了简化使用 Docker 时多容器应用的管理和部署而设计的。

容器名

角色

IP

映射端口

r1

master

192.168.150.101

7001

r2

slave

192.168.150.101

7002

r3

slave

192.168.150.101

7003

docker-compose.yaml:

services:
  r1:
    image: redis
    container_name: r1
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7001"]
  r2:
    image: redis
    container_name: r2
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7002"]
  r3:
    image: redis
    container_name: r3
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7003"]

 安装docker compose可以到其他博主

Docker Compose - 安装和基本使用_docker-compose安装-CSDN博客

将docker-compose.yaml迁移到/root/redis

 

 执行命令

docker-compose up -d

查看节点

可以看到,初始状态下,每个实例都是master。

 

搭建主从集群

# Redis5.0以前
slaveof <masterip> <masterport>
# Redis5.0以后
replicaof <masterip> <masterport>

有临时和永久两种模式:

  • 永久生效:在redis.conf文件中利用slaveof命令指定master节点

  • 临时生效:直接利用redis-cli控制台输入slaveof命令,指定master节点

临时生效:

 

 测试读写

在master节点可以写和读,在slave节点只能读

 主从同步原理

为什么搭建主从集群后,在master r1写入的信息,在slave r2 r3可以读到信息,说明主从之间完成了数据同步。

全量同步和增量同步

  • 全量同步:在该节点第一次来同步,将master的全部数据通过bgsave命令(redis在内存中的所有数据持久化到硬盘中)生成RDB文件,发送到slave执行;
  • 增量同步: 该节点不是第一次同步,因为某些原因宕机后又恢复了,此时只需要将slave宕机后master写入的数据同步即可;

全量同步

那master如何判断slave是不是第一次来同步?

replicationID:每一个master节点都有自己的id,在为搭建主从关系前,每一个节点都是master,所以replicationID不同,搭建主从集群后,有些master变成了slave,replicationID也变成了master的replicationID。所以可以根据replicationID是否相同来判断,不同则是第一次来。

增量同步

理论上来说,对重连需要同步新数据的slave执行全量同步也能同步数据,但是全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了。

master和slave虽然又主从关系,但是无法监听,说明master是不知道slave什么时候宕机的,那增量同步要从哪里开始?

offset:repl_backing会记录第一次建立主从同步的所有写操作命令,写得越多,offset越大,当主从的offset一致则代表数据一致。

offset记录了master和slave的同步情况,可以根据offset的差距去执行增量同步。

repl_backing文件,这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。

会存在问题,假如长度为10(0-1-2-3-4-5-6--7-8-9-0),在slave宕机时,同步数据0-2,master更新数据绕了一圈又回到了2,这时候就刚好,但是超过2后,就会覆盖数据,slave就无法同步被覆盖的数据。

主从同步优化

 Redis哨兵

前面说那么多,主从集群、提高并发和主从同步,那主没怎么办?

哨兵(sentinel)就是用来保证主从集群的高可用性的。

  • 状态监控Sentinel 会不断检查您的masterslave是否按预期工作

  • 故障恢复(failover):如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后会成为slave

  • 状态通知Sentinel充当Redis客户端的服务发现来源,当集群发生failover时,会将最新集群信息推送给Redis的客户端

 1.状态监控

Sentinel基于心跳机制监测Redis集群服务状态,每隔1秒向集群的每个节点发送ping命令,并通过响应结果来做出判断:

  • 主观下线(sdown):如果某sentinel节点发现某Redis节点未在规定时间响应,则认为该节点主观下线。

  • 客观下线(odown):若超过指定数量(通过quorum设置)的sentinel都认为该节点主观下线,则该节点客观下线。quorum值最好超过Sentinel节点数量的一半,Sentinel节点数量至少3台。

 

2.故障恢复 

在当前master宕机后,Sentinel会根据规则选取一个slave作为新的master:

  • 首先会判断slave节点与master节点断开时间长短,如果超过down-after-milliseconds * 10则会排除该slave节点;

  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举(默认都是1)。

  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高

  • 最后是判断slave节点的run_id大小,越小优先级越高(通过info server可以查看run_id)。

问题来了,当选出一个新的master后,该如何实现身份切换呢?

大概分为两步:

  • 在多个sentinel中选举一个leader

  • leader执行failover

 3.选举leader

首先,Sentinel集群要选出一个执行failover的Sentinel节点,可以成为leader。要成为leader要满足两个条件:

  • 最先获得超过半数的投票

  • 获得的投票数不小于quorum

而sentinel投票的原则有两条:

  • 优先投票给目前得票最多的

  • 如果目前没有任何节点的票,就投给自己

比如有3个sentinel节点,s1s2s3,假如s2先投票:

  • 此时发现没有任何人在投票,那就投给自己。s2得1票

  • 接着s1s3开始投票,发现目前s2票最多,于是也投给s2s2得3票

  • s2称为leader,开始故障转移

不难看出,谁先投票,谁就会称为leader,那什么时候会触发投票呢?

答案是第一个确认master客观下线的人会立刻发起投票,一定会成为leader。

4.故障转移

 5.搭建哨兵集群

1.修改docker-compose.yaml:

version: "3.2"

services:
  r1:
    image: redis
    container_name: r1
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7001"]
  r2:
    image: redis
    container_name: r2
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7002", "--slaveof", "虚拟机ip", "7001"]
  r3:
    image: redis
    container_name: r3
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7003", "--slaveof", "虚拟机ip", "7001"]
  s1:
    image: redis
    container_name: s1
    volumes:
      - /root/redis/s1:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]
  s2:
    image: redis
    container_name: s2
    volumes:
      - /root/redis/s2:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]
  s3:
    image: redis
    container_name: s3
    volumes:
      - /root/redis/s3:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]

2.sentinel配置 

 

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

3.执行命令 

docker compose down
docker-compose up -d

 4.启动哨兵

 停止r1(master),s3第一个发现r1客观下线,s3成为leader

 s3给r3发送send slaveof no one命令,r3成为master

 重启r1,s3发送convert  to slave给r1


http://www.kler.cn/a/589521.html

相关文章:

  • CML(Current Mode Logic)电平详解
  • MyBatis XMLMapperBuilder 是如何解析 SQL 映射文件的? 它读取了哪些信息?
  • docker安装rabbitmq
  • pyyaml_include 2.x 版本使用说明
  • Spring Cloud Gateway 生产级实践:高可用 API 网关架构与流量治理解析
  • Linux应用软件编程(多任务:进程间通信)
  • Excel VBA实现智能合并重复元器件数据(型号去重+数量累加)
  • VSCode C/C++ 环境搭建指南
  • 云原生服务网格:微服务通信的神经中枢革命
  • 【AI知识管理系统】(一)AI知识库工具测评
  • 美颜SDK x AIGC:如何用滤镜API结合AI生成技术打造创意视觉特效?
  • CI/CD构建与注意事项
  • gazebo报错:[Err] [InsertModelWidget.cc:302] Missing model.config for model
  • 【最佳实践】Go 状态模式
  • 蓝桥杯学习-11栈
  • Gone v2 Tracer 组件-给微服务提供统一的traceID
  • 深入解析Java面向对象三大特征之多态、final、抽象类与接口
  • CMake学习笔记(二):变量设值,源文件/文件查找
  • 网络安全运维应急响应与溯源分析实战案例
  • 【ES6】01-ECMAScript基本认识 + 变量常量 + 数据类型