我用Docker搭建了Redis的一主两从三哨兵的集群,地址:https://blog.youkuaiyun.com/qq_41327483/article/details/107414945
但当我用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 = [('127.0.0.1', 6390), ('127.0.0.1', 6391), ('127.0.0.1', 6392)] 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.自我转换(有问题)
#转换的方法
def redis_conn(s):
if s=="容器resis的master的IP":
conn = redis.StrictRedis(
host='服务器的IP',
port=docker映射出来的端口,
password="自己的密码",
decode_responses=True)
return conn
elif s=="172.19.0.3":
conn = redis.StrictRedis(
host='服务器的IP',
port=docker映射出来的端口,
password="自己的密码",
decode_responses=True)
return conn
else:
conn = redis.StrictRedis(
host='服务器的IP',
port=docker映射出来的端口,
password="自己的密码",
decode_responses=True)
return conn
from redis.sentinel import Sentinel
from apps.utils.handler import redis_conn
sentinel = Sentinel([('服务器的IP', 26380),('服务器的IP', 26381),('服务器的IP', 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='密码', db=0,decode_responses=True)
拿出来之后,故意故障转移(kill掉主节点),程序自动切换到正确的节点。
结果是可行的。