2021-05-31

本文详细介绍了如何使用Docker和docker-compose搭建Redis主从复制及哨兵系统,包括配置文件设置、启动命令以及哨兵的监控和故障转移功能。通过这种方式,可以在读高并发场景下确保数据的高可用性和故障切换的自动化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Docker搭建Redis哨兵

Replication

  • Redis 的Replication功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(Master),而通过复制创建出来的复制品则为从服务器(Slave)。 只要主从服务器之间的网络连接正常,主服务器就会将写入自己的数据同步更新给从服务器,从而保证主从服务器的数据相同。
  • 在这种模式下,数据的复制是单向的,只能由主节点到从节点,简单理解就是从节点只支持读操作,不允许写操作。主要是读高并发的场景下用主从架构。如果主节点执行过save命令,那么在主节点挂掉的情况下也可以在从节点中读取内容。
  • 当主数据库遇到异常中断服务后,开发者需要通过手动的方式选择一个从数据库来升格为主数据库,以使得系统能够继续提供服务。然而整个过程相对麻烦且需要人工介入,难以实现自动化。

使用docker-compose搭建Replication

使用一主两从的结构,考虑到后续加入哨兵,推荐使用docker network 的host方式,以方便客户端访问,主服务器使用6379端口,从服务器分别使用6380和6381端口,结构如下图:
RedisReplication

  1. 下载配置文件:官方配置文件
    主要设置以下几项:
#注释掉,限制redis只能本地访问
bind 127.0.0.1 
#默认yes,限制为本地访问, 改为no
protected-mode no 
#访问端口,默认6379
port 6379
#输入本地redis数据库存放文件夹(可选)
dir  ./ 
#以AOF方式redis持久化(可选)
appendonly yes 
#访问密码,建议设置
requirepass ****

因为每个Redis实例对外的端口都不一样,因此为每一个Redis实例都配备一个redis.conf,除port外其余都相同即可。

  1. 编写docker-compose.yml
version: "3.7"
services:
  redis_master:
    image: redis
    container_name: redis_master
    network_mode: "host"
    volumes:
      - ./config/redis.conf:/etc/redis/redis.conf
      - ./data:/data
    command: redis-server /etc/redis/redis.conf --requirepass YOURPASS --appendonly no
  redis_slave1:
    image: redis
    container_name: redis_slave1
    network_mode: "host"
    volumes:
      - ./config/redis2.conf:/etc/redis/redis.conf
      - ./data:/data
    command: redis-server /etc/redis/redis.conf --slaveof 宿主机IP 6379 --masterauth YOURPASS --appendonly yes
  redis_slave2:
    image: redis
    container_name: redis_slave2
    network_mode: "host"
    volumes:
      - ./config/redis3.conf:/etc/redis/redis.conf
      - ./data:/data
    command: redis-server /etc/redis/redis.conf --slaveof 宿主机IP 6379 --masterauth YOURPASS --appendonly yes

  1. 启动docker容器
    在docker-compose.yml文件目录下执行
docker-compose up -d

查看Replication信息

docker exec -it redis_master redis-cli

如下显示则配置Replication成功

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=********,port=6380,state=online,offset=14,lag=1
slave1:ip=********,port=6381,state=online,offset=14,lag=1
master_failover_state:no-failover
master_replid:940d1ccd310a93815a992766418eafaf3949f484
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28

哨兵 Sentinel

哨兵的作用就是监控Redis系统的运行状况,它的功能包括以下两个:

(1)监控主数据库和从数据库是否正常运行。
(2)主数据库出现故障时自动将从数据库转换为主数据库。

一个主从系统中可以有多个哨兵同时监视整个系统,哨兵之间也会互相监视。
哨兵启动后,会与要监控的主数据库建立两条连接,这两个连接的建立方式与普通的Redis客户端无异。其中一条连接用来订阅该主数据的__sentinel__:hello频道以获取其他同样监控该数据库的哨兵节点的信息,另外哨兵也需要定期向主数据库发送 INFO 等命令来获取主数据库本身的信息,因为4.4.4节介绍过当客户端的连接进入订阅模式时就不能再执行其他命令了,所以这时哨兵会使用另外一条连接来发送这些命令。
和主数据库的连接建立完成后,哨兵会定时执行下面3个操作。

  1. 每10秒哨兵会向主数据库和从数据库发送INFO命令。使得哨兵可以获得当前数据库的相关信息(包括运行ID、复制信息等)从而实现新节点的自动发现.
  2. 每 2 秒哨兵会向主数据库和从数据库的__sentinel__:hello 频道发送自己的信息。与同样监控该数据库的哨兵分享自己的信息。发送的消息内容为:<哨兵的地址>, <哨兵的端口>, <哨兵的运行 ID>, <哨兵的配臵版本>, <主数据库的名字>, <主数据库的地址>, <主数据库的端口>, <主数据库的配臵版本>
  3. 每1秒哨兵会向主数据库、从数据库和其他哨兵节点发送PING命令。

当超过down-after-milliseconds选项指定时间后,如果被PING的数据库或节点仍然未进行回复,则哨兵认为其主观下线(subjectively down)。主观下线表示从当前的哨兵进程看来,该节点已经下线。如果该节点是主数据库,则哨兵会进一步判断是否需要对其进行故障恢复:哨兵发送 SENTINEL is-master-down-by -addr命令询问其他哨兵节点以了解他们是否也认为该主数据库主观下线,如果达到指定数量时,哨兵会认为其客观下线(objectivelydown),并选举领头的哨兵节点对主从系统发起故障恢复。这个指定数量即为前文介绍的quorum参数。

使用docker-compose搭建哨兵

这一步将设置三个哨兵,每个哨兵监测只监测主节点,结构如下图:
RedisSentinel

  1. 编写配置文件sentinel.conf
port 26379
dir /tmp

sentinel monitor mymaster IP 6379 2
sentinel auth-pass mymaster 6379091170 
sentinel down-after-milliseconds mymaster 10000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000  
sentinel deny-scripts-reconfig yes

三个哨兵节点的配置相同
2. 编写docker-compose文件

version: '3.7'
services:
  sentinel1:
    image: redis      
    container_name: redis_sentinel_1
    networks:
      - redis
    ports:
    - "26379:26379"
    volumes:
      - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf
    # redis sentinel会修改config文件,修改方式推测是创建新的文件进行替代,如果只是用volumes方式挂载的话会出现Device or resource busy,无法修改
    command: 
      - sh 
      - -c 
      - |
          mkdir /etc/redis/
          cp /usr/local/etc/redis/sentinel.conf /etc/redis/sentinel.conf
          redis-sentinel /etc/redis/sentinel.conf


  sentinel2:
    image: redis      
    container_name: redis_sentinel_2
    networks:
      - redis
    ports:
    - "26380:26379"
    command: 
      - sh 
      - -c 
      - |
          mkdir /etc/redis/
          cp /usr/local/etc/redis/sentinel.conf /etc/redis/sentinel.conf
          redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./config/sentinel2.conf:/usr/local/etc/redis/sentinel.conf

  sentinel3:
    image: redis      
    container_name: redis_sentinel_3
    networks:
      - redis
    ports:
    - "26381:26379"
    command: 
      - sh 
      - -c 
      - |
          mkdir /etc/redis/
          cp /usr/local/etc/redis/sentinel.conf /etc/redis/sentinel.conf
          redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./config/sentinel3.conf:/usr/local/etc/redis/sentinel.conf

networks:
  redis:
    driver: bridge
    name: redis

  1. 启动容器
docker-compose -f redis-sentinel.yml up -d

查看结果:


root@bfaa11ab2fda:/data# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=IP:6379,slaves=2,sentinels=3

  1. 验证
    关闭主节点所在容器:
docker stop redis_master

进入哨兵节点查看:

127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=IP:6381,slaves=2,sentinels=3

成功将从节点升级为主节点。
5. 原理
可以进入主节点,查看__sentinel__:hello的内容:

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "172.23.0.4,26379,a8a10d765844d75e02a01e615465b014fe24f369,0,mymaster,IP,6381,0"
1) "message"
2) "__sentinel__:hello"
3) "172.23.0.3,26379,c083b8f532a31f60202dd99dae8f2a38e12e6b0e,0,mymaster,IP,6381,0"
1) "message"
2) "__sentinel__:hello"
3) "172.23.0.2,26379,5171cc8406e46aea8ef8ac8be2513bb6a3ed5f6a,0,mymaster,IP,6381,0"

可以看到,发送的消息内容为:<哨兵的地址>, <哨兵的端口>, <哨兵的运行 ID>, <哨兵的配臵版本>, <主数据库的名字>, <主数据库的地址>, <主数据库的端口>, <主数据库的配臵版本>。
进入哨兵节点,查看配置文件sentinel.conf:


root@bfaa11ab2fda:/data# cat /etc/redis/sentinel.conf
port 26379
dir "/tmp"

sentinel monitor mymaster IP 6381 2
sentinel auth-pass mymaster 6379091170
sentinel down-after-milliseconds mymaster 10000

sentinel failover-timeout mymaster 10000
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
user default on nopass ~* &* +@all
sentinel myid 14d8e55124f6544c34fe07677ed631ad84a2dda8
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel current-epoch 1
sentinel known-replica mymaster IP 6379
sentinel known-replica mymaster IP 6380
sentinel known-sentinel mymaster 172.23.0.3 26379 b3dbb7b056757c6aa987af96982c933c33368783
sentinel known-sentinel mymaster 172.23.0.2 26379 bc166fe18ca1b4d4f6d1ff4663da7321a81f1bcd

在进行了一次选举之后,配置文件中的主节点成为了6381端口的Redis实例。客户端将通过该文件中记录的信息来连接redis主节点,若使用docker的内部网络,此时的IP地址都为172.23.0.*,客户端将无法访问docker的内部网络。

SpringBoot中配置Redis哨兵

spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - IP:26379
        - IP:26380
        - IP:26381

结语

至此,Redis哨兵搭建完毕,对客户端来说实现了读高并发下的高可用。当主节点宕机之后,哨兵将自动选举出新的主节点,而客户端无需做任何修改。

参考

docker安装redis并以配置文件方式启动
https://github.com/zaozaoniao/Redis-sentinel-with-docker-compose
《Redis入门指南(第二版)》 李子骅著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值