Redis主从哨兵容器配置
主要测试下容器的主从如何搭建,主要使用一台虚拟机,部署三个容器,构成主从结构
一、部署的结构:
主:172.17.0.2 6379->6379
从1:映射端口 6380 -> 6379
从2:映射端口 6381 -> 6379
二、拉取Redis容器镜像
docker pull redis
三、下载Redis官方配置文件,并修改,作为容器配置文件的挂在(容器中服务配置,需要在主机上挂载)
wget http://download.redis.io/redis-stable/redis.conf
主配置:
# 注释这一行,表示Redis可以接受任意ip的连接 # bind 127.0.0.1 # 关闭保护模式,如果开启则需要配置 bind ip或者设置密码才能访问 protected-mode no # 让redis服务后台运行 ,容器部署的话这个需要设置成前台访问,否则容器不能正常启动,即为no daemonize no # 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码. 只是练习配置,就不使用密码认证了) # requirepass masterpassword # 配置日志路径,为了便于排查问题,指定redis的日志文件目录,这个目录必须存在否则容器不能启动 logfile "/data/redis.log"
从配置:
# 注释这一行,表示Redis可以接受任意ip的连接 # bind 127.0.0.1 # 关闭保护模式 protected-mode no # yes是让redis服务后台运行 daemonize no # 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码) requirepass masterpassword # 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码 masterauth <master-password> # 设定master的IP和端口号,redis配置文件中的默认端口号是6379 # 低版本的redis这里会是slaveof,我这个版本用的是replica # 这里设置master容器内部的IP,使用docker inspect redis-1 | grep IPAddress ,找到容器IP replicaof 172.17.0.2 6379 # 配置日志路径,为了便于排查问题,指定redis的日志文件目录,必须存在 logfile "/data/redis.log"
四、启动镜像,并指定启动的配置文件
docker run -it --name redis-1 --privileged=true -v /data/redis/redis-1/redis.conf:/etc/redis.conf -v /root/docker/redis/data:/data -d -p 6379:6379 redis redis-server /etc/redis.conf docker run -it --name redis-2 --privileged=true -v /data/redis/redis-2/redis.conf:/etc/redis.conf -v /root/docker/redis/data:/data -d -p 6380:6379 redis redis-server /etc/redis.conf docker run -it --name redis-3 --privileged=true -v /data/redis/redis-3/redis.conf:/etc/redis.conf -v /root/docker/redis/data:/data -d -p 6381:6379 redis redis-server /etc/redis.conf
解释:
-
--name 指定容器的名称 redis-2
-
--privileged=true,将外部的root权限,赋予容器用户,否则容器中有些权限不能执行
-
-v /data/redis/redis-3/redis.conf:/etc/redis.conf ,挂在宿主机上的配置到容器中
-
-v /root/docker/redis/data:/data ,挂在容器的数据文件到宿主机上
-
-p 6380:6379 指定端口映射到宿主机的端口6380,那外部访问这个redis需要通过6380
-
容器启动后执行redis配置文件加载:redis-server /etc/redis.conf(容器中配置文件的位置),这个命令容器启动以后登陆到容器中执行不生效,不知道具体问题
五、登陆到容器中验证
docker exec -it redis-1 bash redis-cli info info replication ( 主显示role:master ,从显示role:slave) 在master上执行 set name wang , 从中查看是否可以同步,如果有数据,则主从搭建成功
六、问题整理
1)解决容器中无权限问题
容器启动的时候添加参数: --privileged=true
2)容器启无异常日志,但是容器启动失败
因为容器是后台启动,如果redis也设置后台启动,则容器就会启动失败,查看redis配置,是否关闭了后台启动: daemonize no
3)redis启动后不能远程访问
启动后提示-并且外网不能访问redis:
docker redis WARNING: IPv4 forwarding is disabled. Networking will not work.
解决:
vi /etc/sysctl.conf net.ipv4.ip_forward=1 #添加这段代码 systemctl restart network && systemctl restart docker #重启network服务 sysctl net.ipv4.ip_forward #查看是否修改成功 (备注:返回1,就是成功)
4)查看自己的配置是否生效(自己开始的时候在容器内部执行这个命令不生效,找了很久都不知道具体原因:redis-server /etc/redis.conf)
登陆到redis-cli执行以下命令,看看是否是我们设置的配置
CONFIG GET replicaof
CONFIG GET protected-mode
5)宿主机配置文件修改
挂在的宿主机上的配置文件每次修改后重启容器中配置文件可以刷新,并生效
六、添加三台哨兵作为切换
1)下载哨兵配置
wget http://download.redis.io/redis-stable/sentinel.conf
修改配置文件: # 让sentinel服务后台运行 daemonize no # 修改日志文件的路径 logfile "/data/sentinel.log" # 修改监控的主redis服务器 # 最后一个2表示,两台机器判定主被动下线后,就进行failover(故障转移) # mymaster 为哨兵中 主的名称(自己起的名字) ,IP 和端口是容器的IP和启动的redis端口 # 可以有多个sentinel monitor 即监控多个master,这个iP和端口是宿主机对外的主redis的IP和端口,以便对外可以访问 sentinel monitor mymaster 35.236.172.131 6379 2
2) 启动哨兵容器
docker run -it --name sentinel-1 --privileged=true -v /data/redis/sentinel-1/sentinel.conf:/etc/sentinel.conf -d -p 26381:26379 redis redis-sentinel /etc/sentinel.conf docker run -it --name sentinel-2 --privileged=true -v /data/redis/sentinel-1/sentinel.conf:/etc/sentinel.conf -d -p 26381:26379 redis redis-sentinel /etc/sentinel.conf docker run -it --name sentinel-3 --privileged=true -v /data/redis/sentinel-1/sentinel.conf:/etc/sentinel.conf -d -p 26381:26379 redis redis-sentinel /etc/sentinel.conf
3)查看哨兵状态
登陆到容器中查看日志可以查看哨兵监听情况: tail -f -n 300 /data/sentinel.log 哨兵节点上执行: redis-cli -h localhost -p 26379 info Sentinel sentinel master mymaster
4)测试主从切换
停掉主redis的容器:docker stop redis-1
查看哨兵日志会切换主节点的容器为其他节点
启动主redis的容器,则主变成了slave节点
5)Jedis客户端连接哨兵测试
public class AppTest { public static void testSentinel() { String masterName = "mymaster"; Set<String> sentinels = new HashSet<>(); sentinels.add("192.168.112.131:26379"); sentinels.add("192.168.112.131:26380"); sentinels.add("192.168.112.131:26381"); //通过sentinel来拿到master然后进行链接 JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); Jedis jedis = pool.getResource(); jedis.set("name", "wang" ); String keys1 = jedis.get("name") ; System.out.println( keys1); pool.close(); } public static void main(String[] args) { testSentinel(); } }
redis做分布式操作->redisson地址:https://github.com/redisson/redisson/wiki