周梦康 发表于 2014-05-10 4229 次浏览 标签 : redis

英文原文 http://oldblog.antirez.com/post/redis-persistence-demystified.html

笔记来源 http://blog.nosqlfan.com/html/3813.html

其他参考 http://blog.csdn.net/jackpk/article/details/30073097

持久化的流程

首先我们来看一下数据库在进行写操作时到底做了哪些事,主要有下面五个过程。

  1. 客户端向服务端发送写操作(数据在客户端的内存中)

  2. 数据库服务端接收到写请求的数据(数据在服务端的内存中)

  3. 服务端调用 write 这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)

  4. 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)

  5. 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)

持久化的方式有两种,第一种是rdb,第二种是aof

RDB 快照

原理

Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。

配置

可以在配置文件中通过save指令来设置保存的时机。

# 24小时保存一次
save 86400 1

比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

当手动执行save,shutdown,slave会触发RDB快照的存储。

可靠性

Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。

不足

一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。

AOF日志

原理

AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。和binlog一样,只会记录有效的写操作的命令。

AOF rewrite

你可以会想,每一条写命令都生成一条日志,那么AOF文件是不是会很大?

答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。

可靠性设置

在Redis中对AOF调用write写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面appendfsync·的三个设置项,安全强度逐渐变强。

appendfsync no

当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

appendfsync everysec

当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。

所以,结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。

这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。

appednfsync always

当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。

重启服务的说明

正确关闭服务:redis-cli shutdown,redis-cli kill都是比较正确的,保证写RDB文件以及将AOF文件fsync到磁盘,不会丢失数据。 如果是Ctrl+C,或者kill -9 就会丢失数据。 执行指令bgsave可触发rdb存盘,bgrewriteaof可触发aof重写。

重启:当同时使用了RDB和AOF的情况下,重启时只会从AOF文件载入数据,不会管RDB文件。那要不要只使用AOF呢?作者建议不要,因为RDB更适合用于备份数据库,快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。


👇 下面是我的公众号,高质量的博文我会第一时间同步到公众号,给个关注吧!

评论列表