redis高级:持久化方案、主从复制原理和方案、哨兵高可用
一、持久化方案
1、什么是持久化
redis的所有数据保存在内存中,把内存中的数据同步到硬盘上这个过程称之为持久化
ps:redis是默认使用自动持久化的,在使用redis的时候我们如果不是强行关掉redis服务,再启动,就可以看到之前设置的数据。因为正常退出或执行shutdown关闭redis连接的时候会自动持久化生成rdb文件
2、持久化的实现方式
实现持久化有两类
方式:
- 快照:记录某时某刻的数据,把他当作一个备份
举例:
1、mysql的Dump
2、redis的RDB
- 写日志:我们执行任何操作的时候,都会在日志上记录下来,需要恢复数据的时候,只要把日志记录的命令重新执行一遍即可
举例:
1、mysql的 Binlog
2、Redis的 AOF
Redis支持两种持久化方式:RDB和AOF。
3、RDB
RDB是Redis默认的持久化方式,它会周期性地将Redis中的数据快照保存到磁盘上,生成一个RDB文件。RDB文件是一个二进制文件,包含了Redis在某个时间点上的数据状态。RDB持久化的优点是占用空间小,恢复速度快,适合用于备份和灾难恢复。缺点是可能会出现数据的丢失,因为RDB是定时快照,如果Redis进程在快照之前崩溃,会导致数据的丢失。
前面我们提到redis默认就是自动使用持久化的,如果我们在退出之后,进入redis文件夹内部的data文件夹内,可以看到一个rdb文件,他就是缓存文件,删除之后,我们再启动redis,就没有之前的数据了
但是我们强行关掉服务,redis并没有生成持久化的rdb文件,这会导致最近一段时间的数据丢失
ps:rdb文件在每次执行持久化操作的时候都会替换掉之前的文件
rdb 持久化配置方式
方式一:
save
主动生成rdb持久化文件,是一个同步操作,如果数据量很大会出现阻塞的情况
方式二:
bgsave
主动生成rdb持久化文件,是一个异步持久化操作,不会阻塞住其他命令的执行
方式三:
在配置文件配置(根据配置文件自动执行持久化)
这个条件触发,就执行bgsave
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir "/root/redis-6.2.9/data"
如果60s中改变了1w条数据,自动生成rdb
如果300s中改变了10条数据,自动生成rdb
如果900s中改变了1条数据,自动生成rdb
dbfilename是配置rdb文件的名称
配置文件存储路径
以上三条符合任意一条,就自动生成rdb,内部使用bgsave
其他不常用配置:
stop-writes-on-bgsave-error yes #出现错误停止
rdbcompression yes #压缩
rdbchecksum yes #校验
其他知识点
1、rdb持久化是全量复制
没有执行save和bgsave没有添加rdb策略,还会生成rdb文件,如果开启主从复制,主会自动生成rdb
2、debug reload
debug级别的重启,不会将内存中的数据清空
3、shutdown save
关闭会出发rdb的生成
把save替换成nosave就是不持久化
4、redis的src文件夹中有一个 redis-check-rdb 可执行文件,他可以校验rdb文件是否正确
4、aof方案
在学习rdb的时候我们可以发现,他会出现数据丢失的问题,因此可以用aof方案处理
ps:如果redis只是用来做缓存,那丢了也没什么关系
RDB问题
耗时,耗性能:
不可控,可能会丢失数据
AOF介绍
客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复
AOF的三种策略
日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上
- always:redis–》写命令刷新的缓冲区—》每条命令fsync到硬盘—》AOF文件
- everysec(默认值):redis——》写命令刷新的缓冲区—》每秒把缓冲区fsync到硬盘–》AOF文件
- no:redis——》写命令刷新的缓冲区—》操作系统决定,缓冲区fsync到硬盘–》AOF文件
命令 | always | everysec | no |
---|---|---|---|
优点 | 不丢失数据 | 每秒一次fsync,丢失1秒数据 | 不用管 |
缺点 | IO开销大,一般的sata盘只有几百TPS | 丢1秒数据 | 不可控 |
AOF重写
随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题
举例:
原生AOF | 重写后的AOF |
---|---|
set hello world set hello java set hello hehe incr counter incr counter rpush mylist a rpush mylist b rpush mylist c 过期数据 | set hello hehe set counter 2 rpush mylist a b c |
本质就是把过期的,无用的,重复的,可以优化的命令,来优化
这样可以减少磁盘占用量,加速恢复速度
AOF重写配置参数
配置名 | 含义 |
---|---|
auto-aof-rewrite-min-size | AOF文件重写需要尺寸 |
auto-aof-rewrite-percentage | AOF文件增长率 |
自动触发时机(两个条件同时满足):
aof_current_size>auto-aof-rewrite-min-size:当前尺寸大于重写需要尺寸
(aof_current_size-aof_base_size)/aof_base_size>auto-aof-rewrite-percentage:(增长率)当前尺寸减去上次重写的尺寸,除以上次重写的尺寸如果大于配置中的增长率
统计名 | 含义 |
---|---|
aof_current_size | AOF当前尺寸(单位:字节) |
aof_base_size | AOF上次启动和重写的尺寸(单位:字节) |
AOF重写配置
# aof持久化的配置 appendonly yes #将该选项设置为yes,打开 appendfilename "appendonly.aof" #文件保存的名字 appendfsync everysec #采用第二种策略 no-appendfsync-on-rewrite yes #在aof重写的时候,是否要做aof的append操作,因为aof重写消耗性能,磁盘消耗,正常aof写磁盘有一定的冲突,这段期间的数据,允许丢失
ps:aof重写可以使用配置文件触发,也可以手动触发:
python
bgrewriteaof
5、RDB和AOF的选择
rdb和aof的比较
命令 | rdb | aof |
---|---|---|
启动优先级 | 低 | 高(挂掉重启,会加载aof的数据) |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
轻重 | 重 | 轻 |
rdb最佳策略
rdb关掉,主从操作时
集中管理:按天,按小时备份数据
主从配置,从节点打开
aof最佳策略
开:缓存和存储,大部分情况都打开,
aof重写集中管理
everysec:通过每秒刷新的策略
最佳策略
小分片:每个redis的最大内存为4g
缓存或存储:根据特性,使用不通策略
时时监控硬盘,内存,负载网络等
ps:要有有足够内存
6、混合持久化
重启Redis时,我们很少使用RDB来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放。
但是重放AOF日志性能相对RDB来说要慢很多,这样在Redis实例很大的情况下,启动需要花费很长的时间。
Redis4.0 为了解决这个问题,带来了一个新的持久化选项 --- 混合持久化。
ps:混合持久化不是简单的同时开启aof和rdb,他们是相互不影响的
如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理
并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件
才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
于是在Redis重启的时候,可以先加载RDB的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,因此重启效率大幅得到提升
配置参数
必须先开启AOF
# 开启 aof
appendonly yes
# 开启 aof复写(这两个是主要配置)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 开启 混合持久化
aof-use-rdb-preamble yes # 这正有用的是这句话
# 关闭 rdb
save ""
ps:aof重写可以使用配置文件触发,也可以手动触发:
bgrewriteaof
二、主从复制原理和方案
1、为什么要用主从复制
我们使用redis的时候可能会出现一下问题:
- 机器故障
- 容量瓶颈(内存不够了)
- QPS瓶颈(QPS是指每秒钟能够处理的查询数)
主从解决了qps问题,机器故障问题
2、主从复制介绍
Redis主从复制是一种用于实现Redis高可用性的技术,通过将一个Redis实例(称为主节点)的数据复制到多个Redis实例(称为从节点)中,以提高系统的可用性和容错性。
在Redis主从复制中,主节点负责处理所有的写请求和读请求,从节点通过复制主节点的数据来实现读请求的负载均衡和故障转移。当主节点出现故障时,从节点中的某个节点可以被选举为新的主节点,以继续处理客户端请求。
通常来说都是:一主一从,一主多从
从库的作用如下:
1、做读写分离
2、做数据副本
3、扩展数据性能
注意事项:
一个maskter可以有多个slave
一个slave只能有一个master
数据流向是单向的,从master到slave,从库只能读,不能写,主库既能读又能写
3、redis主从赋值流程,原理
# redis主从赋值流程,原理
1. 副本(从)库通过slaveof 127.0.0.1 6379命令,连接主库,并发送SYNC给主库
2. 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3. 副本库接收后会应用RDB快照,load进内存
4. 主库会陆续将中间产生的新的操作,保存并发送给副本库
5. 到此,我们主复制集就正常工作了
6. 再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.
7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的
主库是否要开启持久化
如果不开有可能,主库重启操作,造成所有主从数据丢失!
操作命令方式配置从库
启动两台redis服务
在从库的redis客户端执行命名
slaveof 127.0.0.1 6379 #异步
ps:执行命令后从库不能写了,以后只能用来读
断开主从关系的命令
slaveof no one
配置文件中配置主从
在从库的redis配置文件中加入配置
slaveof 127.0.0.1 6379 #配置从节点ip和端口
slave-read-only yes #从节点只读,因为可读可写,数据会乱
autpass 123456
辅助配置(主库用的主从数据一致性配置)
min-slaves-to-write 1
min-slaves-max-lag 3
#那么在从服务器的数量少于1个,或者三个从服务器的延迟(lag)值都大于或等于3秒时,主服务器将拒绝执行写命令
三、哨兵高可用
1、什么是高可用
高可用性(High Availability,简称HA)是指系统在面对各种故障或异常情况时,仍能够保持正常运行的能力。在计算机系统中,高可用性通常指系统能够在出现硬件故障、软件错误、网络中断、自然灾害等情况下,继续提供服务,保证系统的可靠性和可用性。
这里可以看看阿里云,自称高可用性达:99.99%(一年内百分之99.99%的时间都是可用的)
2、哨兵实现高可用
哨兵(Sentinel)是Redis官方提供的一种用于实现Redis高可用性的解决方案。哨兵通过监控Redis主节点的状态,自动进行故障检测和故障转移,以确保Redis集群的高可用性和容错性。
主从复制不是高可用,一旦主机挂了,整个服务就没了
主从存在问题
1、主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个slave变成master(这就是哨兵)
2、主从复制,只能主写数据,所以写能力和存储能力有限(可以通过集群解决)
架构说明(工作原理)
可以做故障判断,故障转移,通知客户端(其实是一个进程),客户端直接连接sentinel的地址
在上图中我们可以看到,哨兵也是要做成高可用的
工作原理:
1 多个sentinel发现并确认master有问题
2 选举触一个sentinel作为领导
3 选取一个slave作为新的master
4 通知其余slave成为新的master的slave
5 通知客户端主从变化(通知从库)
6 等待老的master复活成为新master的slave
3、哨兵实现高可用搭建步骤
我们可以在一台设备上开启多个redis实现高可用,也可以在多态设备上实现redis高可用
步骤一
先搭建一主两从
步骤二
哨兵配置文件,启动哨兵(redis的进程,也要监听端口,启动进程有配置文件)
由于我们是在一台设备上实现哨兵高可用的,需要在不同的端口启动redis
配置参数介绍
port 26379
'redis启动的端口'
daemonize yes
'以后台进程的方式启动'
dir /root/redis/data
'日志文件保存的位置'
bind 0.0.0.0
'redis启动的ip地址'
logfile "redis_sentinel.log"
'配置日志文件的名称'
sentinel monitor mymaster 127.0.0.1 6379 2
'这里的mymaster是主机名称,从库的配置中也要一致,然后这个配置的意思是,两个从库认为你这个主机挂了,就确认你是挂掉的状态了,一般写:哨兵数量/2+1'
sentinel down-after-milliseconds mymaster 30000
'这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒'
其他辅助配置
protected-mode no
# 保护模式(设为no就是没有密码)
sentinel parallel-syncs <master-name> <numslaves>
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel failover-timeout <master-name> <milliseconds>
failover-timeout 可以用在以下这些方面:
1. 同一个sentinel对同一个master两次failover之间的间隔时间。
2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
3.当想要取消一个正在进行的failover所需要的时间。
4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
搭一个一主两从,创建三个配置文件:
配置文件名称:sentinal_端口号.conf
创建 data1 data2 data3 个文件夹
port 26379
daemonize yes
dir /root/redis/data
bind 0.0.0.0
logfile "redis_sentinel.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
port 26380
daemonize yes
dir /root/redis/data1
bind 0.0.0.0
logfile "redis_sentinel.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
port 26381
daemonize yes
dir /root/redis/data2
bind 0.0.0.0
logfile "redis_sentinel.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
步骤三
启动三个哨兵
./src/redis-sentinel ./sentinal_26379.conf ./src/redis-sentinel ./sentinal_26380.conf ./src/redis-sentinel ./sentinal_26381.conf
步骤四
登陆哨兵的命令
./src/redis-cli -p 26377
主动停掉主redis 6379,哨兵会自动选择一个从库作为主库
redis-cli -p 6379 shutdown
我们发现80库变成了主库,以后79库启动,变成了从库