基于docker实现redis双机热备
redis的双机热备,是由redis主从+sentinel(哨兵)来实现的,至于使不使用docker差别不是特别大,我之所以选择基于docker主要出于方便。
我这里基于两台服务器进行讲解,主从设置上,一主一从或者一主多从都可以,但是哨兵模式上,官方的建议是2n+1(n>=1)台服务器的,不过出于资源有限,以及我们是基于一主一从的模式,所以,我们这里只采用两台服务器,勉强搞搞啦~
服务器1: 192.168.0.1(主)
服务器2: 192.168.0.2(从)
一、安装docker
docker教程这里就不详细讲了,可参考《linux下安装docker》
二、拉取redis镜像
-
服务器1
和服务器2
分别执行docker命令,拉取redis的最新镜像$ docker pull redis
-
查看拉取的镜像
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 01a52b3b5cd1 2 weeks ago 98.2MB
主从
redis的主从是实现redis集群和redis哨兵高可用的基础,redis的主从结构使从可以复制主上的数据,如果从与主之间网络断开,从会自动重连到主上。
一、配置主从服务配置文件
-
服务器1
和服务器2
分别拉取redis的配置文件 docker拉取的redis跟我们平时自己下载的不一样,没有redis.conf文件,如果需要可以通过官方提供的地址下载默认配置文件
建议把redis.conf文件放置到
/etc/redis/
目录下,方便记忆,后续启动容器的时候,该配置文件会与容器内的配置文件进行关联。$ mkdir /etc/redis $ cd /etc/redis $ wget http://download.redis.io/redis-stable/redis.conf
-
修改
服务器1
(主机)的redis.conf文件, 注意:主机、从机配置有差别$ vim /etc/redis/redis.conf
# 注释这一行,表示Redis可以接受任意ip的连接 # bind 127.0.0.1 # 关闭保护模式 protected-mode no # 让redis服务后台运行 daemonize yes # 设定密码(可选,如果这里开启了密码要求,从机的配置里就要加这个密码. 都是内网的话,不考虑安全性,就不使用密码认证了) # requirepass password # 配置日志路径,为了便于排查问题,指定redis的日志文件目录,该目录为容器内的目录 logfile "/var/log/redis.log"
-
修改
服务器2
(从机)的redis.conf文$ vim /etc/redis/redis.conf
# 注释这一行,表示Redis可以接受任意ip的连接 # bind 127.0.0.1 # 关闭保护模式 protected-mode no # 让redis服务后台运行 daemonize yes # 配置日志路径,为了便于排查问题,指定redis的日志文件目录,该目录为容器内的目录 logfile "/var/log/redis.log" # ############################## # 以下设定为主机和从机的区别之处 # ############################## # 设定密码(可选) # requirepass password # 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码 # masterauth <master-password> # 设定master的IP和端口号,redis配置文件中的默认端口号是6379 # 低版本的redis这里会是slaveof,意思是一样的,因为slave是比较敏感的词汇,所以在redis后面的版本中不在使用slave的概念,取而代之的是replica # 将服务器1做为主,服务器2做从。ip和端口号按照机器和配置做相应修改。 replicaof 192.168.0.1 6379
二、创建日志文件,方便查看运行情况
服务器1
和服务器2
分别创建日志文件,该文件后续在容器启动的时候,会与容器内的日志文件相关联,方便查看日志
$ touch /var/log/redis/redis.log
三、启动redis服务,检查主从配置正确性
因为从机依赖主机的活动状态,只有主机在线,从机才能正常工作,所以,我们在服务器1执行如下命令,再去服务器2执行同样的操作即可
-
启动容器
# 首先以后台模式运行容器,--name、-it、-p、-v、-d的含义可以自行查询docker命令的参数说明 $ docker run -it --name redis -p 6379:6379 -v /etc/redis/redis.conf:/etc/redis.conf -v /var/log/redis/redis.log:/var/log/redis.log -d redis /bin/bash # 容器成功启动后,会打印一个长串的容器ID a3952342094dfd5a56838cb6becb5faa7a34f1dbafb7e8c506e9bd7bb1c2951b # 通过ps命令查看容器的状态,可以看到redis已经启动 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a3952342094d redis "docker-entrypoint.s…" 1 minutes ago Up 1 minutes 0.0.0.0:6379->6379/tcp redis
-
进入容器,启动redis服务
# 以交互模式进入容器redis $ docker exec -it redis bash # 启动redis服务器,如果没有任何输出,就说明成功了,失败的话会有相应的错误信息 $ redis-server /etc/redis.conf # 在容器里启动一个redis客户端 $ redis-cli # 执行info命令,查看服务器状态 127.0.0.1:6379> info # 查看role值,主机的值是master,从机的值是slave ... role:master ... # 退出容器,返回服务器 $ exit
-
校验主从复制是否正常
利用redis链接工具或者redis-cli,连接服务器1的redis服务,设置一个key值,查看服务器2的redis服务下同样会出现一个相同的key,同理,删除服务器1中的该key后,服务器2中的也会相应删除掉。
哨兵模式
主从结构搭建成功了,系统的可用性变高了,但是如果主发生故障,需要人工手动切换从机为主机。这种切换工作不仅浪费人力资源,更大的影响是主从切换期间这段时间redis是无法对外提供服务的。因此,哨兵系统被开发出来了,哨兵可以在主发生故障后,自动进行故障转移,在从机里选出一台升级为主机,并持续监听着原来的主机,当原来的主机恢复后,会将其作为新主机的从机。
哨兵先监听主机,通过对主机发送info命令,获取到从机的信息,然后也会监听到从机。另外哨兵都会向主机订阅__sentinel__:hello频道,当有新的哨兵加入时,会向这个频道发送一条信息,这条信息包含了该哨兵的IP和端口等信息,那么其他已经订阅了该频道的哨兵就会收到这条信息,就知道有一个新的哨兵加入。这些哨兵会与新加入和哨兵建立连接,选主机是需要通过这个连接来进行投票的。
一、拉取哨兵的配置文件并修改
哨兵可以根据你的服务器数量配置多个,目前我们有两台服务器,我们就配置两个,与redis服务不同,redis服务区分主从,哨兵彼此之间没有区别。
-
拉取官方配置
$ wget http://download.redis.io/redis-stable/sentinel.conf
-
修改配置文件
# 注释这一行,表示Redis可以接受任意ip的连接 # bind 127.0.0.1 # 关闭保护模式 protected-mode no # 让sentinel服务后台运行 daemonize yes # 修改日志文件的路径,指定哨兵的日志文件目录,该目录为容器内的目录 logfile "/var/log/sentinel.log" # 修改监控的主redis服务器 # 最后一个1表示,一台机器判定主被动下线后,就进行failover(故障转移) # 官方的建议的哨兵数量是2n+1(n≥1),所以该值也通常设定为n+1,因为我这里只有两台服务器,所以就用了1 sentinel monitor mymaster 192.168.0.1 6379 1 # 检测到主机挂掉后,多久选取一台从机作为主机,默认值是30s,这里调成3s sentinel down-after-milliseconds mymaster 3000
二、创建日志文件,方便查看运行情况
$ touch /var/log/redis/sentinel.log
三、启动哨兵
与启动redis容器类似,启动一个别名为sentinel的容器,用来运行哨兵服务
-
启动容器
$ docker run -it --name sentinel -p 26379:26379 -v /etc/redis/sentinel.conf:/etc/sentinel.conf -v /var/log/redis/sentinel.log:/var/log/sentinel.log -d redis /bin/bash
-
进入容器,启动服务
# 进入容器 $ docker exec -it sentinel bash # 启动哨兵 redis-sentinel /etc/sentinel.conf
-
校验故障转移是否正常
将服务器1的主机redis服务的docker实例stop掉,通过info命令观察从机的
role
值是否由salve
转为master
。启动服务器的主机redis服务,并通过info命令查看该服务的
role
值为salve
。成功~
总结
通过主从复制的方式保证高可用,同时为了降低人工维护成本,引入哨兵模式自动切换主从,进一步提升了高可用性。
同时引入了一个新的问题,当主从自动切换的时候,客户端如何甄别哪台服务器为主,从而进行不间断的服务访问,请参考《spring boot整合redis哨兵模式(双机热备)》