RDB是Redis持久化数据的一种方式,是执行时间点的Redis内存快照,redis数据还原时加载rdb文件,Redis的主从数据同步也是基于RDB实现的。
RDB流程:
1)执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。
2)父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
3)父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
4)子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。
5)进程发送信号给父进程表示完成,父进程更新统计信息,具体见info Persistence下的rdb_*相关选项。
AOF是Redis持久化数据的另一种方式,这种方式以日志形式记录每一条操作,当redis恢复数据时,还原所有操作。
AOF流程:
1)所有的写入命令会追加到aof_buf中。
2)AOF缓冲区根据对应的策略向硬盘做同步操作。
3)随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
4)当Redis服务器重启时,可以加载AOF文件进行数据恢复。
AOF缓冲区同步文件策略(配置appendfsync参数)说明:
always:命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程返回
everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次
no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30s
配置为always时,每次写入都要同步AOF文件,在一般的SATA硬盘上,Redis只能支持大约几百TPS写入,显然跟Redis高性能特性背道而驰,不建议配置。
配置为no,由于操作系统每次同步AOF文件的周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证。
配置为everysec,是建议的同步策略,也是默认配置,做到兼顾性能和数据安全性。理论上只有在系统突然宕机的情况下丢失1秒的数据。
(策略选择根据业务不同进行选择)
系统调用write和fsync说明:
write操作会触发延迟写(delayed write)机制,Linux在内核提供页缓冲区用来提高硬盘IO性能,write操作在写入系统缓冲区后直接返回,同步硬盘操作依赖于系统调度机制,例如:
缓冲区页空间写满或达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证了数据持久化。
子进程通过fork操作产生,占用内存大小等同于父进程,理论上需要两倍的内存来完成持久化操作,但Linux有写时复制机制(copy-on-write)。父子进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照。避免在大量写入时做子进程重写操作,这样将导致父进程维护大量页副本,造成内存消耗。
Linux kernel在2.6.38内核增加了Transparent Huge Pages(THP),支持huge page(2MB)的页分配,默认开启。当开启时可以降低fork创建子进程的速度,但执行fork之后,如果开启THP,复制页单位从原来4KB变为2MB,会大幅增加重写期间父进程内存消耗。建议设置“sudo echonever>/sys/kernel/mm/transparent_hugepage/enabled”关闭THP。
RDB和AOF对比:
RDB文件紧凑小巧,RDB文件生成又子进程完成,不会阻塞主进程,并且可以利用多核CPU资源,数据的恢复速度也比AOF快,但是RDB方式容易丢失数据,有些公司为了充分利用CPU资源,将Redis进程与cpu核心进行绑定,进行RDB时子进程与父进程会发生资源竞争,影响服务吞吐。
AOF更加安全,可以将数据更加及时的同步到文件中,但是AOF需要较多的磁盘IO开支,AOF文件尺寸较大,文件内容恢复数度相对较慢。
注:文中图片皆来自书中。
下一篇会介绍主从复制流程
原文地址:https://www.cnblogs.com/iamsach/p/8490387.html