一、Redis主从复制
一)理论知识讲解
1、实现主从复制
- 从 Redis 2.8 开始,使用异步复制。
- 一个主服务器可以有多个从服务器。
- 从服务器也可以有自己的从服务器。
- 复制功能不会阻塞主服务器。
- 可以通过复制功能来让主服务器免于执行持久化操作,由从服务器去执行持久化操作即可
2、全量复制(redis2.8以前)
1、全量复制的流程
2、全量复制开销
- bgsave时间
- RDB文件网络传输时间
- 从节点清空数据时间
- 从节点加载RDB时间
- 可能的AOF重写时间:RDB加载完毕后,若开启了AOF参数,会进行AOF重写,以保证AOF是最新的状态
3、全量复制的问题
master与slave之间的网络发生了抖动,这段时间的数据就会丢失
2、Redis部分复制(Redis2.8之后添加的功能)
1、部署复制的流程
2、部分复制解决了全量复制的网络抖动导致数据丢失的问题
master在写的时候,会写一份复制缓冲区的命令;
- 当网络抖动结束后,slave会发送pysnc {offset} {runId}告知自己目前偏移量(数据所处的位置)
- 当master收到slave的偏移量后,看是否在buffer中,若在返回给slave一个CONTINUE,随后发送slave缺失数据到相应的slave
(buffer默认是1M,为了保证数据的完整性,可以配置大一些)
4、故障处理
没有设置自动转移,只能自己手工操作处理
架构图,如下
1、slave宕机
slave宕机如图
手动解决
2、mater宕机
手动解决
4、优化架构,解决主从复制故障转移问题
5、开发与运维中的问题
1、问题汇总
- 读写分离
- 主从配置不一致
- 规避全量复制
- 规避复制风暴
2、读写分离
- 读写分离:读流量分摊到从节点
- 可能遇到的问题
- 复制数据延迟:读写数据不一致
- 惰性删除 主节点处理读取命令时,自动检测键的时间,如果超时自动删除
- 定时删除 在内部循环,定期查看键有没有过期,如果过期自动删除,之后同步给从节点
- 从节点故障
3、配置不一致
- maxmemory设置不一致:丢失数据(避免此问题,通过配置管理工具标准化安装、配置)
- 数据结构优化参数(利润比hash-max-ziplist-entries):内存不一致
4、规避全量复制
- 第一次全量复制
- 第一次不可避免
- 操作时间:小主节点、低峰时操作
- 节点运行ID不匹配
- 主节点重启(运行ID变化)
- 故障转移:例如哨兵或者集群
- 复制积压缓冲区不足
- 网络中断,部分复制无法满足
- 增大复制缓冲配置rel_backlog_size,网络"增强" 规避复制风暴(计算每分钟可以写入多少字节 * 故障处理分钟数)
5、规避复制风暴
详情见连接:javascript:void(0)
什么是复制风暴?举例:我们master重启,其master下的所有slave检测到RunID发生变化,导致所有从节点向主节点做全量复制。尽管redis对这个问题做了优化,即只生成一份RDB文件,但需要多次传输,仍然开销很大。
- 单主节点复制风暴 太多从节点
- 单机复制风暴 机柜
二)redis主从复制实战
1、redis主从架构
当数据量变得庞大的时候,读写分离还是很有必要的。同时避免一个redis服务宕机,导致应用宕机的情况,我们启用sentinel(哨兵)服务,实现主从切换的功能。redis提供了一个master,多个slave的服务。
准备三个redis服务,依次命名文件夹子master,slave1,slave2.这里为在测试机上,不干扰原来的redis服务,我们master使用6000端口。
2、修改Redis主从的配置
注意:配置文件的位置,根据实际情况更改
1、配置详解
2、master修改配置
3、slave1修改配置
4、slave2修改配置
requirepass:是认证密码,应该之后要作主从切换,所以建议所有的密码都一致。masterauth是从机对主机验证时,所需的密码(即主机的requirepass)。
3、启动主机
注意:配置文件的位置,根据实际情况更改
1、启动master
2、启动slave
3、查看启动后进程和端口
4、验证主从复制
1、master
2、slave1
3、slave2
可以看到主机执行写命令,从机能同步主机的值,主从复制,读写分离就实现了。
二、Redis主从复制哨兵sentinel模式(主从切换)
一)redis哨兵sentinel概述
万一主机挂了怎么办,这是个麻烦事情,所以redis提供了一个sentinel(哨兵),以此来实现主从切换的功能,类似与zookeeper。
注意:配置文件的位置,根据实际情况更改
启动三个哨兵:建议配置节点个数是基数(>=3)
哨兵sentinel官网链接:https://redis.io/topics/sentinel
1、Sentinel的基本知识
- 您需要至少三个Sentinel实例才能实现可靠的部署。
- 三个Sentinel实例应放置在相信独立失败的计算机或虚拟机中。例如,不同的物理服务器或虚拟机在不同的可用区域上执行。
- 由于Redis使用异步复制,Sentinel + Redis分布式系统不能保证在故障期间保留已确认的写入。然而,有些方法可以部署Sentinel,使窗口可以丢失局限于某些时刻的写入,而另外还有其他安全性较低的部署方式。
- 您的客户需要支持Sentinel。受欢迎的客户端库支持Sentinel,但不是全部。
- 如果您不在开发环境中进行不定期测试,或者在生产环境中可以更好地进行测试(如果可行),那么就没有安全的HA设置。你可能有一个错误的配置,只有当它太迟了(凌晨3点,当你的主站停止工作时)才会显现出来。
- Sentinel,Docker或其他形式的网络地址转换或端口映射应该小心:Docker执行端口重新映射,打破其他Sentinel进程的Sentinel自动发现以及主服务器的从属列表。有关更多信息,请查看本文后面有关Sentinel和Docker的部分。
2、三个定时任务
1、没10秒每个sentinel对master和slave执行info
- 发现slave
- 确认主从关系
2、每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
- 通过_sentinel_:hello频道交互
- 交互对节点的“看法”和自身信息
3、每1秒每个sentinel对其他sentinel和redis执行ping
- 心跳检测,失败判定依据
二)Redis哨兵(sentinel)实现主从切换部署
1、配置 三个sentinel进程
master的sentinel.conf
slave1的sentinel.conf
slave2的sentinel.conf
2、启动sentinel服务(到对应的目录执行相应的命令)
启动方式一:
如果您使用的是redis-sentinel
可执行文件(或者如果您的可执行文件具有该名称的符号链接redis-server
),则可以使用以下命令行运行Sentinel:
启动方式二:
查看日志
从对应的日志观察到,一个master服务,两个slave服务。
3、验证
1、 直接验证:哨兵
新开一个命令行窗口进入redis的src目录,用redis-cli工具登录其中一个哨兵
连接成功后运行如下命令
2、故障验证:master宕机
查看日志
master切换了,当6000端口的这个服务重启的时候,他会变成6001端口服务的slave。
因为sentinel在切换master的时候,把对应的sentinel.conf和redis.conf文件的配置修改。
期间我们还需要关注的一个问题:sentinel服务本身也不是万能的,也会宕机,所以我们还得部署sentinel集群,象我这样多启动几个sentinel。
注意这个配置:
三)故障切换过程
1、主观下线和客观下线
sentinel monitor <masterName> <ip> <port> <quorum>
sentinel down-after-milliseconds <masterName> <timeout>
主观下线:每个sentinel节点对Redis节点失败的“偏见”
客观下线:所有sentinel节点对Redis节点失败“达成共识”(超过quorum个统一)
sentinel is-master-down-by-addr 问其他sentinel节点,是否同意master下线
2、领导者选举
原因:仅需要一个sentinel节点完成故障转移
选举:通过sentinel is-master-down-by-addr命令都希望成为领导者
- 每个做主观下线的sentinel节点向其他sentinel节点发送命令,要求将它设置为领导者
- 收到命令的sentinel节点若没有同意过其他sentinel节点发送的命令,那么将同意该请求,否则拒绝
- 若该sentinel节点发现自己的票数已经超过sentinel集合半数且超过querum,那么它将成为领导者
- 若此过程有多个sentinel节点成为了领导者,那么将等待一段时间重新进行选举
3、故障转移(sentinel领导者节点完成)
- 从slave节点中选出一个“合适的”节点作为新的master节点
- 对上面的slave节点执行slaveof no one命令让其成为master节点
- 向剩余的slave节点发送命令,让它们成为新master节点的slave节点,复制规则和parallel-syncs参数有关(parallel-syncs设置的数据,根据新master的系统资源进行配置,设置为1是顺序执行RDB文件和buffer的发送)
- 更新对原来master节点配置为slave,并保持着对其“关注”,当其恢复后命令它去复制新的master节点
4、选择“合适的”slave节点(需要另外配置)
- 选择slave-priority(slave节点优先级)最高的slave节点,若存在则返回,不存在则继续(默认不配置)
- 选择复制偏移量最大的slave节点(复制的最完整),若存在则返回,不存在则继续
- 选择runId最小的slave节点
四)客户端接入
1、客户端接入原理
2、客户端接入流程
- sentinel地址集合
- masterName
- 不是代理模式
3、各种语言接入sentinel
1、java接入sentinel
java接入sentinel
2、python接入sentinel
python接入sentinel
3、php接入sentinel
php接入sentinel
五)常见的开发运维问题
1、节点运维
1、何时需要节点下线
- 机器下线:例如过保等情况
- 机器性能不足:例如CPU、内存、磁盘、网络等
- 节点自身故障:例如服务不稳定等
2、节点下线
主节点下线
从节点下线
临时下线(暂时关闭)还是永久下线,例如是否做一些请理工作(RDB、AOF等)。要考虑读写分离的情况
sentinel节点下线(同上)
3、节点上线
主节点:sentinel failover进行替换
从节点:slaveof即可,sentinel节点可以感知
sentinel节点:参考其他sentinel节点启动即可
2、常见的开发问题:高可用读写分离