redis-持久化
redis-持久化
1.介绍
我们知道redis的数据全部存储在内存中,如果redis服务器突然宕机,则会导致数据全部丢失,所以必须要有一种机制来保证redis的数据不丢失或者丢失很少一部分,这种机制就是redis的持久化机制。
Redis的持久化则将内存中的数据持久备份到硬盘中,在服务重启时可以恢复。Redis目前提供了两种持久化方式
- RDB,即Redis DataBase:把 Redis 服务器中内存的数据保存到一个 dump 文件中,数据的集合
- AOF,即 Append-only file:把所有对 Redis 服务器进行修改的命令保存到一个 aof 文件中,命令的集合
2.RDB
RDB,即 Redis 的内存快照,它是在某一个时间点将 Redis 的内存数据 全量 写入一个临时文件,当写入完成后,用该临时文件替换上一次持久化生成的文件,这样就完成了一次持久化过程。
#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在/redis/src下启动的redis-cli,则数据会存储在当前src目录下
dir ./
##snapshot触发的时机,save <seconds> <changes>
##一般来说我们需要根据系统变更操作密集程度来认真评估这个值
##可以通过 “save “””来关闭snapshot功能
save 900 1
save 300 10
save 60 10000
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
stop-writes-on-bgsave-error yes
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间
rdbcompression yes
触发过程
RDB 持久化触发分为手动和自动两种方式,其中手动方式有两种:save 命令和 bgsave 命令。
- save 命令:阻塞 Redis 服务,直到整个 RDB 持久化完成。我们知道 RDB 是全量持久化,如果内存的数据量大,则造成长时间的阻塞,这样势必会影响业务。所以一般不推荐采用这种方式。
- bgsave 命令:该模式下的 RDB 持久化由子进程完成.Redis 进程接收到该命令后,会 fork 操作创建一个子进程,持久化过程有子进程完成。Redis 服务阻塞只会发生在 fork 阶段,而且该阶段时间过程一般都会很短。其流程如下:
- 客户端发送 bgsave 命令,Redis 进程首先判断当前是否存在其他子进程在执行操作,如 RDB 或者 AOF 子进程,如果有,则立刻返回,否则执行 2。
- Redis 父进程执行 fork 操作创建子进程,在 fork 操作过程中父进程会阻塞。
- Redis 父进程 fork 操作完成后,bgsave 命令返回
Background saving started
信息并不再阻塞 Redis 父进程,可以继续响应其他命令了。 - fork 的子进程则根据 Redis 父进程的内存数据生成 RDB 文件,完成后替换原有的 RDB 文件。同时,发送信号给 Redis 父进程表示 RDB 操作已完成,父进程则更新统计信息。
演示一下如何使用rdb:
-
先存一条数据进去
-
执行bgsave操作
-
查看日志,我们看到将值传进去了
-
将 key =user这条数据删除
-
执行get user,查看是否删除,我们可以看到key=user这条数据已经被删除
接下来就是进行数据恢复,我们需要重启redis,再去查看该值是否恢复
-
重启redis
-
get name 查看该值是否存在,我们发现已经恢复成功了
RDB数据恢复:
RDB 文件的载入工作是在服务器启动时自动加载的,如果在 Redis 服务器中没有设置 AOF ,那么 Redis 服务器在启动是就会检测 RDB 文件(redis-check-rdb 命令),并自动载入。在载入期间,Redis 服务器会一直处于阻塞状态,直到完成为止。如果载入的 RDB 文件损坏了,则会载入失败,Redis 服务会启动失败,我们可以通过 redis-check-rdb
来完成对 RDB 文件的检测和修复。
优缺点:
- 优点
- 由于 RDB 文件是一个非常紧凑的二进制文件,所以加载的速度回快于 AOF 方式
- fork 子进程方式,不会阻塞
- RDB 文件代表着 Redis 服务器的某一个时刻的全量数据,所以它非常适合做冷备份和全量复制的场景
- 缺点
- 没办法做到实时持久化,会存在丢数据的风险。定时执行持久化过程,如果在这个过程中服务器崩溃了,则会导致这段时间的数据全部丢失
3. aof
RDB 最大的问题就在于他提供的持久化策略是不安全的,不适合做实时持久化,所以 Redis 提供了第二套持久化方式:AOF 来解决这个问题。
AOF 即 append only file,它是将每一行对 Redis 数据进行修改的命令以独立日志的方式存储起来。由于 Redis 是将“操作 + 数据” 以格式化的方式保存在日志文件中,他代表了这段时间所有对 Redis 数据的的操作过程,所以在数据恢复时,我们可以直接 replay 该日志文件,即可还原所有操作过程,达到恢复数据的目的。它的主要目的是解决了数据持久化的实时性。
AOF 默认关闭,需要在配置文件 redis.conf 中开启,appendonly yes
。与 AOF 相关的配置如下:
## aof功能的开关,默认为“no”,修改为 “yes” 开启
## 只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly no
## 指定aof文件名称
appendfilename appendonly.aof
## 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
# appendfsync always
appendfsync everysec
# appendfsync no
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
## aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”
auto-aof-rewrite-min-size 64mb
## 相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。
## 每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后
## 触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
auto-aof-rewrite-percentage 100
AOF执行过程
AOF分为三个流程
- 命令写入
- 文件同步
- 文件重写
命令写入
Redis 在命令写入时,将缓冲区(aof_buf)引用进来了。我们知道 Redis 是单线程的,如果每次 append aof 文件命令都直接追加到硬盘,那么性能完全取决于当前硬盘的负载,性能肯定会受到一些影响,所以将命令先写入到 aof_buf 中。这样做还有一个目的,那就 Redis 可以提供多种同步策略,让用户在性能和安全方面做出平衡。
文件同步
命令写入到缓冲区,然后根据不同的策略刷到硬盘中。Redis 提供提供了三种不同的同步策略:always everysec no,由 appendfsync 控制。
策略 | always | everysec | no |
---|---|---|---|
行为 | 每条命令fsync到硬盘 | 每秒把缓冲区fsybc到硬盘 | OS决定什么时候来把缓冲区的命令写到硬盘 |
特点 | 不丢失数据,IO开销大,硬盘压力 | 可能会丢失某一秒的数据 | 不用管,不可控 |
- always :每天命令都会同步至硬盘,是最安全的方式,但是对 IO 开支大,硬盘压力大,无法满足 Redis 高性能的要求,所以我们一般不推荐这种策略。如果对数据安全性要求这么高,其实可以选择关系型数据库。
- everyesc:每秒同步一次,算是一种比较中庸的选择方式,也是 Redis 推荐的方式,但是如果遇到服务器故障,可能会丢失最近一秒的记录 。
- no:Redis 服务并不会直接参与同步,而是将控制权交个操作系统,操作系统会根据系统实际情况来触发同步,不可控。
文件重写
随着命令的不断写入,AOF 文件会越来越庞大,直接的影响就是导致“数据恢复”时间延长,而且有些历史的操作是可以废弃的(比如超时、del等等),为了解决这些问题,Redis 提供了 “文件重写”功能,该功能有以下两种方式触发。
- 手动触发:bgrewriteaof 命令
- 自动触发:由 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数来确定自动触发时机。
- auto-aof-rewrite-min-size:运行 AOF 重写时文件最小体积
- auto-aof-rewrite-percentage:代表当前 AOF 文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比值
- 触发时机 = 当前 AOF 文件空间 > AOF 重写时文件最小体积 &&
重写 AOF 文件最直观的表现是导致 AOF 文件减小,重写时,Redis 主要做了如下几件事情让 AOF 文件减小:
- 已过期的数据不在写入文件。
- 保留最终命令。例如
set key1 value1
、set key1 value2
、....set key1 valuen
,类似于这样的命令,只需要保留最后一个即可。 - 删除无用的命令。例如
set key1 valuel;del key1
,这样的命令也是可以不用写入文件中的。 - 多条命令合并成一条命令。例如
lpush list a、lpush list b、lpush list c
,可以转化为lpush list a b c
演示aof:
1.首先我们需要先开启aof服务,在redis.conf里修改一下配置,并需要重启redis
appendonly yes
-
使用我们之前学的管道符,将命令一起打包给redis服务端执行,我们新建a.txt,内容如下
接下来进行执行
-
我们查看appendonly.aof
AOF 的优缺点
优点
- 相比于 RDB,AOF 更加安全,默认同步策略为 everysec 即每秒同步一次,所以顶多我们就失去一秒的数据(其实不止一秒,这个话题我们后面分析)。
- 根据关注点不同,AOF 提供了不同的同步策略,我们可以根据自己的需求来选择。
- AOF 文件是以 append-only 方式写入,相比如 RDB 全量写入的方式,它没有任何磁盘寻址的开销,写入性能非常高。
缺点
- 由于 AOF 日志文件是命令级别的,所以相比于 RDB 紧致的二进制文件而言它的加载速度会慢些。
- AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低。
参考:https://www.cmsblogs.com/article/1391390833768534016