redis 持久化
REDIS 持久化的两种方式
一种是RDB快照(snapshotting)、另外一种是AOF
RDB
是把当前内存中的数据集快照写入磁盘,也就是快照(数据库中所有键值对数据),恢复时是将快照文件直接读到内存里。
RDB 可以是自动触发或手动触发(客户端执行save或者bgsave命令)。如果达到了触发自动保存的条件,会fork一个子进程来保存数据(bgsave)。
此时父进程继续处理client请求,子进程负责将内存内容写入到临时文件(由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照,所以此时主进程最新修改的数据,不会被这次的持久化写入到磁盘)
当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出(fork一个进程时内存也被复制了,即内存会是原来的两倍)。
RDB持久化配置
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000
AOF
redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容
aof的问题是。持久化文件会变的越来越大。如调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库其实文件中保存一条set test 100就够了,为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。
收到此命令后,redis将使用与快照类似的方式,将内存中的数据,以命令的方式保存到临时文件中,最后替换原来的文件。具体过程如下:
1、fork一个子进程,子进程根据内存中的数据库快照,往临时文件中写入重建数据库的命令
2、父进程继续处理client请求,把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。
3、当子进程把快照内容,以命令方式写入临时文件后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入临时文件。
4、父进程使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
整个重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容,用命令的方式重写了一个新的aof文件。
AOF持久化配置
appendonly yes //启用aof持久化方式
appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
appendfsync no //完全依赖os,性能最好,持久化没保证,(对大多数Linux操作系统。是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上)