前言
从主从复制到哨兵模式。
一、主从复制
1.概述
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。
- 前者称为主节点(master / leader),后者称为从节点(slave/follower)。
- 数据的复制是单向的,只能由主节点到从节点。
- Master 以写为主,Slave 以读为主。
- 一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
- 默认情况下,每台 Redis 服务器都是主节点。
2.作用
数据冗余
主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复
当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复。这也是一种服务的冗余。
负载均衡
在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载。
尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
高可用
主从复制是哨兵和集群能够实施的基础,因此说主从复制是 Redis 高可用的基础。
一般来说,要将 Redis 运用于工程项目中,只使用一台 Redis 是万万不能的,原因如下:
- 结构上:单个 Redis 服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大。
- 容量上:单个 Redis 服务器内存容量有限,一般来说,单台 Redis 最大使用内存不应该超过 20G。
应用
电商网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是多读少写。
对于这种场景,我们可以使用如下这种架构:
3.模拟实践
搭建场景
进入redis.conf所在文件夹,复制三个redis.conf文件
cp redis.conf redis6379.conf cp redis.conf redis6380.conf cp redis.conf redis6381.conf
修改复制的文件
修改 redis6379.conf内的以下属性:
daemonize yes pidfile /var/run/redis_6379.pid logfile "6379.log" dbfilename dump6379.rdb
修改 redis6380.conf内的以下属性:
daemonize yes port 6380 pidfile /var/run/redis_6380.pid logfile "6380.log" dbfilename dump6380.rdb
修改 redis6381.conf内的以下属性:
daemonize yes port 6381 pidfile /var/run/redis_6381.pid logfile "6381.log" dbfilename dump6381.rdb
启动三个redis服务器
redis-server /usr/local/redis6379.conf redis-server /usr/local/redis6380.conf redis-server /usr/local/redis6381.conf
查看
ps -ef|grep redis
说明已启动成功。
开三个窗口分别客户端连接三个服务
redis-cli -p 端口号 -a 密码 //没有密码不需要 -a 选项
redis-cli -p 6379 -a 123456 redis-cli -p 6380 -a 123456 redis-cli -p 6381 -a 123456
模拟实践
主要命令
info replication # 查看当前库信息 slaveof 主库IP 主库端口 # 指定主库(配从库不配主库)
查看三个库的信息
三个库的前两个信息都一样,目前都是主机且都没有从机(默认三个都是主机):
配置一个主机(master),两个从机(slave)
slaveof host port # 找谁当老大
在6380和6381窗口输入以下命令:
slaveof 127.0.0.1 6379
查看6379、6380、6381信息:
主机赋值,从机取值,实现读写分离
在主机6379窗口赋值,两个从机都能获取到,但是从机不能赋值(会报错)。主机中的所有信息和数据都会自动被从机保存,
主机断开
这时从机依然是从机且正常工作。
主机再次恢复
主机恢复后再赋值,从机依然能够读取到,这样可以保证高可用。
从机断开
从机断开后,主机赋了新值,从机启动后无法获取到新值,原因是从机启动后又默认为主机了。
如果想从机断开再启动还为从机,就不要用命令行配置主机从机(只是临时配置),可以采取配置文件(redis.conf)直接指定(永久的):
只要谋位的从机由主机变回从机,立马会从主机中获值。
谋朝篡位
主机断开后,从机如果想要当主机,可以使用 slaveof no one
进行“谋朝篡位”,从而变成主机。
但此时其他节点还是很“忠心”,依然认定之前的主机为主机,这样变成的主机是没有从机的,是个“孤家寡人”。
主机如果恢复,可以“平息叛乱”,之前的从机依旧认定它为主机,但是变成主机的那个从机不再认定原主机了。
如图可看出从机已经变成主机:
主机恢复,可以看出只有一个从机了(6781):
从机复制主机信息数据的原理
改朝换代
前面的操作在实际场景中并不适用,因为我们希望的是主机断开后有从机作为主机,依旧实现主从复制。
所以在从机“谋朝篡位”后,还需要让剩余的从机“认主”,让他们都“归顺”于新的主机,但是这种需要自己在主机消失后,手动配置修改从机认定的主机。
这样原来的主机恢复后就变成了“孤家寡人”。
有没有好的方法让主机消失后,其中一个从机自动变成主机继续实现主从复制,避免故障呢,下面就要开始讲诉哨兵模式了。
二、哨兵模式
1.概述
- 主从切换技术的操作是:当主机宕机后,需要手动把一台从机切换为主机。这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
- Redis 从 2.8 开始正式提供了 Sentinel(哨兵) 架构来解决这个问题。它是“谋朝篡位”的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从机转换为主机。
- 哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。
这里的哨兵有两个作用:
- 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主机和从机。
- 当哨兵监测到 master 宕机,会自动将 slave 切换成 master,然后通过发布订阅模式通知其他的从机,修改配置文件,让它们切换主机。然而一个哨兵进程对 Redis 服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。
各个哨兵之间还会进行监控,这样就形成了多哨兵模式:
假设主机宕机,哨兵 1 先检测到这个结果,系统并不会马上进行 failover(故障转移) 过程,仅仅是哨兵 1 主观的认为主机不可用,这个现象称为主观下线。
当后面的哨兵也检测到主机不可用,并且数量达到一定值时,哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行 failover 操作。
切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从机实现切换主机,这个过程称为客观下线。
2.配置使用
这里演示一个哨兵监测一个主机。
在 redis 目录下新建 myconfig 目录,并创建文件 sentinel.conf
具体看自己,我是在/usr/local目录下创建的myconfig,并在myconfig内创建 sentinel.conf
文件名必须为 sentinel.conf
mkdir myconfig cd myconfig/ vim sentinel.conf
编写sentiel.conf
sentinel monitor myredis 127.0.0.1 6379 1 # sentinel monitor 被监控的名称 host port 1
末尾的 1 代表选票达到多少时选举成功
启动
在myconfig上一级文件输入以下命令:
redis-sentinel myconfig/sentinel.conf
主机断开
主机断开后,哨兵进程会监测到,然后发起选举,调用选举算法,最后选举 6380 为新的主机,6381 也认定其为主机。
主机恢复
之前断开的主机恢复后,哨兵进程也会检测到,但此时并不会将其再设为主机,而是设为新的主机的从机。
3.优缺点
优点:
- 哨兵集群模式是基于主从模式的,所有主从的优点,哨兵模式同样具有。
- 主从可以切换,故障可以转移,系统可用性更好。
- 哨兵模式是主从模式的升级,系统更健壮,可用性更高。
缺点:
- Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
- 实现哨兵模式的配置也不简单,甚至可以说有些繁琐。
4.sentinel.conf完整配置
# 哨兵 sentinel 实例运行的端口 默认 26379 port 26379 # 哨兵 sentinel 的工作目录 dir /tmp # 哨兵 sentinel 监控的 redis 主节点的 ip port # master-name 可以自己命名的主节点名字:只能由字母 A-z、数字 0-9、".-_"这三个字符组成。 # quorum 配置多少个 sentinel 哨兵统一认为 master 主节点失联那么这时客观上认为主节点失联了 # sentinel monitor <master-name> <ip> <redis-port> <quorum> sentinel monitor mymaster 127.0.0.1 6379 2 # 当在 Redis 实例中开启了 requirepass foobared 授权密码 这样所有连接 Redis 实例的客户端都要提供密码 # 设置哨兵 sentinel 连接主从的密码,注意必须为主从设置一样的验证密码 # sentinel auth-pass <master-name> <password> sentinel auth-pass mymaster MySUPER--secret-0123passw0rd # 指定多少毫秒之后,主节点没有应答哨兵 sentinel,此时,哨兵主观上认为主节点下线,默认 30 秒 # sentinel down-after-milliseconds <master-name> <milliseconds> sentinel down-after-milliseconds mymaster 30000 # 这个配置项指定了在发生 failover 主备切换时最多可以有多少个 slave 同时对新的 master 进行同步 # 这个数字越小,完成 failover 所需的时间就越长 # 但是如果这个数字越大,就意味着越多的 slave 因为 replication 而不可用 # 可以通过将这个值设为 1 来保证每次只有一个 slave 处于不能处理命令请求的状态 # sentinel parallel-syncs <master-name> <numslaves> sentinel parallel-syncs mymaster 1 # 故障转移的超时时间 failover-timeout 可以用在以下这些方面: # 1. 同一个 sentinel 对同一个 master 两次 failover 之间的间隔时间 # 2. 当一个 slave 从一个错误的 master 那里同步数据开始计算时间。直到 slave 被纠正为向正确的 master 那里同步数据时。 # 3. 当想要取消一个正在进行的 failover 所需要的时间。 # 4. 当进行 failover 时,配置所有 slaves 指向新的 master 所需的最大时间。 # 不过,即使过了这个超时,slaves 依然会被正确配置为指向 master,但是就不按 parallel-syncs 所配置的规则来了 # 默认三分钟 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout mymaster 180000 # SCRIPTS EXECUTION # 配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。 # 对于脚本的运行结果有以下规则: # 若脚本执行后返回 1,那么该脚本稍后将会被再次执行,重复次数目前默认为 10 # 若脚本执行后返回 2,或者比 2 更高的一个返回值,脚本将不会重复执行。 # 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为 1 时的行为相同。 # 一个脚本的最大执行时间为 60s,如果超过这个时间,脚本将会被一个 SIGKILL 信号终止,之后重新执行。 # 通知型脚本:当 sentinel 有任何警告级别的事件发生时(比如说 redis 实例的主观失效和客观失效等),将会去调用这个脚本 # 这时这个脚本应该通过邮件,SMS 等方式去通知系统管理员关于系统不正常运行的信息。 # 调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。 # 如果 sentinel.conf 配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则 sentinel 无法正常启动成功。 # 通知脚本 # sentinel notification-script <master-name> <script-path> sentinel notification-script mymaster /var/redis/notify.sh # 客户端重新配置主节点参数脚本 # 当一个 master 由于 failover 而发生改变时,这个脚本将会被调用,通知相关的客户端关于 master 地址已经发生改变的信息。 # 以下参数将会在调用脚本时传给脚本: # <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port> # 目前 <state> 总是 “failover”,<role> 是 “leader” 或者 “observer” 中的一个。 # 参数 from-ip,from-port,to-ip,to-port是用来和旧的 master 和新的 master (即旧的 slave)通信的 # 这个脚本应该是通用的,能被多次调用,不是针对性的。 # sentinel client-reconfig-script <master-name> <script-path> sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
总结
以上就是哨兵模式的详细讲解。