分布式存储-Redis持久化&高可用
分布式存储-Redis持久化&高可用
我们知道Redis很强大的一部分原因是因为它的数据是存储在内存中的,那如果服务器挂了之后,是不是我们的数据会丢失了呢?那我们需要把内存中的数据通过一个机制给它持久化,从而对数据的安全进行保障。本篇会聊到:
- 两种数据存储机制【RDB】 和【AOF】
- 哨兵模式
Redis的持久化机制
RDB【快照模式】:在某个时间段把当前的内存中数据进行一个存储【 默认】
这种方式适合【灾备】,但是在备份的间隔时间可能造成一部分数据丢失
触发方法->
- 自定义规则配置。在redis.conf中有一个save的命令行 第一个参数是 【save命令】 第二个参数是 【second】 第三个参数是 【change】。举例而言:如果在900s内有任何一个key发生变化他都会去触发一个快照。
我们可以尝试修改
5s中有一个key变化,就生成它的快照文件。当我们修改后就会生成一个dump文件,这个文件的位置我们可以使用redis-config中的dir参数进行指定。我们要保障他是数据的安全性,我们就可以写脚本,不断的把dump进行备份。当出现危险情况,把dump文件还原,就可以恢复数据了。
- 可以执行SAVE(同步-阻塞)命令和BGSAVE(异步-非阻塞)命令
- 执行FLASHALL命令(执行这个命令的时候出发快照)
- Master-replicate(复制的时候)
AOF【Append Only File】:采用日志的方式来保存每个事务操作,他会把每个操作都写在文件中。
【配置方式(redis config中)】:我们可以把no 改成 yes,然后重启配置文件,我们发现appendonly.aof文件会生成到我们指定的文件路径下面(dir中指定的,和dump文件在同样的目录下)。当我们打开这个文件发现什么都没有
、
我们插入几个数据到redis中就会在这个文件中生成相关的数据,其实它存储的数据和咱们在手写redis客户端的那里的命令是一样的
那么他是实时同步数据到这个文件中的吗?这点其实我们可以配置,根据我们的cpu和数据数据安全程度进行权衡。
- no:交给操作系统进行同步(默认30s)。
- everysec:默认/S都进行同步。
- always:每个命令实时同步
但是这引发了一个弊病:每次事务操作都进行记录,那么这个文件必然是越来越大的,这对于我们后来的解析是很不友好的,这个时候就引出了rewrite
【rewrite】:把无效的指令全部都进行压缩,本质其实是重新生成当前的AOF文件,这是因为如果去修改这个的AOF文件的话,那样的时间和效率的代价太大,生成文件之后对老的AOF文件进行覆盖
- 自动触发重写
![]()
- 【rewrite-percentage】:当当前的AOF的文件大小超过上一个AOF文件的百分之多少(我们自己配置的)的时候就会进行重写:
- 【rewrite-min-size】:不会进行重写的最小大写(当文件小于64mb的时候不会进行重写)
- 手动触发重写(bgrewriteaof)
问题:会不会在写AOF的时候有些数据没有写入?
主进程在进行数据操作的时候,他会把数据保存在一个重写缓存中,换而言之,他会单独开辟一块空间去存储在重写期间接受到的命令,然后在重写完成后把重写的文件再次追加到新的AOF文件中。所以不会的。
Redis的高可用
主从复制:下面有多种方式可以进行选择,这些不仅可以应用在redis上,其实在很多 情况下都可以使用,比如数据库。
- 【一主多从】:所有的事务操作全部访问master,slave进行读的操作。这样的好处就是我们可以对slave进行水平扩容,当读多写少的情况下。但是当有多个slave的情况下,master同步数据给slave的压力就变大了,这个时候就可以采用级联复制【由一个slave去同步数据给其他slaves】
- 【双主复制(双亲热备)】:其实他们有两个角色【master、backup】,并且在同一个时刻只有一个节点在进行工作,但是这两个节点都是输入运行状态。然后在这两个前面假设一个Keepalived,他会不断发送心跳去确定master的状态,如果master挂了,他就会把backup作为新的master进行顶替
- 【多主一从】:把不同master上的数据放在同一个slave上去进行数据统计和汇总
一主多从配置&准备
- 准备三个节点,并且都安装好redis
- 关闭防火墙 systemctl stop firewalld / fifirewall-cmd --zone=public --add-port=6379/tcp --permanent
- 配置slave 在config中加上 replicaof <masterip > <masterport>
- 启动子节点,这个时候我们发现,其实启动的时候,master的数据就自动同步到slave中了,并且我们可以使用 【info replication】查看他的角色
同步原理(RDB模式):
- slave连接到master服务器发送一个sync指令
- master接受到指令后执行一个bgsave指令生成快照,并且发送快照给slave服务器
- slave接受到快照后覆盖自己的快照文件
- 如果在生成快照的时候有新的命令执行,master会把新的命令放在缓存中,当我们slave收到了快照文件后,再把新增的增量的指令同步到slave节点
slave告诉master自己的端口,然后手动发送一个sync命令给master,这个时候就是【全量同步】
这个时候在别的节点上执行一个set指令
我们发现他的指令就自动同步到其他的节点,这个叫做【增量同步】
默认情况下是异步进行同步的,意味着master只要完成客户端请求后,立刻返回给客户端,不管是否同步给slave,当然我们可以修改这个机制。
- master可以写的前提是,他的数据是已经同步给了3个节点
- 允许slave最长失去联系的时间是10s
哨兵模式:
使用上面的一主多从进行主从复制的问题是,如果master节点挂了怎么办?所以这就引出了哨兵模式。他的功能为:
- 【监控】:Sentinel会不断检查主服务器和从服务器是否正常运行。
- 【通知】:如果某一个被监控的实例出现问题,Sentinel可以通过API发出通知。
- 【自动故障转移(failover)】:如果主服务器发生故障,Sentinel可以启动故障转移过程。把某台服务器升级为主服务器,并发出通知。
- 【配置管理】:客户端连接到Sentinel,获取当前的Redis主服务器的地址。
其实他就是监控redis中的所有节点的一个进程,当然他也可以做集群。当master挂了之后, 他就可以从其他的slave中重新选举出一个master.在这种哨兵机制下,客户端连接的就是哨兵的地址,而不是master的地址。
【哨兵配置】:sentinel是redis自带的,这个文件本身就有,一般和redis,conf在一个文件下
在sentinel.confi配置监听的master
- mymaster:自己起的一个哨兵的名字
- 192.168.221.128: master的ip
- 6379:mater的端口
- 2:最低的投票通过次数(至少两个哨兵认为master挂了,才算真的挂了 哨兵可以做集群)
【配置心跳超时时间:】这里的意思是5s后,master没有响应,那哨兵就认为master挂了
【配置容错机制】: 一定时间master还没有活过来就启动 failover【进行选举】
![]()
【 启动sentinel】
【 查看 日志 】
这个时候启动其他两个slave的sentinel按照同样的方式,我们发现在master的sentinel的日志中打印了他们的日志
这个时候我们的架构就是
模拟master宕机,看看是否会进行选举。查看哨兵的日志发现:
- sdown指的是当前的哨兵的主观认为
- vote-for-leader:指的是进行投票
- odown:指的是三分之二的哨兵都认为maser宕机了
- next failover delay:在咱们配置中指定的时间【容错机制的时候讲到了这个】内如果master没有启动那就证明要进行重新选举
- switch master:这个时候就选举一个新的master
这个时候发现原来的slave变成了master
【常见问题】:
谁来进行故障转移:当通过上面的机制确定了master已经挂了之后,谁来把剩下的slave变成master?
其实每次当master出现故障,他们都会使用raft 机制选举出哨兵leader 进行故障转移。raft我们后面会聊到
故障转移的过程是什么:
- 由Sentinel Leader向某个节点发送slaveof no one命令,让它成为独立节点
- 然后向其他节点发送replicaof x.x.x.x xxxx(本机服务),让它们成为这个节点的子节点,故障转移完成。
- 断开连接时长,如果与哨兵连接断开的比较久,超过了某个阈值,就直接失去了选举权
-
优先级排序,如果拥有选举权,那就看谁的优先级高,这个在配置文件里可以设置(replicapriority 100),数值越小优先级越高
-
复制数量,如果优先级相同,就看谁从master中复制的数据最多(复制偏移量最大)
-
进程id,如果复制数量也相同,就选择进程id最小的那个