目录
主从互备:
一,条件:
2台设备,(注意主从角色只是暂时的)
主角色:master 192.168.58.14
从角色:slave 192.168.58.4
二,哨兵:
3个 sentinel 哨兵实例,master 两个,slave 一个 ()
最佳实践和考虑因素:
-
最小数量:
- Sentinel 的最小推荐数量是 3。这是因为 Sentinel 使用 Raft 一致性算法来决定何时执行故障转移,而 Raft 需要大多数节点的同意来进行决策。至少需要三个 Sentinel 实例可以在一个实例失效时仍然保持决策能力。
-
奇数规则:
- 最好配置奇数个 Sentinel 实例。这样可以更容易地达到“多数派”决策,从而避免在网络分区情况下的脑裂问题(即两个子网络各自认为自己是有效的主节点)。例如,有 3 个 Sentinel 实例时,即使一个实例无法通信,剩余两个仍然可以形成多数派进行决策。
-
网络分布:
- 如果可能,将 Sentinel 实例分布在不同的物理服务器或至少在不同的虚拟机上。这样可以防止单点故障影响多个 Sentinel 实例,比如一台物理服务器的故障导致多个 Sentinel 实例同时失效。
-
与 Redis 服务器的关系:
- Sentinel 实例可以与 Redis 服务器共存于同一硬件上,但在生产环境中,最好将它们分开部署以避免资源争用和提高故障隔离性。
Redis Sentinel 集群依赖于所谓的“多数派”(quorum)来做出决策,特别是对故障转移操作。Quorum 是一个配置参数(一般为奇数),代表执行故障转移前必须同意该操作的最小 Sentinel 数量。通常,这个值至少是 Sentinel 总数的一半加一,以确保决策的有效性和防止脑裂。
- 如果有三个 Sentinel,你可能设置了一个 quorum 值为 2。
- 如果两个 Sentinel 异常退出,剩下的一个 Sentinel 将无法达到 quorum。因此,即使它独自认为主节点已经下线,也无法自主进行故障转移操作。
三,redis 配置:
主:
bind 0.0.0.0
protected-mode no
requirepass yourMasterPassword
masterauth yourMasterPassword
找到并注释掉slaveof这一行(如果存在)
从:
bind 0.0.0.0
protected-mode no
requirepass YourMasterPassword
masterauth yourMasterPassword
slaveof master_ip master_port
四,sentinel 配置:
主:
【/etc/redis-sentinel1.conf 配置】
port 26379
daemonize no
sentinel monitor ml_redismaster 192.168.58.14 6379 2
sentinel auth-pass ml_redismaster bird
sentinel down-after-milliseconds ml_redismaster 30000
sentinel parallel-syncs ml_redismaster 1
sentinel failover-timeout ml_redismaster 180000
sentinel deny-scripts-reconfig yes
logfile /var/log/redis/sentinel1.log
pidfile /var/run/redis-sentinel1.pid
dir /tmp
【/etc/redis-sentinel2.conf 配置】
port 26380
daemonize no
sentinel monitor ml_redismaster 192.168.58.14 6379 2
sentinel auth-pass ml_redismaster bird
sentinel down-after-milliseconds ml_redismaster 30000
sentinel parallel-syncs ml_redismaster 1
sentinel failover-timeout ml_redismaster 180000
sentinel deny-scripts-reconfig yes
logfile /var/log/redis/sentinel2.log
pidfile /var/run/redis-sentinel2.pid
dir /tmp
从:
【/etc/redis-sentinel.conf 配置】
port 26379
daemonize no
sentinel monitor ml_redismaster 192.168.58.14 6379 2
sentinel auth-pass ml_redismaster bird
sentinel down-after-milliseconds ml_redismaster 30000
sentinel parallel-syncs ml_redismaster 1
sentinel failover-timeout ml_redismaster 180000
sentinel deny-scripts-reconfig yes
logfile /var/log/redis/sentinel.log
pidfile /var/run/redis-sentinel.pid
dir /tmp
关键配置说明:
sentinel monitor xxx quorum(法定数),即至少需要2个 Sentinel 同意主服务器不可用时才会触发故障转移)
验证:
redis-cli -p 26379 sentinel master ml_redismaster
redis-cli -p 26379 sentinel slaves ml_redismaster
redis-cli -h 192.168.58.4 -p 6379 -a bird info replication 查看该节点角色
五,代码例子:
import time
import random
from redis.sentinel import Sentinel
from redis.exceptions import ConnectionError
# 配置Sentinel
sentinel = Sentinel([
('192.168.58.14', 26379),
('192.168.58.14', 26380),
('192.168.58.4', 26379)
], socket_timeout=0.1, password='bird')
def get_master_slave(sentinel, master_name):
""" 获取主从服务器的连接 """
try:
master = sentinel.master_for(master_name, socket_timeout=0.1, password='bird')
slave = sentinel.slave_for(master_name, socket_timeout=0.1, password='bird')
return master, slave
except ConnectionError:
print("连接主服务器失败,正在尝试重新连接...")
return None, None
master_name = 'ml_redismaster'
master, slave = get_master_slave(sentinel, master_name)
try:
while True:
if not master:
# 如果主服务器连接失败,则尝试重新获取
master, slave = get_master_slave(sentinel, master_name)
if not master:
print("故障转移可能正在进行,等待后重试...")
time.sleep(1)
continue
# 生成随机键值对
key = f"key{random.randint(1, 10000)}"
value = f"value{random.randint(1, 10000)}"
try:
# 写入操作
master.set(key, value)
# 读取操作
retrieved_value = slave.get(key)
print(f"Set {key} to {value}, retrieved {retrieved_value}")
except ConnectionError as e:
print(f"操作失败: {e}")
master, slave = None, None # 重置连接
# 休眠一秒,模拟实际操作间隔
time.sleep(0.5)
except KeyboardInterrupt:
print("测试被用户中断。")