基于Docker搭建Redis一主两从三哨兵

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: 安装redis集群,安装爬坑的过程。以及如何在python中使用所遇到的问题,和解决这些问题的方法。

获取Redis镜像

docker命令拉取镜像

docker pull redis

查看镜像

docker image ls

获取并修改redis配置文件

redis官方提供了一个配置文件样例,通过wget工具下载下来。

wget http://download.redis.io/redis-stable/redis.conf
在此只做配置主从关系的必要修改

其中redis服务器的master和slave角色使用的配置文件还会有些不同,下面分别进行说明。

首先说明一下,正常情况下配置主从关系需要多台机器,但现实往往不允许。所以现在在一台机器上模拟。

将下载下来的redis.conf复制三份,分别命名为 redis-master.conf,redis-slave1.conf,redis-slave2.conf

cp redis.conf redis-master.conf
cp redis.conf redis-slave1.conf
cp redis.conf redis-slave2.conf

将三个配置文件我放在了/usr/local/docker-redis/目录下

首先修改master的配置文件

vim redis-master.conf

# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1 

# 关闭保护模式
protected-mode no 

# 让redis服务后台运行
daemonize yes 
# 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码
masterauth <master-password>
# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码. 只是练习配置,就不使用密码认证了)
 requirepass masterpassword 

# 配置日志路径,为了便于排查问题,指定redis的日志文件目录
logfile "/var/log/redis/redis.log"

如果是服务器,redis密码很重要,因为redis默认没密码有漏洞,有很多人利用redis漏洞来使你的服务器挖矿,亲身体会。

其次修改slave配置。

vim redis-slave1.conf

# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1 

# 关闭保护模式
protected-mode no 

# 让redis服务后台运行
daemonize yes 

# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码)
requirepass masterpassword 

# 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码
masterauth <master-password>

# 设定master的IP和端口号,redis配置文件中的默认端口号是6379
# 低版本的redis这里会是slaveof,意思是一样的,因为slave是比较敏感的词汇,所以在redis后面的版本中不在使用slave的概念,取而代之的是replica
# 将35.236.172.131做为主,其余两台机器做从。ip和端口号按照机器和配置做相这里的IP地址往下看。
replicaof 198.18.0.2 6379

# 配置日志路径,为了便于排查问题,指定redis的日志文件目录
logfile "/usr/local/logs/redis.log"

上方提到的这个主节点地址为master的docker容器的地址,可以通过以下命令查看

docker inspect redis_master  # 用来查看容器的详细信息

slave2配置与上述相同。

启动容器

首先以后台模式运行master容器,注意文件的地址

docker run -it --name redis-master --network=dockercompose --ip 172.19.0.2 -v /data/docker_redis/redis-conf/redis-master.conf:/usr/local/redis/redis.conf -d -p 6379:6379 redis /bin/bash

首先以后台模式运行slave1容器,注意文件的地址和端口号,物理机的端口号不可冲突

$ docker run -it --name redis-master -v /usr/local/docker-redis/redis-slave1.conf:/usr/local/redis/redis.conf -d -p 6380:6379 redis /bin/bash

slave2启动同上

接下来进入容器里启动redis服务器。

以交互模式进入容器redis-master

docker exec -it redis-master bash

创建日志文件目录,与配置文件相同

mkdir /usr/local/logs/
touch /usr/local/logs/redis.log

启动redis服务器,如果没有任何输出,就说明成功了

redis-server /usr/local/redis/redis.conf

在容器里启动一个redis客户端

redis-cli

输入密码,进行身份验证

127.0.0.1:6379> auth password

执行info命令,查看服务器状态

127.0.0.1:6379> info

如果是主,这里的role的值会是master,如果是从,这里的role的值会是slave

image.png

对于slave,还要查看master_link_status这个属性值。slave上这个属性值为up就说明主从复制是OK的,否者就有问题。如果从机状态不为up,首先排查主机的端口是否被限,然后查看redis日志排查原因

退出客户端

127.0.0.1:6379> quit

最后退出容器

exit

验证主从复制

主从搭建成功后,可以通过在master上写入一个key-value值,查看是否会同步到slave上,来验证主从同步是否能成功

redis-cli
auth password
set test hello

在任意slave机器上进入容器,也运行一个redis-cli,查询这个key的值。如果能查询到这个值,且与主机上的值相同,说明主从同步成功。经测试,主动同步成功。

redis-cli
auth password
get test 

添加哨兵

可以在主发生故障后,自动进行故障转移,从从机里选出一台升级为主机,并持续监听着原来的主机,当原来的主机恢复后,会将其作为新主的从机。

哨兵先监听主,通过对主发送info命令,获取到从的信息,然后也会监听到从。另外哨兵都会像主订阅__sentinel__:hello频道,当有新的哨兵加入时,会向这个频道发送一条信息,这条信息包含了该哨兵的IP和端口等信息,那么其他已经订阅了该频道的哨兵就会收到这条信息,就知道有一个新的哨兵加入。这些哨兵会与新加入和哨兵建立连接,选主是需要通过这个连接来进行投票。这个关系可以用下面这个图来描述

image.png

获取并修改sentinel配置文件

通过wget命令获取sentinel的配置文件

wget http://download.redis.io/redis-stable/sentinel.conf

修改配置文件以下几项

vim sentinel.conf

# 让sentinel服务后台运行
daemonize yes 

# 修改日志文件的路径
logfile "/var/log/redis/sentinel.log"

# 修改监控的主redis服务器
# 最后一个2表示,两台机器判定主被动下线后,就进行failover(故障转移)
sentinel monitor mymaster 192.18.0.2 6379 2
# 主数据库密码,需要将配置放在sentinel monitor master 127.0.0.1 6379 1下面
sentinel auth-pass mymaster 123456789

启动容器

docker run -it --name sentinel -p 26379:26379 -v /usr/local/docker-redis/sentinel.conf:/usr/local/redis/sentinel.conf -d redis /bin/bash

运行哨兵

进入容器

docker exec -it sentinel bashdocker exec -it sentinel bash

创建日志目录和文件

mkdir /usr/local/logs
touch /usr/local/logs/sentinel.log

启动sentinel

redis-sentinel /usr/local/redis/sentinel.conf

查看是否生效

cat /usr/local/logs/sentinel.log

验证故障转移

为了验证哨兵机制下的自动主从切换,我们将主上的redis进程kill掉。

doker top reedis-master

找到redisserver的PID

kill -9 PID

稍等几秒钟后,就有另外一台从升级为主机,实验时是第三台机器,也就是redis-3升级为了主,用info命令查询可以看到redis-3服务器的角色变成的master。说明自动主从切换成功。

Python如何使用Redis

但当我用Python使用的时候出现了两个问题,这里记录一下: 1、redis.exceptions.ConnectionError: Error 113 connecting to 172.19.0.3:6379. No route to host. 2、redis.exceptions.ConnectionError: Error 99 connecting to 192.168.7.71:6380. Cannot assign requested address.

1. 安装redis包

pip install redis

2.实现连接逻辑

from redis.sentinel import Sentinel
from redis import WatchError
SENTINEADDRESS = [('192.18.0.2', 26380), ('192.18.0.2', 26381), ('192.18.0.2', 26382)] def 
MYSETINEL = Sentinel(SENTINEADDRESS, socket_timeout=2000)  # 尝试连接最长时间单位毫秒, 1000毫
#有密码可以加上参数password
MASTER = MYSETINEL.master_for('mymaster', socket_timeout=2000)
MASTER.set("a","A")
result=MASTER.get("a")
print(result)

这时候出现错误:

redis.exceptions.ConnectionError: Error 113 connecting to 172.19.0.3:6379. No route to host.

3.解决外界访问容器IP过程

首先想到就是容器IP不可达,想到两种解决方案:

1.获取容器IP转为公网IP后建立连接(单连接正常,频繁连接出现错误)

2.搭建了python容器。

1.自我转换(有问题)

转换的方法

    if s=="172.19.0.2":
        conn = redis.StrictRedis(
            host='192.18.0.2',
            port=6380,
            password="pwd",
            decode_responses=True)
        return conn
    elif s=="172.19.0.3":
        conn = redis.StrictRedis(
            host='192.18.0.2',
            port=6381,
            password="pwd",
            decode_responses=True)
        return conn
    else:
        conn = redis.StrictRedis(
            host='192.18.0.2',
            port=6382,
            password="pwd",
            decode_responses=True)
        return conn
from redis.sentinel import Sentinel
from apps.utils.handler import redis_conn
    sentinel = Sentinel([('192.18.0.2', 26380),('192.18.0.2', 26381),('192.18.0.2', 26382)
                         ],
                        socket_timeout=0.5)
master=sentinel.discover_master("mymaster")
master = redis_conn(master[0])
results = master.get("a")
print(results)   

可以正常使用。不过我执行的是定时脚本,需要频繁的写入操作,这时候出现新的问题了。

redis.exceptions.ConnectionError: Error 99 connecting to 192.168.7.71:6380. Cannot assign requested address.
原因就是频繁连接redis。最好的办法就是用哨兵原有的办法连接。

2.使用python容器

搭建完容器之后,执行定时脚本,发现依然会出现上述错误,那是因为我把哨兵放到了方法里面,我担心放在方法外面,当故障转移的时候,这个mymaster不能改变,是静态的,当我尝试把

master = sentinel.master_for('mymaster', socket_timeout=0.5, password='pwd', db=0,decode_responses=True)

拿出来之后,故意故障转移(kill掉主节点),程序自动切换到正确的节点。

结果是可行的。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
13天前
|
NoSQL 关系型数据库 Redis
Docker的通俗理解和通过宿主机端口访问Redis容器的实例
本文目标:引导初学者入门Docker,理解镜像、容器和宿主机概念,学习常用Docker命令,特别是如何创建并从Redis容器通过宿主机端口访问。 关键点: - Docker核心:镜像(类)、容器(实例)、宿主机(运行环境)。 - `docker pull` 拉取镜像,如 `redis:3.0`。 - `docker run -d --name` 后台运行容器,如 `my-redis`。 - `-p` 参数做端口映射,如 `6379:6379`。 - `docker exec -it` 交互式进入容器,如 `bash` 或执行命令。
|
12天前
|
运维 监控 NoSQL
Redis Sentinel哨兵模式部署
Redis Sentinel哨兵模式部署
36 2
|
3天前
|
监控 NoSQL Java
redis哨兵架构
不过为了高可用一般都推荐至少三个哨兵节点。为什么推荐奇数个哨兵节点跟集群奇数个master节点类似。
11 0
redis哨兵架构
|
15天前
|
NoSQL Redis Docker
docker部署redis
docker部署redis
26 4
|
1天前
|
存储 监控 NoSQL
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
4 0
|
3天前
|
NoSQL 关系型数据库 MySQL
一文学会dockers安装 (附docker安装MySQL、Redis)
一文学会dockers安装 (附docker安装MySQL、Redis)
27 0
|
23天前
|
监控 NoSQL Redis
Redis哨兵,Redis哨兵核心功能如何一个云服务器完成6个节点的搭建-docker什么是docker是否可以把六个容器,都写到同一个ym配置中,一次都启动,不就直接保证互通问题了吗?
Redis哨兵,Redis哨兵核心功能如何一个云服务器完成6个节点的搭建-docker什么是docker是否可以把六个容器,都写到同一个ym配置中,一次都启动,不就直接保证互通问题了吗?
|
7月前
|
NoSQL Redis Docker
Mac下Docker安装Redis
Mac下Docker安装Redis
343 0
|
1月前
|
NoSQL Redis Docker
在docker中安装redis,并且阿里云服务器配置
在docker中安装redis,并且阿里云服务器配置
216 1
|
1月前
|
NoSQL Redis 数据安全/隐私保护
最详细的docker中安装并配置redis
最详细的docker中安装并配置redis
2750 0