在 Python 中命名当前 Redis master (运行 in Docker)
Naming current Redis master (run in Docker) in Python
如果主服务器宕机,如何Python故障转移到Redis从服务器?
在当前配置下,Sentinels 选出一个新的 master,但是 Python 写入停止。
我假设我不应该像 docker-compose.yml 文件中那样使用 redis-master;还有哪些选择?
在网络模式下,我无法让 Sentinels 相互识别。
docker-compose.yml
version: '3'
services:
redis-master:
container_name: redis-master
image: redis:latest
command: redis-server --port 6379
ports:
- "6379:6379"
volumes:
- .:/app
redis-slave:
container_name: redis-slave
image: redis:latest
command: redis-server --slaveof redis-master 6379 --protected-mode no
volumes:
- .:/app
sentinel-1:
container_name: sentinel-1
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
sentinel-2:
container_name: sentinel-2
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
sentinel-3:
container_name: sentinel-3
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
app:
container_name: python-app
image: pyredis
command: python app.py
Python 应用程序:
import redis
import random
import time
r = redis.StrictRedis(host="redis-master", port=6379, db=0)
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
r.set(timestamp, num)
time.sleep(2)
谢谢,欢迎任何意见。
您需要一个函数来重新定义您的 r
值:
import redis
from redis.exceptions import ConnectionError
def get_connection(host):
global r
other_host = "redis-slave" if "master" in host else "redis-master"
try:
r = redis.StrictRedis(host=host, port=6379, db=0)
except ConnectionError:
# connection against host failed, try other_host
host = other_host
r = redis.StrictRedis(host=host, port=6379, db=0)
return host
host = get_connection('redis-master')
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
try:
r.set(timestamp, num)
# handles explicitly redis.exceptions.ConnectionError
except ConnectionError:
host = get_connection(host)
r.set(timestamp, num)
time.sleep(2)
在master宕机的情况下,会调用那个函数,将连接切换到slave,反之亦然。如果两个都down了,被外层except
捕获的Exception
会被raise,程序会崩溃
编辑
对于通常为 BIG NO-NO 的可变默认值,这可能是一个非常有趣的用例。 注意,我仍然不会在任何生产代码中实现它,只是在这里显示副作用
双端队列支持就地旋转,因此您可以使用它来切换 host
和 other_host
,如下所示:
from collections import deque
d = deque(('redis-master', 'redis-slave'), maxlen=2)
d
deque(['redis-master', 'redis-slave'], maxlen=2)
d.rotate()
d
deque(['redis-slave', 'redis-master'], maxlen=2)
现在,您可以将其用作缓存并交换顺序
def get_connection(d=deque(('redis-master', 'redis-slave'), maxlen=2)):
global r
host, other_host = d # unpacks the two values
try:
r = redis.StrictRedis(host=host, port=6379, db=0)
except ConnectionError:
r = redis.StrictRedis(host=other_host, port=6379, db=0)
d.rotate() # changes the order of the hosts
展示其工作原理:
def get_connection(d=deque(('redis-master', 'redis-slave'), maxlen=2)):
print(d)
try:
raise ValueError # as a test
except ValueError:
print("Caught error")
d.rotate()
print(d)
get_connection()
deque(['redis-master', 'redis-slave'], maxlen=2)
Caught error
deque(['redis-slave', 'redis-master'], maxlen=2)
get_connection()
deque(['redis-slave', 'redis-master'], maxlen=2)
Caught error
deque(['redis-master', 'redis-slave'], maxlen=2)
现在您的外部程序不需要知道 host
,它只需要根据需要调用重试函数:
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
try:
r.set(timestamp, num)
# handles explicitly redis.exceptions.ConnectionError
except ConnectionError:
get_connection() # host doesn't need to be returned anymore
r.set(timestamp, num)
time.sleep(2)
如果主服务器宕机,如何Python故障转移到Redis从服务器?
在当前配置下,Sentinels 选出一个新的 master,但是 Python 写入停止。
我假设我不应该像 docker-compose.yml 文件中那样使用 redis-master;还有哪些选择?
在网络模式下,我无法让 Sentinels 相互识别。
docker-compose.yml
version: '3'
services:
redis-master:
container_name: redis-master
image: redis:latest
command: redis-server --port 6379
ports:
- "6379:6379"
volumes:
- .:/app
redis-slave:
container_name: redis-slave
image: redis:latest
command: redis-server --slaveof redis-master 6379 --protected-mode no
volumes:
- .:/app
sentinel-1:
container_name: sentinel-1
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
sentinel-2:
container_name: sentinel-2
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
sentinel-3:
container_name: sentinel-3
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
app:
container_name: python-app
image: pyredis
command: python app.py
Python 应用程序:
import redis
import random
import time
r = redis.StrictRedis(host="redis-master", port=6379, db=0)
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
r.set(timestamp, num)
time.sleep(2)
谢谢,欢迎任何意见。
您需要一个函数来重新定义您的 r
值:
import redis
from redis.exceptions import ConnectionError
def get_connection(host):
global r
other_host = "redis-slave" if "master" in host else "redis-master"
try:
r = redis.StrictRedis(host=host, port=6379, db=0)
except ConnectionError:
# connection against host failed, try other_host
host = other_host
r = redis.StrictRedis(host=host, port=6379, db=0)
return host
host = get_connection('redis-master')
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
try:
r.set(timestamp, num)
# handles explicitly redis.exceptions.ConnectionError
except ConnectionError:
host = get_connection(host)
r.set(timestamp, num)
time.sleep(2)
在master宕机的情况下,会调用那个函数,将连接切换到slave,反之亦然。如果两个都down了,被外层except
捕获的Exception
会被raise,程序会崩溃
编辑
对于通常为 BIG NO-NO 的可变默认值,这可能是一个非常有趣的用例。 注意,我仍然不会在任何生产代码中实现它,只是在这里显示副作用
双端队列支持就地旋转,因此您可以使用它来切换 host
和 other_host
,如下所示:
from collections import deque
d = deque(('redis-master', 'redis-slave'), maxlen=2)
d
deque(['redis-master', 'redis-slave'], maxlen=2)
d.rotate()
d
deque(['redis-slave', 'redis-master'], maxlen=2)
现在,您可以将其用作缓存并交换顺序
def get_connection(d=deque(('redis-master', 'redis-slave'), maxlen=2)):
global r
host, other_host = d # unpacks the two values
try:
r = redis.StrictRedis(host=host, port=6379, db=0)
except ConnectionError:
r = redis.StrictRedis(host=other_host, port=6379, db=0)
d.rotate() # changes the order of the hosts
展示其工作原理:
def get_connection(d=deque(('redis-master', 'redis-slave'), maxlen=2)):
print(d)
try:
raise ValueError # as a test
except ValueError:
print("Caught error")
d.rotate()
print(d)
get_connection()
deque(['redis-master', 'redis-slave'], maxlen=2)
Caught error
deque(['redis-slave', 'redis-master'], maxlen=2)
get_connection()
deque(['redis-slave', 'redis-master'], maxlen=2)
Caught error
deque(['redis-master', 'redis-slave'], maxlen=2)
现在您的外部程序不需要知道 host
,它只需要根据需要调用重试函数:
for i in range(0, 1000):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
num = random.randint(1,101)
try:
r.set(timestamp, num)
# handles explicitly redis.exceptions.ConnectionError
except ConnectionError:
get_connection() # host doesn't need to be returned anymore
r.set(timestamp, num)
time.sleep(2)