Redis支持RDB(Redis DataBase)与AOF(Append Only File)两种持久化机制,持久化可以避免因进程异常退出或down机导致的数据丢失问题,在下次重启时能利用之前的持久化文件实现数据恢复。
RDB
RDB:生成数据快照,RDB持久化即通过创建快照(压缩的二进制文件)的方式进行持久化,保存某个时间点的全量数据。RDB持久化是Redis默认的持久化方式。
优点:适合备份,恢复大数据比较快,
缺点:当服务器宕机的时候可能会丢失时间间隔内的数据。
原理
Redis 会 fork 一个子进程,子进程将数据写到磁盘上一个临时 RDB 文件中。当子进程完成写临时文件后,将原来的 RDB 替换掉,这样的好处就是可以 copy-on-write
同时这个也是一个缺点,如果数据集比较大的时候,fork可以能比较耗时,造成服务器在一段时间内停止处理客户端的请求。
当Redis持久化fork子进程后,占用内存大小和父进程等同,由于Linux在写时有copy-on-write机制,父子进程共享相同的物理内存页,当父进程处理写请求的时候会把要修改的页创建副本,而子进程在fork过程中共享整个父进程的内存快照。
RDB持久化的触发包括手动触发与自动触发两种方式。
手动触发
1、save, 在命令行执行save命令,将以同步的方式创建rdb文件保存快照,会阻塞服务器的主进程,生产环境中不要用
2、bgsave, 在命令行执行bgsave命令,将通过fork一个子进程以异步的方式创建rdb文件保存快照,除了fork时有阻塞,子进程在创建rdb文件时,主进程可继续处理请求
自动触发
1、在redis.conf中配置 save m n 定时触发,如 save 900 1表示在900s内至少存在一次更新就触发
2、主从复制时,如果从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点
3、执行debug reload命令重新加载Redis时
4、执行shutdown且没有开启AOF持久化
命令 | save | bgsave |
---|---|---|
IO类型 | 同步 | 异步 |
阻塞 | 是 | 是(阻塞发生在fork时,通常非常快) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外的内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要fork子进程,消耗内存 |
AOF
AOF(Append-Only-File)持久化即记录所有变更数据库状态的指令,以append的形式追加保存到AOF文件中。在服务器下次启动时,就可以通过载入和执行AOF文件中保存的命令,来还原服务器关闭前的数据库状态。保存写数据操作,追加日志。
优点:颗粒度较小,
缺点:文件体积过大,redis提供重写,(从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录该键值对的多个命令)
AOF通过保存命令来持久化,随着时间的推移,AOF文件会越来越大,Redis通过AOF文件重写来解决AOF文件不断增大的问题(可以减少文件的磁盘占有量,加快数据恢复的速度),
原理
1、调用fork,创建一个子进程
2、子进程读取当前数据库的状态来“重写”一个新的AOF文件(这里虽然叫“重写”,但实际并没有对旧文件进行任何读取,而是根据数据库的当前状态来形成指令)
3、主进程持续将新的变动同时写到AOF重写缓冲区与原来的AOF缓冲区中
4、主进程获取到子进程重写AOF完成的信号,调用信号处理函数将AOF重写缓冲区内容写入新的AOF文件中,并对新文件进行重命名,原子地覆盖原有AOF文件,完成新旧文件的替换
AOF的重写也分为手动触发与自动触发
- 手动触发: 直接调用bgrewriteaof命令
- 自动触发: 根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。其中auto-aof-rewrite-min-size表示运行AOF重写时文件最小体积,默认为64MB。auto-aof-rewrite-percentage表示当前AOF文件大小(aof_current_size)和上一次重写后AOF文件大小(aof_base_size)的比值。自动触发时机为 aof_current_size > auto-aof-rewrite-min-size &&(aof_current_size - aof_base_size)/aof_base_size> = auto-aof-rewrite-percentage