redis的持久化机制
RDB : (保存某一个时间点的数据)快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
手动触发: redis的save命令和bgsave命令都可以调用 rdbSave 函数,都可以生成RDB文件。
1 save 阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。(不推荐)
2 BGSAVE 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成
自动触发:自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave。
如果 每900s redis 数据发生了一次变化,则触发bgsave;
save 900 1
bgsave过程:1 redis会单独创建(fork)一个子进程来进行持久化
2 父进程继续处理client请求,子进程负责将内存内容写入到临时文件。此时父子进程共享相同的物理页面,当父进程处理写请求时OS会为父线程创建一个副本。
3 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。
所以如果redis意外宕机的话,就会丢失最后一次快照后的所有修改
AOF : 每进行一次写命令都会记录到AOF文件(appendonly.aof)当中去 。AOF 比RDB有更好的持久化性。
但是os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。我们可以通过fsync函数强制os写入到磁盘。
三种方式: 1 appendfsync always 每次收到写命令就立即强制写入磁盘(不推荐)
2 appendfsync everysec 每秒钟强制写入磁盘一次(默认)
3 appendfsync no 完全依赖OS(不推荐)
AOF的方式也会带来一些问题: 比如AOF文件越来越大。
redis 提供了bgrewriteaof命令用来重写 比如 set a =1 。set a =2 ,set a =3 。 就会压缩为一条指令: set a=3
重写过程:
1 redis会创建(fork)一个“重写子进程”
2 这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
3 主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。
如果运气比较差,AOF文件出现了被写坏的情况,也不必过分担忧,redis并不会贸然加载这个有问题的AOF文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:
1.备份被写坏的AOF文件
2.运行redis-check-aof –fix进行修复
3.用diff -u来看下两个文件的差异,确认问题点
4.重启redis,加载修复后的AOF文件
redis还提供了redis-check-aof工具,可以用来进行日志修复。
优缺点
热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份.
而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库.
RDB的优点 :
- (1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备。
- (2)RDB对redis对外提供读写服务的时候,影响非常小,因为redis 主进程只需要fork一个子进程出来,让子进程对磁盘io来进行rdb持久化
- (3) RDB比AOF更适合灾难性宕机后的大数据恢复。
RDB缺点
- (1)快照的方式持久化,如果发生故障停机, 就可能会丢失好几分钟的数据。
- (2)RDB每次fork出子进程来执行RDB快照生成文件时,如果文件特别大,可能会导致客户端提供服务暂停数毫秒或者几秒
AOF的优点:
- (1)AOF可以更好的保护数据不丢失,一般AOF会以每隔1秒,通过后台的一个线程去执行一次fsync操作,如果redis进程挂掉,最多丢失1秒的数据。
- (2)AOF以appen-only的模式写入,所以没有任何磁盘寻址的开销,写入性能非常高。
- (3)AOF日志文件的命令通过非常可读的方式进行记录,这个非常适合做灾难性的误删除紧急恢复,不小心用flushall命令清空了所有数据,只要这个时候还没有执行rewrite,那么就可以将日志文件中的flushall删除,进行恢复。
AOF的缺点
- (1)对于同一份文件AOF文件比RDB数据快照要大。
- (2)AOF开启后支持写的QPS会比RDB支持的写的QPS低,因为AOF一般会配置成每秒fsync操作,每秒的fsync操作还是很高的
- (3)数据恢复比较慢,不适合做冷备。