背景(why):
redis一般作为缓存使用,从而提供系统的整体性能。redis是以内存请求为主的nosql DB,在重启、或者宕机的情况,如何确保数据不丢失,并且快速恢复,是redis的一大挑战。
How:
redis主要有两大方案保障数据的安全,分别是:RDB(redis data base)和AOF(append only file)。
what:
RDB:
就是所谓的“内存快照”,记录了redis某个时间点的内存数据,并以文件的形式存储在磁盘中。在redis重启是,能够使用RDB直接恢复内存数据。执行流程如下:
这样就可以不用每次写操作,都需要写磁盘,只需要在某个时间点写一次数据就可以了,同时RDB 采用二进制 + 数据压缩的方式写磁盘,文件体积小,数据恢复速度快。但是会出现数据丢失的问题(2次快照之间的数据,并没有落到磁盘上)。如果RDB的频率很高,例如1S1次,会加重磁盘的负担,从而降低性能。
执行方式:有同步(save)和异步(bgsave)。
save是主线程执行的,会阻塞redis;
bgsave主线程会fork一个子线程来完成,刚fork出的子线程和主线程是数据和代码共享的(所以在进程分离的一瞬间,内存的增长几乎没有明显变化),只有在主线程有写操作时,才会产生不同的数据。如图:
为了确保子线程做快照时,主线程还能写入数据。采用的方案是COW(copy on write),即:当主线程执行写指令修改数据的时候,这个数据就会复制一份副本, bgsave 子进程读取这个副本数据写到 RDB 文件。
AOF:
只记录了redis中写操作的顺序指令。这样恢复时,只需将写操作执行一遍(也叫重放),数据就可以恢复了。
redis采用记录方案:
是“写后日志”,即:先执行写操作,内存写成功后,再记录日志(对比是:写前日志(Write Ahead Log, WAL),即: 在实际写数据之前,将修改的数据写到日志文件中,故障恢复得以保证)。操作流程如下:
“写后日志”好处是:不需要做指令检查,对当前指令没有阻塞(但是写磁盘动作,可能影响下1条指令)。
数据落盘方案:
always:同步写回,写指令执行完毕立马将 aof_buf缓冲区中的内容刷写到 AOF 文件。
everysec:每秒写回,写指令执行完,日志只会写到 AOF 文件缓冲区,每隔一秒就把缓冲区内容同步到磁盘。
no: 操作系统控制,写执行执行完毕,把日志写到 AOF 文件内存缓冲区,由操作系统决定何时刷写到磁盘。
AOF会出现