Redis系列 使用docker部署redis主从模式+哨兵监听

前言

redis现已成为我们项目中经常使用到的服务,比如说要实现缓存,秒杀活动,分布式锁以及一些高并发场景,那redis都是必不可少的,那这么多的需求都用到了redis,如果项目并发小的话也到没啥,但是往往一些大项目还是会轻轻松松的达到redis单机的瓶颈,然后使项目的运行速度大打折扣,那我们就不得不去根据我们的项目环境去搭建redis主从模式或者集群了!

那我们今天就给大家带来第一个方案,他惯用于读多写少的环境,使用空间去换取时间,新增多个redis节点去同步数据,达到主写从读的读写分离,优点就是大幅提高redis瓶颈和数据的安全,如果搭配哨兵也会形成了一个高可用的服务存储框架,那缺点呢也很明显每个读写分离框架的通病就是当主机收到写请求时他需要同步到其他各个从节点,虽然会很快但是也会有毫米级得到时差,那在这一段时间从服务的数据也就被称为是脏数据了,所以在使用该主从模式时需要项目能接受短时间的脏数据!

在服务部署之前需要我们当前系统环境有docker服务,如果有小伙伴没有安装的可以看我们另一篇文章 - Linux系列 CentOS7(yum)安装docker

redis主从环境部署

创建redis网络环境

为了主从环境的隔离性和安全性,我们先创建一个独立的docker网络区域(网段)来部署redis主从

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 redisnet

各参数解释

  • docker netword create (docker的基础网络创建命令)
  • --driver 设置网络模式,有以下几种网络模式
    • bridge 桥接模式,docker默认使用该模式 , 自己创建的网络也使用bridge模式
    • none 不配置网络
    • host 和宿主机共享网络
    • container 容器网络联通!(用的少!局限很大)
  • --subnet 设置网络的子网掩码,分为以下两个子网掩码
    • 192.168.0.0/16 可以使用6W+个IP地址 一般用于企业 等于就是 255.255.0.0
    • 192.168.0.0/24 可以使用255个IP地址 一般用于家庭 等于就是 255.255.255.0
  • --gateway 设置网络的网关(定义该网络段的网关地址)一般推荐使用该网段主机id为1或者主机id为255,看个人喜好
  • redisnet 自定义的网络名称

查看网络是否新建成功

docker network ls

image

网络创建成功之后,我们在创建redis各个节点的配置文件!

创建各个redis节点的配置文件

新建一个文件夹用来存放我们每个redis节点的启动配置文件

mkdir /var/redis/
mkdir /var/log/redis/

进入该文件夹,我们首先创建一个redis的master(主机)节点的配置文件

mkdir /var/redis/redis-master/
cd /var/redis/redis-master/
vim redis-master.conf

填入以下配置(主机),

#端口号
port 6379
#网关绑定ip 127.0.0.1 只能本机访问,0.0.0.0所有ip都可以访问
bind 0.0.0.0
#开启appendonly备份模式
appendonly yes
#日志配置
#debug : 会打印生成大量信息,适用与开发/测试阶段
#verbose : 包含很多不太有用的信息,但不像debug级别那么乱
#notice : 适度冗长,适用于生产环境
#warning : 仅记录非常重要、关键的警告消息
loglevel notice
#日志文件路径
logfile /var/log/redis/redis-master.log
#持久化文件保存目录
dir /var/redis/redis-master/
#持久化保存文件名
dbfilename dump_6380.rdb
#节点密码
requirepass 123456
#声明自己的ip地址与端口号
slave-announce-ip *.*.*.*
slave-announce-port 6370
#主节点密码-如果后续要启动哨兵服务,主节点密码还是要填的,要不当主节点挂掉重启变从机以后会访问不了新的master节点(所以哨兵服务推荐大家主从节点的密码都设置一致)
masterauth 123456

slave-announce-ip : 我们着重说一些这个参数,如果我们使用的docker非host网络模式部署的redis主从+哨兵,那下面这个配置需要填自己的宿主机的外网地址和映射到宿主机的端口,不然项目使用哨兵以后请求哨兵会返回redis主节点在docker中的内网地址,那这个地址外网项目访问肯定是不通的,除非你的项目和redis节点都在一个网络上,如果该redis主从集群不使用外网请求/或者不使用哨
兵进行高可用的话也可以注释掉

然后我们在使用脚本循环创建6个从机的配置文件

for port in $(seq 1 6); \
do \
mkdir /var/redis/redis-${port}/
touch /var/redis/redis-${port}/redis-${port}.conf

cat << EDF >/var/redis/redis-${port}/redis-${port}.conf
port 6379
bind 0.0.0.0
appendonly yes
loglevel notice
logfile /var/log/redis/redis-${port}.log
dir /var/redis/redis-${port}/
dbfilename dump_6380.rdb
requirepass 123456
#主节点的ip地址和端口号
replicaof 192.168.0.100 6379
#告诉主节点我的ip地址和端口号,改成自己的,如果要使用哨兵推荐改成自己的服务器的外网地址
slave-announce-ip *.*.*.*
slave-announce-port 637${port}
#主节点密码
masterauth 123456
EDF
done

image

修改redis日志文件夹权限和数据文件夹的权限,让docker内的数据和日志可以生成文件!生成的数据文件和日志文件不会是 777权限,放心!

chmod -R 777 /var/log/redis
chmod 777 /var/redis/*

主机和从机的配置文件创建完成之后我们使用这些配置文件去构建并启动对应的redis实例

构建redis主机实例

使用docker构建实例还是很简单,一行命令就可以了

我们先构建第一个redis-master(主机)实例

docker run -p 6370:6379 -p 16370:16379 --name redis-master \
 -v /var/redis/redis-master/:/var/redis/redis-master/ \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.100 redis:latest redis-server /var/redis/redis-master/redis-master.conf

各参数解释

  • -p 宿主机端口:docker容器内端口,宿主机与docker容器映射,请求宿主机的6371=请求该docker容器的6379端口
  • --name 给该docker容器命名,后续可以根据该名称进行删除和进入和网络连接(在同网段,容器名称可以代替ip来使用)等操作
  • -v 宿主机目录:容器内部目录,将redis的数据文件夹以及conf文件挂载出去,防止redis节点意外删除数据丢失
  • -d 后台启动
  • --net 设置redis列入那个网络中(这里是注入的上面自定义的网络 redisnet 中 , 网关是 192.168.0.1)
  • --ip 设置redis的ip地址,与配置中cluster-announce-ip对应即可
  • redis-server 后续填写启动该redis实例使用的配置文件路径
  • redis:latest 这是docker hub上的镜像名,大家也可以去hub上找自己想要的版本,这里展示的是获取最新版本

构建redis从机实例

主机实例构建完成后,我们在构建剩下的从机实例

第一个从机实例启动命令

docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
 -v /var/redis/redis-1/:/var/redis/redis-1/ \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.101 redis:latest redis-server /var/redis/redis-1/redis-1.conf

第二个从机实例启动命令

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
 -v /var/redis/redis-2/:/var/redis/redis-2 \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.102 redis:latest redis-server /var/redis/redis-2/redis-2.conf

第三个从机实例启动命令

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
 -v /var/redis/redis-3/:/var/redis/redis-3 \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.103 redis:latest redis-server /var/redis/redis-3/redis-3.conf

第四个从机实例启动命令

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
 -v /var/redis/redis-4/:/var/redis/redis-4 \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.104 redis:latest redis-server /var/redis/redis-4/redis-4.conf

第五个从机实例启动命令

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
 -v /var/redis/redis-5/:/var/redis/redis-5 \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.105 redis:latest redis-server /var/redis/redis-5/redis-5.conf

第六个从机实例启动命令

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
 -v /var/redis/redis-6/:/var/redis/redis-6 \
 -v /var/log/redis/:/var/log/redis/ \
 -d --net redisnet --ip 192.168.0.106 redis:latest redis-server /var/redis/redis-6/redis-6.conf

我们使用docker ps 指令docker中运行的实例容器

docker ps

image

我们可以看见1个主节点和6和从节点都已经启动成功了

检测各节点是否都运行正常

然后我们再看一下主节点的日志,看看其他6个从节点的同步情况

cat /var/redis/redis-master/redis-master.log

image

也可以直接进入master节点使用info命令去看

docker exec -it [容器id] /bin/bash #进入docker容器内部-容器id可以使用docker ps命令查看

进入docker容器内部后

root@2328179594eb:/data# redis-cliredis-cli #进入redis数据库
127.0.0.1:6379> auth [redis主机密码]
127.0.0.1:6379> info

image

然后找Replication下面显示的就是主从机的详情了

image

现在我们就构建了一个redis的主从模式,主机用来写操作,从机用来读操作,我们也可以使用nginx或者其他负载均衡的代理服务对从机进行负载均衡让请求不会聚集在一个从机上,使项目可以稳定切快速的运行!

但是现在还会面临一个问题,那就是写操作全在master上,那如果master宕机了数据都存不进来了,所有从机的数据也就全都变成了胀数据,我们该怎么办呢,

那接下来我们就要搭建一个redis的一个哨兵模式,顾名思义就是使用一个哨兵去看着每一个主从节点,当一个节点发生宕机之后他会进行推举机制,在从机中推举一个出来当master,具体哨兵的推举机制为了文章的整洁性,我会在后续的文章中着重讲解!

搭建redis哨兵集群

生成哨兵的配置文件

为了配置文件便于维护,我们还是在redis的配置文件夹下去新建哨兵的配置文件

cd /var/redis

使用for命令循环生成3个哨兵的配置文件

for port in $(seq 1 3); \
do \
mkdir /var/redis/redis-sentinel-${port}/
touch /var/redis/redis-sentinel-${port}/redis-sentinel-${port}.conf
cat << EDF >/var/redis/redis-sentinel-${port}/redis-sentinel-${port}.conf
port 2638${port}
bind 0.0.0.0
daemonize no
dir /var/log/redis/
logfile "redis-sentinel-${port}.log"
sentinel monitor mymaster 192.168.0.100 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
EDF
done

重要的几个配置,这里说一下

  • sentinel monitor mymaster : redis主节点的ip地址和端口号,还有需要几个哨兵判断主观下线才进行failover(故障转移),如果不外网请求redis就写内网地址192.168.0.100 , 如果需要外网请求redis就需要填宿主机的外网地址+主节点映射到宿主机的端口号也就是redis主节点配置中的 slave-announce-ip 和 slave-announce-port参数
  • sentinel auth-pass mymaster : redis主节点的密码
  • daemonize : 是否开启守护进程,也就是是否要后台运行,我们是使用docker启动有-d,所以要设置为no
    然后我们通过这三个配置文件启动哨兵

    启动哨兵

    第一个哨兵启动命令

    docker run -p 26381:26381 --name redis-sentinel-1 \
    -v /var/redis/redis-sentinel-1/:/var/redis/redis-sentinel-1/ \
    -v /var/log/redis/:/var/log/redis/ \
    -d --net redisnet --ip 192.168.0.201 redis:latest redis-sentinel /var/redis/redis-sentinel-1/redis-sentinel-1.conf

    第二个哨兵启动命令

    docker run -p 26382:26381 --name redis-sentinel-2 \
    -v /var/redis/redis-sentinel-2/:/var/redis/redis-sentinel-2/ \
    -v /var/log/redis/:/var/log/redis/ \
    -d --net redisnet --ip 192.168.0.202 redis:latest redis-sentinel /var/redis/redis-sentinel-2/redis-sentinel-2.conf

    第三个哨兵启动命令

    docker run -p 26383:26381 --name redis-sentinel-3 \
    -v /var/redis/redis-sentinel-3/:/var/redis/redis-sentinel-3/ \
    -v /var/log/redis/:/var/log/redis/ \
    -d --net redisnet --ip 192.168.0.203 redis:latest redis-sentinel /var/redis/redis-sentinel-3/redis-sentinel-3.conf

    然后我们使用docker ps命令看一下哨兵是否都启动成功了

docker ps

image

可以看见三个哨兵服务已经在运行,然后我们就来测试一下哨兵是否都在正常运转

我们把存放这master节点的docker容器给他关掉,看看哨兵会不会推举一个新的master出来

docker stop 2328179594eb

然后我们去看哨兵的日志

image

我们进192.168.0.101节点里面看一下是否已经被推举成master了

[root@iZbp11wpwnsuekkZ /]# docker exec -it 149 /bin/bash
root@14923983e87d:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info

image

所以可以确定我们的哨兵集群在正常的运作!

扩展 : 如何使用SpringBoot去连接哨兵

如果你搭建了redis主从+哨兵框架,那你项目就不可以去连接redis的主节点了,因为当主节点挂掉以后你项目并不知道最新的主节点,还是会根据配置文件去请求之前的旧节点,所以我们要去配置连接哨兵,让哨兵告诉我们最新的主节点地址然后再去请求;

重要 : 每个redis配置中需要配置slave-announce-ip和slave-announce-port参数,参数值就是你服务器的外网地址以及你redis映射到宿主记的端口号,如果不声明的话,外网请求哨兵,哨兵会返回redis在docker中内网地址,在上述教程中已经着重讲解,这里在提一下,这里很容易犯错!!!

如何查看每个redis容器节点映射到宿主机的端口号呢

docker ps

image

  1. 先导入操作redis的基础依赖
<dependency>
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 修改yum配置文件

spring:
  redis:
    password: 123456  #如果有密码的话 这里就redis的密码
    sentinel:
      master: mymaster  # 主机名称
      nodes: # 每个哨兵的ip地址:端口,改成自己的
        - 127.27.239.96:26381
        - 127.27.239.96:26382
        - 127.27.239.96:26382

小结

这样子一个简单实用的redis主从+哨兵的高可用服务就搭建成功了,有些小伙伴肯定也会觉得虽然中间配置文件虽然有些使用了for脚本来生成但是还是好繁琐好复杂对不对

但是在docker面前怎么可以说复杂呢呢,后续我们将使用docker-compose(容器编排)来实现,告诉你怎么使用一个配置文件+一行命令直接搭建出一个redis主从+哨兵的高可用服务,1分钟搭建一个redis高可用服务你激不激动,那就敬请期待吧!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇