• 哨兵模式(sentinel)


    为什么需要哨兵模式

    redis的主从复制模式能够缓解“读压力”,但是存在两个明显问题。

    1. 主节点发生故障,进行主节点切换的过程比较复杂,需要人工参与,导致故障恢复时间无法保障
    2. 主节点通过主从复制模式将读压力分散出去,但是写压力/存储压力无法被分散,受单机的限制

    其中第一个问题是高可用问题,可以通过redis哨兵模式解决。第二个问题是存储分布式问题,要通过redis集群解决。本篇只讨论第一个问题。

    哨兵模式

    通过人工的方式解决主节点故障,不靠谱。而哨兵模式可以自动解决主节点故障问题。
    哨兵机制是通过独立的进程实现的,即redis sentinel,和redis-server是不同的进程。redis sertinel不负责存储数据,只是对redis-server进程起到监控效果。
    并且哨兵节点,也会搞一个集合。防止单个节点发生故障,而且单个节点容易出现误判(网络传输数据容易出现抖动,延迟,丢包,会误认为主节点发生故障)

    人工恢复主节点故障

    1. image.png

    服务器需要7*24运行,为了保证服务器能够长期运行,程序员会写一个监控程序来监控服务器的运行状态。当服务器出现问题,就会通知程序员,程序员会先看看主节点能不能修复

    1. image.png

    如果主节点挂的原因不好定位,或者原因知道,但是短时间难以解决就需要挑一个从节点,设置为新的主节点。

    1. image.png
    1. 把选中的从节点通过slaveof no one,脱离原来的主节点
      2)把其他从节点,修改slaveof的主节点ip和port,连上新的主节点。
    1. image.png

    修改客服端的配置,让客服端连接上新的主节点

    1. image.png

    当之前挂的主节点修复完成后,就可以作为一个新的从节点,挂到这组机器中

    哨兵自动恢复主节点故障

    image.png
    哨兵集合中有多个单独的redis sentinel进程,这三个哨兵进程会监控现有的redis masterslave.

    监控:sentinel进程会和主从节点建立tcp长连接,定期发送心跳包。如果发送ping,没有返回pong意味着这个主机挂了。

    1. 如果从节点挂了,问题不太严重,如果主节点挂了,哨兵就会发挥作用。

    一个哨兵节点发现主节点挂了,还不够,需要多个哨兵节点共同认同这件事情,防止出现误判

    1. 确认主节点挂了,这些哨兵节点就会推举出一个leader,由这个leader负责从现有的从节点中,挑选一个作为新的主节点
    2. 挑选出新的主节点后,哨兵节点会自动控制被选中的节点,执行slaveof no one并且控制其他从节点,修改slaveof到新的主节点上
    3. 哨兵节点自动通知客服端程序现在主节点是哪个,并且后续客服端再进行写操作,就会针对新的主节点进行操作

    image.png

    redis哨兵的核心功能:

    1. 监控:sentinel节点会定期检测redis数据节点
    2. 故障转移:实现从节点晋升为主节点并维护后续正确的主从关系
    3. 通知:sentinel节点会将故障转移的结果通知给应用方

    安装部署(基于docker)

    咱们要安装上图哨兵模式中的6个节点,是需要6个不同的服务器。但是我只有1个服务器,因此只能在一个云服务器下安装。如果我们按照主从结构配置的方式进行部署,容易出现端口/配置文件/数据文件各种问题,比较繁琐,也和在不同主机上部署存在较大差异。因此我们采docker部署。

    docker可以认为是一个“轻量级”虚拟机,起到虚拟机这样隔离环境的效果,但是又不吃很多硬件资源。

    docker安装

    1. 确认操作系统:centos7/8/9,咱们采用centos7

    使用cat /etc/*release*命令查看linux版本是否符合
    image.png

    1. 确认cpu架构: ARM/x86_64

    使用uname -a命令查看当前的cpu架构
    image.png

    1. 查看是否下载过docker

    使用docker命令,或docker version命令
    image.png
    我的linux中并没有安装过

    如果存在docker

    1. 卸载旧版本
      :::tips
      yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
      :::
    2. 卸载历史版本
      :::tips
      #删除机器上的包
      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 4.
      sudo rm -rf /var/lib/containerd
      :::
    1. 配置仓库
      :::tips
      sudo yum install -y yum-utils
      sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
      #配置国内源
      sed -i ‘s@//download.docker.com@//mirrors.ustc.edu.cn/docker-ce@g’ /etc/yum.repos.d/docker-ce.repo
      :::

    2. 安装最新版本
      :::tips
      yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
      :::

    3. 启动docker
      :::tips
      #加载配置
      systemctl daemon-reload
      #查看服务状态
      systemctl status docker
      #启动服务
      systemctl start docker
      #开机自启动
      systemctl enable docker
      :::

    4. 检查安装结果查看版本
      :::tips
      docker version
      :::

    5. 更详细的查看docker信息
      :::tips
      docker info
      :::

    6. 执行hello-world看到Hello from Docker,表明docker服务正常
      :::tips
      docker run hello-world
      :::

    7. 配置docker国内的镜像源,加速下载镜像
      :::tips
      mkdir /etc/docker
      cd /etc/docker
      vim daemon.json
      {
      “registry-mirrors”: [“http://hub-mirror.c.163.com”,“https://registry.docker-cn.com”,“https://docker.mirrors.ustc.edu.cn”]
      }
      #重新加载配置
      systemctl daemon-reload
      #重启docker
      systemctl restart docker
      docker info
      image.png
      :::

    8. 修改docker目录

    docker中有很多镜像,为了防止磁盘不够用,需要将他挂载到大磁盘的目录上
    :::tips
    #假定我们大磁盘的目录为 /data ,
    mkdir /data/var/lib/docker -p
    cd /etc/docker/
    vim daemon.json
    #输入下面的json
    {
    “data-root”: “/data/var/lib/docker”
    }
    #重新加载配置
    systemctl daemon-reload
    #重启docker
    systemctl restart docker
    #查看docker信息
    docker info
    image.png
    :::

    安装redis

    1. 安装docker-compose:docker中可以安装很多容器,容器之间存在依赖关系,因此引入docker-compose来帮助我们编排这些容器
      :::tips
      yum install docker-compose
      :::

    2. 停止redis进程,防止后续出现干扰
      :::tips
      service redis-server stop
      ps aux | grep redis
      通过kill -9杀死其他端口的redis进程
      :::

    3. 使用docker获取redis镜像
      :::tips
      docker pull redis:5.0.9
      :::

    docker中的镜像类似于”可执行程序“,容器类似于”进程“。docker pull使用docker从中央仓库拉取镜像。拉取到的镜像包含一个精简的Linux操作系统并且上面安装有redis,只要基于这个镜像创建一个容器跑起来,此时redis服务器就搭建好了
    image.png

    1. 使用docker-compose编排redis-server节点

    咱们需要安装3个redis-server和3个redis哨兵节点,每个redis server或者redis sentinel都是一个单独的容器,使用docker-compose方便安装。
    具体是通过一个yml格式的配置文件,把要创建那些容器,每个容器运行的各种参数,描述清楚即可。后续通过一个命令,就能批量的启动/停止这些容器。
    咱们通过两个yml文件来配置,一个yml文件配置redis server节点,一个yml文件配置redis的哨兵节点。

    其实也可以只使用1个yml文件,但是如果6个容器同时启动,可能哨兵节点先启动,数据节点后启动,哨兵就会误认为数据节点挂了。虽然影响不大,但是会影响观察执行日志的过程。

    :::tips
    mkdir redis
    cd redis
    mkdir redis-data
    mkdir redis-sentinel
    cd redis-data/
    vim docker-compose.yml
    :::

    version: '3.3'
    services:
     master:
       image: 'redis:5.0.9'
       container_name: redis-master
       restart: always
       command: redis-server --appendonly yes
       ports:
         - 6379:6379
     slave1:
       image: 'redis:5.0.9'
       container_name: redis-slave1
       restart: always
       command: redis-server --appendonly yes --slaveof redis-master 6379
       ports:
         - 6380:6379
     slave2:
       image: 'redis:5.0.9'
       container_name: redis-slave2
       restart: always
       command: redis-server --appendonly yes --slaveof redis-master 6379
       ports:
         - 6381:6379
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    image.png

    1. 启动所有redis-server容器
      :::tips
      docker-compose up -d
      :::

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

    1. 可以通过docker ps -a查看搭建好的redis节点

    image.png

    1. 编排redis-sentinel节点
      1. 编写docker-compose.yml

    image.png

    version: '3.3'
    services:
      sentinel1:
        image: 'redis:5.0.9'
        container_name: redis-sentinel-1
        restart: always
        command: redis-sentinel /etc/redis/sentinel.conf
        volumes:
          - ./sentinel1.conf:/etc/redis/sentinel.conf
        ports:
          - 26379:26379
      sentinel2:
        image: 'redis:5.0.9'
        container_name: redis-sentinel-2
        restart: always
        command: redis-sentinel /etc/redis/sentinel.conf
        volumes:
          - ./sentinel2.conf:/etc/redis/sentinel.conf
        ports:
          - 26380:26379
      sentinel3:
       image: 'redis:5.0.9'
       container_name: redis-sentinel-3
       restart: always
       command: redis-sentinel /etc/redis/sentinel.conf
       volumes:
         - ./sentinel3.conf:/etc/redis/sentinel.conf
       ports:
         - 26381:26379
    networks:
    	default:
      	external:
      		name: redisdata_default
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    image.png

    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
    
    • 1
    • 2
    • 3
    • 4

    image.png
    image.png

    1. 启动redis-sentinel
      :::tips
      docker-compose up -d
      :::

    2. 观察redis-sentinel的配置的rewrite

    启动完以后,再次打开哨兵的配置文件,发现文件内容已经被自动修改
    image.png

    模拟主节点宕机情况

    1. 手动将redis-master干掉
      :::tips
      docker stop redis-master
      :::

    2. 观察哨兵日志
      :::tips
      docker-compose logs
      :::
      image.png

    sdown: 主观下线,本哨兵节点,认为该主节点挂了
    odown:客观下线,其他节点也认为主节点挂了,票数超过一半

    1. 查看redis-server

    image.png
    image.png

    1. 重新连上原来的主节点
      :::tips
      docker start redis-master
      :::
      image.png

    哨兵选举主节点流程

    1. 主观下线:哨兵节点通过心跳包,判定redis服务器是否正常工作,如果超过心跳包时间,说明服务器挂了。(此时可能是由于网络抖动造成,因此只能是单方面认为redis节点挂了)
    2. 客观下线:多个redis节点认为主节点挂了(投票超过法定票数)
    3. 在多个哨兵节点,选出一个leader节点,由这个leader节点负责选一个从节点作为新的主节点
      1. 3号哨兵第一个发现主节点掉线,立即投自己一票,推荐自己成为leader,并告诉1和2号哨兵节点(类似于拉票)

    image.png

    1. 1号哨兵节点给哨兵3投票

    image.png

    1. 2号哨兵节点给哨兵3投票

    image.png

    谁网络延迟小,谁是leader

    1. 选举完leader,leader需要挑选一个从节点,作为主节点
      1. 优先级:每个redis数据节点,在配置文件中有一个优先级设置slave-priority,选择优先级高的slave节点
      2. offset:offset是从节点从主节点同步数据的进度,数值越大,说明从节点的数据和主节点越接近。选择offset大的从节点
      3. runid:当上面都一样时,选择谁都没差别了。runid是redis节点启动时随机生成的一串数字,根据runid大小选择

    注意事项

    1. 哨兵节点不能只有一个,否则哨兵节点挂了容易影响系统可用性
    2. 哨兵节点最好是奇数个,方便选举leader,得票数更容易过半数
    3. 哨兵节点不存储数据,仍然是redis主节点负责存储
    4. 主从+哨兵解决的是“可用性”问题,不能解决“数据极端情况下写丢失”问题
    5. 主从+哨兵不能提高数据的存储容量,当我们需要存的数据接近或超过机器的物理内存,这样的结构很难胜任,需要引入集群
  • 相关阅读:
    高可用集群 keepalived
    GFS分布式文件系统&实验
    superset连接Apache Spark SQL(hive)过程中的各种报错解决
    Vue学习:分析hello案例
    用Unity同时开发【微信小游戏】【安卓】【IOS】游戏#5.5.2 组件拓展
    天然气销售企业人工智能技术应用研究
    012--python之文件操作
    Linux环境基础开发工具使用
    C++ 基础与深度分析 Chapter11 类与面向对象编程(析构与复制成员函数、字面值类、成员指针与bind交互)
    【k8s】Kubernetes 原理剖析与实战应用(更新中)
  • 原文地址:https://blog.csdn.net/weixin_61427900/article/details/132981661