主从配置:
- 将redis中的redis.conf拷贝到/etc/redis/redis.conf 。
- 将/etc/redis/redis.conf拷贝一份,命名为slave.conf到当前目录下。
- 打开slave.conf,修改port( 默认port 6379)为6380。
- 修改从机的配置文件(
slave.conf
),设置slaveof 127.0.0.1 6379
# 表示6380启动的redis服务从属于6379。 - 查看主从关系:进入到redis中:info Replication
- 也可以直接info 可以查看所有的信息
Sentinel 哨兵
为了保证redis最大程度上能够使用,redis提供了主从同步+Sentinel哨兵机制。(对于集群而言 默认开启了哨兵,所以不需要开启)
redis安装后自带哨兵功能
https://redis.io/topics/sentinel
redis提供的哨兵是用来看护redis实例进程的,可以自动进行故障转移,其功能如下:
- Monitoring. 监视 监视那个主机是否可用–判断方式:redis和哨兵之间会实时通讯 哨兵通过这个端口,进行通讯(tcp通讯) ,判断主机是否可以正常使用,称为心跳机制
- Notification. 提供通知事件 通知主从的可用性
- Automatic failover. 自动故障转移 当主机无法正常工作时,会选出一个从充当主 主再次运行起来后 降级为从
- 问题:连接的ip地址和端口号不会改变,如果连接了从机 如何进行操作?
- Configuration provider. 配置的提供者 将哨兵配置好 ip的配置由哨兵进行 配置
在redis安装后,会自带sentinel哨兵程序,我们只需要修改sentinel.conf配置文件,即可使用哨兵
bind 127.0.0.1 #哨兵的ip
port 26380 #哨兵的端口号
daemonize yes #守护进程
logfile /var/log/redis-sentinel.log #哨兵运行的日志
sentinel monitor mymaster(对哨兵看护redis的主从起个名字) 127.0.0.1 6380 2 #指明集群中任何一台redis的ip地址端口号
sentinel down-after-milliseconds mymaster 30000#心跳机制的判断时间 30000毫秒 30秒后无反应 认为主已经宕机了
sentinel parallel-syncs mymaster 1#指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步
sentinel failover-timeout mymaster 180000#等待180秒后 主仍然没有恢复的话 就进行故障转移
- sentinel monitor mymaster 127.0.0.1 6380 2 说明
- mymaster 为sentinel监护的redis主从集群起名
- 127.0.0.1 6300 为主从中任一台机器地址,可以通过这个找到所有的主从
- 2 表示有两台以上的哨兵认为某一台redis宕机后,才会进行自动故障转移。 一般要大于一半的哨兵认为宕机才判断成功,所以配置哨兵的最少数量为3
哨兵的启动方式:
redis-sentinel sentinel.conf
高可用方案注意事项
- 至少三个sentinel以上
- sentinel要分散运行在不同的机器上,一般情况下,每个redis服务器上将有一个哨兵
代码中哨兵的实现
Python客户端使用
# redis 哨兵
#写明所有服务器的ip地址和端口号
REDIS_SENTINELS = [
('127.0.0.1', '26380'),
('127.0.0.1', '26381'),
('127.0.0.1', '26382'),
]
#设置该主从集的名字
REDIS_SENTINEL_SERVICE_NAME = 'mymaster'
#哨兵模块
from redis.sentinel import Sentinel
_sentinel = Sentinel(REDIS_SENTINELS) 获得 一个哨兵
#主机和从机的获得 由哨兵自动从配置文件中获得
redis_master =
_sentinel.master_for(REDIS_SENTINEL_SERVICE_NAME)# 获取redis连接(主)
redis_slave = _sentinel.slave_for(REDIS_SENTINEL_SERVICE_NAME)#获取redis连接(从)
使用示例
# 读数据,master读不到去slave读
try:
real_code = redis_master.get(key)
except ConnectionError as e:
real_code = redis_slave.get(key)
# 写数据,只能在master里写
try:
current_app.redis_master.delete(key)
except ConnectionError as e:
logger.error(e)