【Redis】Redis Sentinel(哨兵)系统:自动故障恢复与高可用性配置全解

本文主要是介绍【Redis】Redis Sentinel(哨兵)系统:自动故障恢复与高可用性配置全解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • 哨兵 (Sentinel)
      • 基本概念
        • 主从复制的问题
        • ⼈⼯恢复主节点故障
        • 哨兵⾃动恢复主节点故障
      • 安装部署 (基于 docker)
        • 准备⼯作
    • 以下部分是独立于这一章节的
      • Docker安装
        • Server版本安装
          • CentOS安装
          • 实战经验
        • GUI版本安装(以windows 11为例)
          • 安装docker
    • 以上部分是独立于这一章节的
      • 重新选举
        • redis-master 宕机之后
        • redis-master 重启之后
      • 选举原理
        • 主观下线
        • 客观下线
        • 选举出哨兵的 leader
        • leader 挑选出合适的 slave 成为新的 master
      • 小结


哨兵 (Sentinel)

本章节相关操作不需要记忆!!! 后续⼯作中如果⽤到了能查到即可。

重点理解流程和原理。

Redis 的主从复制模式下,⼀旦主节点由于故障不能提供服务,需要⼈⼯进⾏主从切换,同时⼤量的客⼾端需要被通知切换到新的主节点上,对于上了⼀定规模的应⽤来说,这种⽅案是⽆法接受的,于是 Redis 从 2.8 开始提供了 Redis Sentinel(哨兵)加个来解决这个问题。本章主要内容如下:

  • Redis Sentinel 的概念
  • Redis Sentinel 的部署
  • Redis Sentinel 命令
  • Redis Sentinel 客⼾端
  • Redis Sentinel 实现原理

在复制章节中,我们说了给⼀个⽼师配了⼏个助教。如果⽼师有事请假了⼏天,助教⼜不能上课的话,学⽣们的学习进度就会受到影响。哨兵就是⽤来解决这个问题的。

基本概念

由于对 Redis 的许多概念都有不同的名词解释,所以在介绍 Redis Sentinel 之前,先对⼏个名词概念进⾏必要的说明,如表所⽰。

Redis Sentinel 相关名词解释

redis-sentinel 不负责存储数据,只是对其他的 redis-server 进程起到监控的作用

Redis Sentinel 是 Redis 的⾼可⽤实现⽅案,在实际的⽣产环境中,对提⾼整个系统的⾼可⽤是⾮常有帮助的,本节⾸先整体梳理主从复制模式下故障处理可能产⽣的问题,⽽后引出⾼可⽤的概念,最后重点分析 Redis Sentinel 的基本架构、优势,以及是如何实现⾼可⽤的。

主从复制的问题

Redis 的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作⽤:第⼀,作为主节点的⼀个备份,⼀旦主节点出了故障不可达的情况,从节点可以作为后备 “顶” 上来,并且保证数据尽量不丢失(主从复制表现为最终⼀致性)。第⼆,从节点可以分担主节点上的读压⼒,让主节点只承担写请求的处理,将所有的读请求负载均衡到各个从节点上。但是主从复制模式并不是万能的,它同样遗留下以下⼏个问题:

  1. 主节点发⽣故障时,进⾏主备切换的过程是复杂的,需要完全的⼈⼯参与,导致故障恢复时间⽆法保障。
  2. 主节点可以将读压⼒分散出去,但写压⼒/存储压⼒是⽆法被分担的,还是受到单机的限制。其中第⼀个问题是⾼可⽤问题,即 Redis 哨兵主要解决的问题。第⼆个问题是属于存储分布式的问题,留给 Redis 集群去解决,本章我们集中讨论第⼀个问题。
⼈⼯恢复主节点故障

Redis 主从复制模式下,主节点故障后需要进⾏的⼈⼯工作是⽐较繁琐的,我们在图中⼤致展⽰了整体过程。

Redis 主节点故障后需要进⾏的操作

实际开发中,对于服务器后端开发,监控程序,是非常重要的!

服务器,要求有比较高的可用性,24h运行。但服务器长期运行总有意外发生,也不能全靠人工监控,就用程序盯着服务器的运行状态,这个就是监控程序。这个往往还需要搭配“报警程序”。

  1. 运维⼈员通过监控系统,发现 Redis 主节点故障宕机。

    其实到第二步之前可能看看主节点是否能抢救恢复,不能再下一步

  2. 运维⼈员从所有节点中,选择⼀个(此处选择了 slave 1)执⾏ slaveof no one,使其作为新的主节点。

  3. 运维⼈员让剩余从节点(此处为 slave 2)执⾏ slaveof {newMasterIp} {newMasterPort} 从新主节点开始数据同步。

  4. 更新应⽤⽅(客户端)连接的主节点信息到 {newMasterIp} {newMasterPort}。

  5. 如果原来的主节点恢复,执⾏ slaveof {newMasterIp} {newMasterPort} 让其成为⼀个从节点。上述过程可以看到基本需要⼈⼯介⼊,⽆法被认为架构是⾼可⽤的。⽽这就是 Redis Sentinel 所要做的。

哨兵⾃动恢复主节点故障

当主节点出现故障时,Redis Sentinel 能⾃动完成故障发现和故障转移,并通知应⽤⽅,从⽽实现真正的⾼可⽤。

Redis Sentinel 是⼀个分布式架构,其中包含若⼲个 Sentinel 节点和 Redis 数据节点,每个Sentinel 节点会对数据节点和其余 Sentinel 节点进⾏监控,当它发现节点不可达时,会对节点做下线表⽰。如果下线的是主节点,它还会和其他的 Sentinel 节点进⾏ “协商”,当⼤多数 Sentinel 节点对主节点不可达这个结论达成共识之后,它们会在内部 “选举” 出⼀个领导节点来完成⾃动故障转移的⼯作,同时将这个变化实时通知给 Redis 应⽤⽅。整个过程是完全⾃动的,不需要⼈⼯介⼊。整体的架构如图所⽰。

这⾥的分布式架构是指:Redis 数据节点、Sentinel 节点集合、客⼾端分布在多个物理节点上,不要与后边章节介绍的 Redis Cluster 分布式混淆。

Redis Sentinel 架构

这里提供了三个单独的 redis sentinel 进程,并且这三个哨兵进程就会监控现有的 redis master 和 slave。

监控:这些进程之间会建立 tcp 长连接,通过这样的长连接,定期发送心跳包

Redis Sentinel 相⽐于主从复制模式是多了若⼲(建议保持奇数)Sentinel 节点⽤于实现监控数据节点,哨兵节点会定期监控所有节点(包含数据节点和其他哨兵节点)。针对主节点故障的情况,故障转移流程⼤致如下:

  1. 主节点故障,从节点同步连接中断,主从复制停⽌。(从节点挂了无所谓)
  2. 哨兵节点通过定期监控发现主节点出现故障。哨兵节点与其他哨兵节点进⾏协商,达成多数认同主节点故障的共识。这步主要是防⽌该情况:出故障的不是主节点,⽽是发现故障的哨兵节点,该情况经常发⽣于哨兵节点的⽹络被孤⽴的场景下。
  3. 哨兵节点之间使⽤ Raft 算法选举出⼀个领导⻆⾊,由该节点负责后续的故障转移⼯作。
  4. 哨兵领导者开始执⾏故障转移:从节点中选择⼀个作为新主节点;让其他从节点同步新主节点;通知应⽤层(客户端程序)转移到新主节点。

通过上⾯的介绍,可以看出 Redis Sentinel 具有以下⼏个功能:

  • 监控:Sentinel 节点会定期检测 Redis 数据节点、其余哨兵节点是否可达。
  • 自动故障转移:实现从节点晋升(promotion)为主节点并维护后续正确的主从关系。
  • 通知:Sentinel 节点会将故障转移的结果通知给应⽤⽅。

redis 哨兵节点只有一个也是可以的,只是:

  1. 如果只有一个,自身也是很容易出问题的,如果这个哨兵节点挂了,后续 redis 节点也挂了,就无法自动恢复
  2. 出现误判的概率提高了,毕竟网络传输是容易出现抖动、延迟、丢包之类的,这单个哨兵节点出问题,影响就大了

基本原则:在分布式系统中,应该避免使用“单点”。

哨兵节点最好搞奇数个,最少是3个,原因:

如果哨兵节点数目为偶数,可能出现两个相等大小的哨兵组认为自己拥有决策权的情况,从而导致系统不能一致地决定哪个Redis实例应该是主节点。这种情况下,两个哨兵组可能会分别选举出不同的主节点,造成数据不一致和应用错误。

安装部署 (基于 docker)

准备⼯作

1)安装 docker 和 docker-compose

以下部分是独立于这一章节的

以下内容在第58到64节

Docker安装

实战目的

掌握如何安装docker

各版本平台⽀持情况

  • Server版本

  • 桌面版本

Server版本安装
CentOS安装

安装依赖

  1. ⽀持的操作系统
 CentOS 7CentOS 8 (stream)CentOS 9 (stream)
  1. ⽀持的CPU
 ARM/X86_64

安装Docker

  1. 确认操作系统
CentOS Linux release 7.9.2009 (Core)
Derived from Red Hat Enterprise Linux 7.9 (Source)
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"CentOS Linux release 7.9.2009 (Core)
CentOS Linux release 7.9.2009 (Core)
cpe:/o:centos:centos:7
  1. 确认CPU架构
[root@centos1 ~]# uname -a
[Linux centos1 3.10.0-1160.71.1.el7.x86_64 #1 SMP Tue Jun 28 15:37:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
  1. 卸载旧版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
  1. 卸载历史版本
# 删除机器上的包
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras# 执行卸载
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd# 这个是老师修改后的目录,根据实际情况设置
sudo rm -rf /data/var/lib/docker
sudo rm -rf /etc/docker/daemon.json
  1. 配置仓库
[root@centos1 ~]# ll /etc/yum.repos.d/
total 40
-rw-r--r--. 1 root root 1664 Nov 23 2020 CentOS-Base.repo
-rw-r--r--. 1 root root 1309 Nov 23 2020 CentOS-CR.repo
-rw-r--r--. 1 root root 649 Nov 23 2020 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 314 Nov 23 2020 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 630 Nov 23 2020 CentOS-Media.repo
-rw-r--r--. 1 root root 1331 Nov 23 2020 CentOS-Sources.repo
-rw-r--r--. 1 root root 8515 Nov 23 2020 CentOS-Vault.repo
-rw-r--r--. 1 root root 616 Nov 23 2020 CentOS-x86_64-kernel.repo[root@centos1 ~]# sudo yum install -y yum-utils[root@centos1 ~]# sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Loaded plugins: fastestmirror
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
repo saved to /etc/yum.repos.d/docker-ce.repo[root@centos1 ~]# ll /etc/yum.repos.d/
total 44
-rw-r--r--. 1 root root 1664 Nov 23 2020 CentOS-Base.repo
-rw-r--r--. 1 root root 1309 Nov 23 2020 CentOS-CR.repo
-rw-r--r--. 1 root root 649 Nov 23 2020 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 314 Nov 23 2020 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 630 Nov 23 2020 CentOS-Media.repo
-rw-r--r--. 1 root root 1331 Nov 23 2020 CentOS-Sources.repo
-rw-r--r--. 1 root root 8515 Nov 23 2020 CentOS-Vault.repo
-rw-r--r--. 1 root root 616 Nov 23 2020 CentOS-x86_64-kernel.repo
-rw-r--r--. 1 root root 1919 Apr 5 07:45 docker-ce.repo# 配置使⽤国内源
[root@centos1 yum.repos.d]# sed -i 's@//download.docker.com@//mirrors.ustc.edu.cn/docker-ce@g' /etc/yum.repos.d/docker-ce.repo
  1. 安装最新版本
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin 
docker-compose-plugin
  1. 启动docker
#配置加载
sudo systemctl daemon-reload
#启动服务
sudo systemctl start docker
#开启启动
sudo systemctl enable docker
#查看服务状态
sudo systemctl status docker
  1. 检查安装结果查看版本
[root@centos1 ~]# docker version
Client:Docker Engine - CommunityVersion:           23.0.3API version:       1.42Go version:        go1.19.7Git commit:        3e7cbfdBuilt:             Tue Apr 4 22:04:18 2023OS/Arch:           linux/amd64Context:           defaultServer:Docker Engine - CommunityVersion:          23.0.3API version:      1.42 (minimum version 1.12)Go version:       go1.19.7Git commit:       59118bfBuilt:            Tue Apr 4 22:02:01 2023OS/Arch:          linux/amd64Experimental:     falsecontainerd:Version:          1.6.20GitCommit:        2806fc1057397dbaeefbea0e4e17bddfbd388f38runc:Version:          1.1.5GitCommit:        v1.1.5-0-gf19387adocker-init:Version:          0.19.0GitCommit:        de40ad0
  1. 更详细查看docker 信息
[root@centos1 ~]# docker info
Client:Context: defaultDebug Mode: falsePlugins:buildx: Docker Buildx (Docker Inc.)Version: v0.10.4Path: /usr/libexec/docker/cli-plugins/docker-buildxcompose: Docker Compose (Docker Inc.)Version: v2.17.2Path: /usr/libexec/docker/cli-plugins/docker-composeServer:Containers: 0Running: 0Paused: 0Stopped: 0Images: 0Server Version: 23.0.3Storage Driver: overlay2Backing Filesystem: xfsSupports d_type: trueUsing metacopy: falseNative Overlay Diff: trueuserxattr: falseLogging Driver: json-fileCgroup Driver: cgroupfsCgroup Version: 1Plugins:Volume: localNetwork: bridge host ipvlan macvlan null overlayLog: awslogs fluentd gcplogs gelf journald json-file local logentries splunk sSwarm: inactiveRuntimes: io.containerd.runc.v2 runcDefault Runtime: runcInit Binary: docker-initcontainerd version: 2806fc1057397dbaeefbea0e4e17bddfbd388f38runc version: v1.1.5-0-gf19387ainit version: de40ad0Security Options:seccompProfile: builtinKernel Version: 3.10.0-1160.71.1.el7.x86_64Operating System: CentOS Linux 7 (Core)OSType: linuxArchitecture: x86_64CPUs: 2Total Memory: 1.795GiBName: centos1ID: 0b3c79d5-957d-4d04-a856-ac15a2a09db2Docker Root Dir: /var/lib/dockerDebug Mode: falseRegistry: https://index.docker.io/v1/Experimental: falseInsecure Registries:127.0.0.0/8Live Restore Enabled: false
  1. 执⾏hello-world可以看到Hello from Docker,表⾯docker服务正常
[root@centos1 ~]# sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete 
Digest: sha256:ffb13da98453e0f04d33a6eee5bb8e46ee50d08ebe17735fc0779d0349e889e9
Status: Downloaded newer image for hello-world:latestHello from Docker!
This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/For more examples and ideas, visit:
https://docs.docker.com/get-started/
实战经验

Docker镜像源修改

对于使⽤ systemd 的系统(Ubuntu 16.04+、Debian 8+、CentOS 7), 在配置⽂件 /etc/docker/daemon.json 中加⼊:

{"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
}

重新启动 dockerd:

sudo systemctl restart docker

参考:https://mirrors.ustc.edu.cn/help/dockerhub.html

Docker⽬录修改

Docker 默认的安装⽬录为/var/lib/docker,这⾥⾯会存放很多很多镜像,所以我们在安装的时候需要考虑这个⽬录的空间,有三种解决⽅案。

(1)将/var/lib/docker挂载到⼀个⼤的磁盘,这种⼀般我们能控制挂载⽬录,像腾讯云这种云⼚商在安装K8s的节点的时候提供了挂载选项,可以直接挂载这个⽬录过去

(2)安装之前挂载⼀个⼤的磁盘,然后创建⼀个软链接到/var/lib/docker,这样就⾃动安装到我们空间⽐较⼤的磁盘了

(3)安装了docker,然后发现忘了配置这个⽬录,我们需要修改docker的配置⽂件

# 假定我们磁盘的⼤的⽬录为 /data
mkdir -p /data/var/lib/docker
# 编辑配置⽂件
vi /etc/docker/daemon.json
# 输⼊下⾯的 JSON
{"data-root": "/data/var/lib/docker"
}
# 加载配置
sudo systemctl daemon-reload
# 重启 Docker
sudo systemctl restart docker
# 查看 Docker 状态
sudo systemctl status docker

配置⽂件信息/etc/docker/daemon.json

修改前在/var/lib/docker下

修改后在/data/var/lib/docker下

GUI版本安装(以windows 11为例)

安装依赖

确定开启虚拟化

  • 输⼊win+i,然后输⼊启⽤或者关闭windows功能

  • 选择windows⼦系统和虚拟机平台

  • 重启电脑,完成系统设置

  • 安装WSL2

    • 以管理员权限运⾏ PowerShell

    • 查看版本,如果不是2需要更新到2

    wsl --status
    
    • PowerShell 运⾏命令更新wsl到最新版本
    PS C:\WINDOWS\system32> wsl --update
    
    • 设置wsl默认版本
    PS C:\WINDOWS\system32> wsl --set-default-version 2
    
  • 通过微软应⽤商店安装 Ubuntu 18.04.5

  • 启动安装好的 Ubunt18.04 ,如图表⽰启动成功
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match y
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: zsc
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.zsc@LAPTOP-DIG6CK4H:~$
安装docker
  • 点击链接下载Docker Desktop for Windows

这是个 .exe 应用程序

  • 下载好之后双击 Docker Desktop Installer.exe 开始安装
  • 点击 Docker Desktop 桌⾯快捷⽅式运⾏ Dokcer
  • 确认 Docker 安装成功, 在 PowerShell 中输⼊ docker version 命令确认Client和Server是否启动
PS C:\Users\zsc> docker version 
Client:Cloud integration: v1.0.29Version: 20.10.21API version: 1.41Go version: go1.18.7Git commit: baeda1fBuilt: Tue Oct 25 18:08:16 2022OS/Arch: windows/amd64Context: defaultExperimental: trueServer: Docker Desktop 4.15.0 (93002)Engine:Version: 20.10.21API version: 1.41 (minimum version 1.12)Go version: go1.18.7Git commit: 3056208Built: Tue Oct 25 18:00:19 2022OS/Arch: linux/amd64Experimental: falsecontainerd:Version: 1.6.10GitCommit: 770bd0108c32f3fb5c73ae1264f7e503fe7b2661runc:Version: 1.1.4GitCommit: v1.1.4-0-g5fd4c4ddocker-init:Version: 0.19.0GitCommit: de40ad0

以上部分是独立于这一章节的

docker-compose 的安装

# ubuntu
apt install docker-compose
# centos
yum install docker-compose

2)停⽌之前的 redis-server

# 停⽌ redis-server
service redis-server stop# 停⽌ redis-sentinel 如果已经有的话. 
service redis-sentinel stop

3)使⽤ docker 获取 redis 镜像

docker pull redis:5.0.9

编排 redis 主从节点

  1. 编写 docker-compose.yml

创建 /root/redis/docker-compose.yml , 同时 cd 到 yml 所在⽬录中.

注意:docker 中可以通过容器名字, 作为 ip 地址, 进⾏相互之间的访问

version: '3.7'
services:master:image: 'redis:5.0.9'container_name: redis-masterrestart: alwayscommand: redis-server --appendonly yesports:- 6379:6379slave1:image: 'redis:5.0.9'container_name: redis-slave1restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6380:6379slave2:image: 'redis:5.0.9'container_name: redis-slave2restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6381:6379

也可以直接在 windows 上使⽤ vscode 编辑好 yml, 然后在上传到 linux 上.

  1. 启动所有容器
docker-compose up -d

如果启动后发现前⾯的配置有误, 需要重新操作, 使⽤ docker-compose down 即可停⽌并删除刚才创建好的容器

  1. 查看运⾏⽇志
docker-compose logs

上述操作必须保证⼯作⽬录在 yml 的同级⽬录中, 才能⼯作.

  1. 验证

连接主节点

redis-cli -p 6379

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.22.0.3,port=6379,state=online,offset=348,lag=1
slave1:ip=172.22.0.4,port=6379,state=online,offset=348,lag=1
master_replid:a22196b425ab42ddfd222cc5a64d53acffeb3e63
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:348
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:348

连接从节点

redis-cli -p 6380

127.0.0.1:6380> info replication
# Replication
role: slave
master_host: redis-master
master_port: 6379
master_link_status: up
master_last_io_seconds_ago: 10
master_sync_in_progress: 0
slave_repl_offset: 446
slave_priority: 100
slave_read_only: 1
connected_slaves: 0
master_replid: a22196b425ab42ddfd222cc5a64d53acffeb3e63
master_replid2: 0000000000000000000000000000000000000000
master_repl_offset: 446
second_repl_offset: -1
repl_backlog_active: 1
repl_backlog_size: 1048576
repl_backlog_first_byte_offset: 1
repl_backlog_histlen: 446

redis-cli -p 6381

127.0.0.1:6381> info replication
# Replication
role: slave
master_host: redis-master
master_port: 6379
master_link_status: up
master_last_io_seconds_ago: 7
master_sync_in_progress: 0
slave_repl_offset: 516
slave_priority: 100
slave_read_only: 1
connected_slaves: 0
master_replid: a22196b425ab42ddfd222cc5a64d53acffeb3e63
master_replid2: 0000000000000000000000000000000000000000
master_repl_offset: 516
second_repl_offset: -1
repl_backlog_active: 1
repl_backlog_size: 1048576
repl_backlog_first_byte_offset: 1
repl_backlog_histlen: 516

编排 redis-sentinel 节点

也可以把 redis-sentinel 放到和上⾯的 redis 的同⼀个 yml 中进⾏容器编排. 此处分成两组, 主要是为了两⽅⾯:

  • 观察⽇志⽅便
  • 确保 redis 主从节点启动之后才启动 redis-sentinel. 如果先启动 redis-sentinel 的话, 可能触发额外的选举过程, 混淆视听. (不是说先启动哨兵不⾏, ⽽是观察的结果可能存在⼀定随机性)
  1. 编写 docker-compose.yml

创建 /root/redis-sentinel/docker-compose.yml , 同时 cd 到 yml 所在⽬录中.

注意: 每个⽬录中只能存在⼀个 docker-compose.yml ⽂件.

version: '3.7'
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379sentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379sentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379
networks:default:external:name: redis-data_default

也可以直接在 windows 上使⽤ vscode 编辑好 yml, 然后在上传到 linux 上.

  1. 创建配置⽂件

创建 sentinel1.conf sentinel2.conf sentinel3.conf . 三份⽂件的内容是完全相同的.

都放到 /root/redis-sentinel/ ⽬录中.

bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000

理解 sentinel monitor

sentinel monitor 主节点名 主节点ip 主节点端⼝ 法定票数
  • 主节点名, 这个是哨兵内部⾃⼰起的名字.
  • 主节点 ip, 部署 redis-master 的设备 ip. 此处由于是使⽤ docker, 可以直接写 docker 的容器名, 会被⾃动 DNS 成对应的容器 ip
  • 主节点端⼝, 不解释.
  • 法定票数, 哨兵需要判定主节点是否挂了. 但是有的时候可能因为特殊情况, ⽐如主节点仍然⼯作正常, 但是哨兵节点⾃⼰⽹络出问题了, ⽆法访问到主节点了. 此时就可能会使该哨兵节点认为主节点下线, 出现误判. 使⽤投票的⽅式来确定主节点是否真的挂了是更稳妥的做法. 需要多个哨兵都认为主节点挂了, 票数 >= 法定票数 之后, 才会真的认为主节点是挂了.

理解 sentinel down-after-milliseconds

  • 主节点和哨兵之间通过⼼跳包来进⾏沟通. 如果⼼跳包在指定的时间内还没回来, 就视为是节点出现故障.
  1. 启动所有容器
docker-compose up -d

如果启动后发现前⾯的配置有误, 需要重新操作, 使⽤ docker-compose down 即可停⽌并删除刚才创建好的容器.

  1. 查看运⾏⽇志
 docker-compose logs

上述操作必须保证⼯作⽬录在 yml 的同级⽬录中, 才能⼯作

可以看到, 哨兵节点已经通过主节点, 认识到了对应的从节点.

  1. 观察 redis-sentinel 的配置 rewrite

再次打开哨兵的配置⽂件, 发现⽂件内容已经被⾃动修改了

bind 0.0.0.0
port 26379
sentinel myid 4d2d562860b4cdd478e56494a01e5c787246b6aa
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
dir "/data"
sentinel monitor redis-master 172.22.0.4 6379 2
sentinel down-after-milliseconds redis-master 1000
sentinel config-epoch redis-master 1
sentinel leader-epoch redis-master 1
sentinel known-replica redis-master 172.22.0.2 6379
sentinel known-replica redis-master 172.22.0.3 6379
sentinel known-sentinel redis-master 172.22.0.7 26379 f718caed536d178f5ea6d1316d
sentinel known-sentinel redis-master 172.22.0.5 26379 2ab6de82279bb77f8397c309d3
sentinel current-epoch 1

# Generated by CONFIG REWRITE 这⾥的内容就是⾃动修改的.

对⽐这三份⽂件, 可以看到配置内容是存在差异的.

重新选举

redis-master 宕机之后

⼿动把 redis-master ⼲掉

docker stop redis-master

观察哨兵的⽇志

可以看到哨兵发现了主节点 sdown, 进⼀步的由于主节点宕机得票达到 3/2 , 达到法定得票, 于是 master 被判定为 odown.

  • 主观下线 (Subjectively Down, SDown):哨兵感知到主节点没⼼跳了。判定为主观下线
  • 客观下线 (Objectively Down, ODown):多个哨兵达成⼀致意⻅,才能认为 master 确实下线了

接下来, 哨兵们挑选出了⼀个新的 master. 在上图中, 是 172.22.0.4:6379 这个节点.

此时, 对于 Redis 来说仍然是可以正常使⽤的.

redis-master 重启之后

⼿动把 redis-master 启动起来

docker start redis-master

观察哨兵⽇志

可以看到刚才新启动的 redis-master 被当成了 slave,也就是失去了最开始主节点的身份,成为了从节点

使⽤ redis-cli 也可以进⼀步的验证这⼀点

127.0.0.1:6379> info replication
# Replication
role: slave
master_host: 172.22.0.4
master_port: 6379
master_link_status: up
master_last_io_seconds_ago: 0
master_sync_in_progress: 0
slave_repl_offset: 324475
slave_priority: 100
slave_read_only: 1
connected_slaves: 0
master_replid: ececc285a2892fba157318c77ebe1409f9c2254e
master_replid2: 0000000000000000000000000000000000000000
master_repl_offset: 324475
second_repl_offset: -1
repl_backlog_active: 1
repl_backlog_size: 1048576
repl_backlog_first_byte_offset: 318295
repl_backlog_histlen: 6181

结论

  • Redis 主节点如果宕机,哨兵会把其中的⼀个从节点,提拔成主节点
  • 当之前的 Redis 主节点重启之后,这个主节点被加⼊到哨兵的监控中,但是只会被作为从节点使⽤

选举原理

假定当前环境如上⽅介绍, 三个哨兵(sentenal1, sentenal2, sentenal3), ⼀个主节点(redis-master), 两个从节点(redis-slave1, redis-slave2).

当主节点出现故障, 就会触发重新⼀系列过程.

主观下线

当 redis-master 宕机,此时 redis-master 和三个哨兵之间的⼼跳包就没有了。此时,站在三个哨兵的⻆度来看,redis-master 出现严重故障。因此三个哨兵均会把 redis-master 判定为主观下线 (SDown)

客观下线

此时,哨兵 sentenal1,sentenal2,sentenal3 均会对主节点故障这件事情进⾏投票。当故障得票数 >= 配置的法定票数之后,

sentinel monitor redis-master 172.22.0.4 6379 2

在这个地⽅配置的 2 , 即为法定票数

此时意味着 redis-master 故障这个事情被做实了。此时触发客观下线 (ODown)

选举出哨兵的 leader

接下来需要哨兵把剩余的 slave 中挑选出⼀个新的 master。这个⼯作不需要所有的哨兵都参与。只需要选出个代表 (称为 leader),由 leader 负责进⾏ slave 升级到 master 的提拔过程

这个选举的过程涉及到 Raft 算法

假定⼀共三个哨兵节点,S1,S2,S3

  1. 每个哨兵节点都给其他所有哨兵节点,发起⼀个 “拉票请求”。(S1 -> S2, S1 -> S3, S2 -> S1, S2 -> S3, S3 -> S1, S3 -> S2)
  2. 收到拉票请求的节点,会回复⼀个 “投票响应”。响应的结果有两种可能,投 or 不投。

⽐如 S1 给 S2 发了个投票请求,S2 就会给 S1 返回投票响应。

到底 S2 是否要投 S1 呢?取决于 S2 是否给别⼈投过票了。(每个哨兵只有⼀票)

如果 S2 没有给别⼈投过票,换⽽⾔之,S1 是第⼀个向 S2 拉票的,那么 S2 就会投 S1,否则则不投。

  1. ⼀轮投票完成之后,发现得票超过半数的节点,⾃动成为 leader

如果出现平票的情况 (S1 投 S2, S2 投 S3, S3 投 S1, 每⼈⼀票), 就重新再投⼀次即可.

这也是为啥建议哨兵节点设置成奇数个的原因. 如果是偶数个, 则增⼤了平票的概率, 带来不必要的开销.

  1. leader 节点负责挑选⼀个 slave 成为新的 master。当其他的 sentenal 发现新的 master 出现了,就说明选举结束了。

简⽽⾔之,Raft 算法的核⼼就是 “先下⼿为强”。谁率先发出了拉票请求,谁就有更⼤的概率成为 leader。

这⾥的决定因素成了 “⽹络延时”,⽹络延时本⾝就带有⼀定随机性。

具体选出的哪个节点是 leader,这个不重要,重要的是能选出⼀个节点即可。

假定 鹏哥,杭哥,蛋哥,是三个哨兵节点

汤⽼湿是主节点,若⼲助教⽼师是从节点

有⼀天,汤⽼湿请假了,需要安排⼀个助教⽼师,代替汤⽼湿上课。那么谁负责去执⾏ “提拔助教” 这个事情呢?显然这个事情不需要 鹏哥,杭哥,蛋哥 同时⼲预。

此时⽐如蛋哥先说,“要不我去负责安排这个事情?”,鹏哥和杭哥⼀致说 “好”,此时蛋哥得票超过半数,蛋哥就成为这次操作的 leader 节点。

leader 挑选出合适的 slave 成为新的 master

挑选规则:

  1. ⽐较优先级。优先级⾼(数值⼩的)的上位。优先级是配置⽂件中的配置项( slave-priority 或者 replica-priority )

  2. ⽐较 replication offset 谁复制的数据多,⾼的上位

  3. ⽐较 run id,谁的 id ⼩,谁上位。(这个是 redis 节点启动的时候随机生成的一串数字,大小是随机的)

蛋哥按照什么标准来提拔助教呢?三个标准~

  1. ⽐较优先级:某个助教是杨校⻓钦定的,那么钦定的⼈直接上位

  2. ⽐较 replication offset:某个助教备课备的最快,⼀共 20 个课件已经备完 18 个了,别的助教才备了 5, 6 个. 那么这个备课快的就直接上位.

  3. ⽐较 run id:⼤家没有钦定,备课速度也⼀样,这个时候就看哪个助教的名字起的好听⽐如蛋哥觉得,嗯,这个名字我喜欢,就你了

当某个 slave 节点被指定为 master 之后,

  1. leader 指定该节点执⾏ slave no one,成为 master
  2. leader 指定剩余的 slave 节点,都依附于这个新 master

小结

上述过程,都是 “⽆⼈值守”,Redis ⾃动完成的。这样做就解决了主节点宕机之后需要⼈⼯⼲预的问题,提⾼了系统的稳定性和可⽤性。

⼀些注意事项:

  • 哨兵节点不能只有⼀个。否则哨兵节点挂了也会影响系统可⽤性。
  • 哨兵节点最好是奇数个(一般三个够了)。⽅便选举 leader,得票更容易超过半数。
  • 哨兵节点不负责存储数据(哨兵节点就可以使用一些配置不高的机器来配置,但不能搞一个机器部署三个哨兵,这样没有意义,一崩就是三个都崩了)。仍然是 redis 主从节点负责存储。
  • 哨兵 + 主从复制解决的问题是 “提⾼可⽤性”,不能解决 “数据极端情况下写丢失” 的问题。
  • 哨兵 + 主从复制不能提⾼数据的存储容量。当我们需要存的数据接近或者超过机器的物理内存,这样的结构就难以胜任了。

为了能存储更多的数据,就引⼊了集群

这篇关于【Redis】Redis Sentinel(哨兵)系统:自动故障恢复与高可用性配置全解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145425

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C