什么是持久化
redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上
持久化策略
快照(:某时某刻数据的一个完成备份,
- mysql的Dump
- redis的RDB
写日志:操作记录日志,恢复数据,只要把日志重新走一遍即可
- mysql的 Binlog
- Hhase的 HLog
- Redis的 AOF
RDB
RDB持久化是指在指定的时间间隔内将通过save命令将内存中的数据生成RDB快照文件
RDB文件是经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。
过程:
Redis调用fork(),产生一个子进程。子进程把数据写到一个临时的RDB文件。当子进程写完新的RDB文件后,把旧的RDB文件替换掉
持久化指令 save与bgsave
- save(同步)
1 客户端执行save命令----》redis服务端----》同步创建RDB二进制文件
2 会造成redis的阻塞(数据量非常大的时候)
3 文件策略:如果老的RDB存在,会替换老的
4 复杂度 o(n)
- bgsave(异步,Backgroud saving started)
1 客户端执行save命令----》redis服务端----》异步创建RDB二进制文件(fork函数生成一个子进程(fork会阻塞reids),执行createRDB,执行成功,返回给reids消息)
2 此时访问redis,会正常响应客户端
3 文件策略:跟save相同,如果老的RDB存在,会替换老的
4 复杂度 o(n)
配置方式
redis默认情况下,是快照RDB的持久化方式,将内存中的数据以快照的方式写入二进制文件中,RDB默认的文件名是dump.rdb
redis.conf文件中的默认配置: 关于redis.conf内容的详解
save 900 1
save 300 10
save 60 10000
含义:
如果60s中改变了1万条数据,自动生成rdb
如果300s中改变了10条数据,自动生成rdb
如果900s中改变了1条数据,自动生成rdb
以上三条符合任意一条,就自动生成dump.rdb文件
我们可以根据需要添加规则,比如再加一条: save 10 1
推荐配置方法
配置:
save 900 1 #配置一条
save 300 10 #配置一条
save 60 10000 #配置一条
dbfilename dump.rdb #rdb文件的名字,默认为dump.rdb
dir ./ #rdb文件存在当前目录
stop-writes-on-bgsave-error yes #如果bgsave出现错误,是否停止写入,默认为yes
rdbcompression yes #采用压缩格式
rdbchecksum yes #是否对rdb文件进行校验和检验
最佳配置:
save 900 1
save 300 10
save 60 10000
dbfilename dump-${port}.rdb #以端口号作为文件名,可能一台机器上很多reids,不会乱
dir /redis-4.0.0/data #RDB文件保存路径
stop-writes-on-bgsave-error yes #出现错误停止
rdbcompression yes #压缩
rdbchecksum yes #校验
优点
RDB是一个紧凑压缩的二进制文件,存储效率较高
RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等场景
RDB恢复数据的速度要比AOF快很多
应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复。
缺点
RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照
到Redis出现问题这段时间的数据就会丢失了。
RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚 至会到1秒。
AOF
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,生成AOF文件,重启Redis
时,AOF里的命令会被重新执行一次,重建数据。
客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复
过程:
Redis调用fork(),产生一个子进程。子进程把新的AOF写到一个临时文件里。主进程持续把新的变动写到内存里的
buffer(暂存区),同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全。当子进程完成文件 的
重写后,主进程会获得一个信号,然后把内存里的buffer(暂存区)追加到子进程生成的那个新AOF里
AOF的三种策略
日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上
- always:redis--》写命令刷新的缓冲区---》每条命令fsync到硬盘---》AOF文件
每次写入操作均同步到AOF文件中,数据零误差,性能较低
- everysec(默认值):redis——》写命令刷新的缓冲区---》每秒把缓冲区fsync到硬盘--》AOF文件
每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高
在系统突然宕机的情况下丢失1秒内的数据
- no:redis——》写命令刷新的缓冲区---》操作系统决定,缓冲区fsync到硬盘--》AOF文件
由操作系统控制每次同步到AOF文件的周期,整体过程不可控
三种策略比较:
命令 | always | everysec | no |
---|---|---|---|
优点 | 不丢失数据 | 每秒一次fsync,丢失1秒数据 | 不用管 |
缺点 | IO开销大,一般的sata盘只有几百TPS | 丢1秒数据 | 不可控 |
配置方式
redis.conf默认配置:
appendonly no
将配置文件中的appendonly修改为yes,即开启AOF持久化。开启后,启动redis服务端,发现多了一个appendonly.aof文件
默认的持久化方案:
# appendfsync always
appendfsync everysec
# appendfsync no
当然always一定是效率最低的,个人认为everysec就够用了,数据安全性能又高。Redis也允许我们同时使用两种方式,再重启redis后会从AOF中恢复数据
推荐配置
port 6379
daemonize yes
logfile "6379.log"
dir /redis-4.0.0/data
save 900 1
save 300 10
save 60 10000
dbfilename dump-6379.rdb
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
appendonly yes # 启动aof
appendfsync everysec # aof策略
appendfilename appendonly-6379.aof # aof文件根据端口号命名
说明: AOF与RDB可以同时配置不冲突
优点
比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒
fsync一次。这意味着你最多丢失一秒钟的数据
缺点
在相同的数据集下,AOF文件的大小一般会比RDB文件大。
日志重写:新文件上会写入能重建当前数据集的最小操作命令的集合。
AOF 重写
随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题
使用AOF做持久化,每一个命令以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 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 |
本质就是把过期的,无用的,重复的,可以优化的命令,来优化,
这样可以减少磁盘占用量,加速恢复速度
重写实现方式
- 手动方式:
bgrewriteaof : 客户端向服务端发送bgrewriteaof命令,服务端会起一个fork进程,完成AOF重写
- 自动触发方式
AOF重写配置:
配置名 | 含义 |
---|---|
auto-aof-rewrite-min-size | AOF文件重写需要尺寸 |
auto-aof-rewrite-percentage | AOF文件增长率 |
统计名 | 含义 |
---|---|
aof_current_size | AOF当前尺寸(单位:字节) |
aof_base_size | AOF上次启动和重写的尺寸(单位:字节) |
自动重写触发条件:
aof_current_size>auto-aof-rewrite-min-size :当前尺寸大于重写需要尺寸
(aof_current_size-aof_base_size)/aof_base_size>auto-aof-rewrite-percentage:(增长率)当前尺寸减去上次重写的尺寸,除以上次重写的尺寸如果大于配置中的增长率
AOF重写流程
配置
appendonly yes #将该选项设置为yes,打开
appendfilename "appendonly-${port}.aof" #文件保存的名字
appendfsync everysec #采用第二种策略
dir /bigdiskpath #存放的路径
no-appendfsync-on-rewrite yes #在aof重写的时候,是否要做aof的append操作,因为aof重写消耗性能,磁盘消耗,正常aof写磁盘有一定的冲突,这段期间的数据,允许丢失
RDB和AOF的选择
rdb和aof的比较
命令 | rdb | aof |
---|---|---|
启动优先级 | 低 | 高(挂掉重启,会加载aof的数据) |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
轻重 | 重 | 轻 |
对数据非常敏感,建议使用默认的AOF持久化方案
- AOF持久化策略使用everysecond,每秒钟fsync一次。该策略redis仍可以保持很好的处理性能,当出现问题时,最多丢失0-1秒内的数据。
- 注意:由于AOF文件存储体积较大,恢复速度较慢
数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工维护的),且恢复速度较快,阶段点数据恢复通常采用RDB方案
- 注意:利用RDB实现紧凑的数据持久化会使Redis降的很低
综合比对
- RDB与AOF的选择实际上是在做一种权衡,每种都有利有弊
- 如不能承受数分钟以内的数据丢失,对业务数据非常敏感,选用AOF
- 如能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选用RDB
- 灾难恢复选用RDB
- 双保险策略,同时开启 RDB 和 AOF,重启后,Redis优先使用 AOF 来恢复数据,降低丢失数据的量
持久化用于场景
应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
应用于具有操作先后顺序的数据控制
应用于最新消息展示
应用于基于黑名单与白名单设定的服务控制
应用于计数器组合排序功能对应的排名
rdb最佳策略
rdb关掉,主从操作时
集中管理:按天,按小时备份数据
主从配置,从节点打开
aof最佳策略
开:缓存和存储,大部分情况都打开,
aof重写集中管理
everysec:通过每秒刷新的策略
最佳策略
小分片:每个redis的最大内存为4g
缓存或存储:根据特性,使用不通策略
时时监控硬盘,内存,负载网络等
有足够内存