缓存持久化
redis做为缓存,数据的持久化是怎么做的?
在Redis中提供了两种数据持久化的方式:1、RDB 2、AOF
方式一:RDB
RDB(Redis Database Backup file),redis数据备份文件,也叫Redis数据快照,就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
最基本的操作是先使用redis的客户端执行命令,命令有save和bgsave,这两个命令都可以手动执行RDB文件的生成。其中save是用主进程来执行RDB,bgsave是用子进程来执行RDB。假如文件比较大,使用主进程会阻塞其他线程的命令,所以一般在项目中是使用bgsave来执行RDB。
redis提供了RDB触发机制,在redis.conf配置文件中可以找到相关配置,比如save 900 1
就是900秒内,如果至少有1个key被修改,则执行bgsave。
RDB的执行原理:
主进程操作虚拟内存,虚拟内存基于页表的映射关联到物理内存,这样就能实现对物理内存读写的操作。当执行bgsave的时候会fork一个子进程,仅仅是把页表拷贝到子进程。这样无需拷贝内存中的数据,子进程和主进程就能实现内存空间共享,速度非常快。子进程拿到页表之后就可以把读到的数据写入到磁盘中,这就是异步持久化。但是子进程在写RDB文件的过程中,主进程可以接收用户的请求修改内存中的数据,这就可能读取脏数据。
为了避免这种情况发生,fork底层采用copy-on-write技术。在fork的时候会把共享的数据标记为read-only,任何一个进程只能读数据。当主线程写数据的时候,会先拷贝一份数据,然后再去完成写操作。一旦完成拷贝操作之后,主进程读数据的时候也会读取拷贝的数据。
方式二:AOF
AOF(Append Only File,追加文件),Redis处理的每一个写命令都会记录在AOF文件中,AOF可以看作是命令日志文件。它默认是关闭的,可以在redis配置文件中开启。在redis中有三种记录频率,也就是刷盘策略。Always
、everysec
和no
。
Always会立即记录每次执行的写命令,可靠性高几乎不丢失数据,但是性能差。everysec每秒刷盘一次,最多丢失一秒数据。no由操作系统决定合适将缓存数据写入到磁盘。一般在项目中会采用everysec。
由于AOF记录的是命令,所以AOF比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但是只有最后一次写操作才有意义。通过执行bgrewriteaof命令,对当前的AOF文件重写,就可以使用最少的命令达到相同的效果。也可以通过redis.conf自动触发阈值,设置auto-aof-rewrite-percentage
的值,也就是AOF文件比上次增长超多百分之多少会触发重写。设置auto-aof-rewrite-min-size
的值,AOF文件体积最小多大以上触发重写。
RDB与AOF对比
RDB和AOF都有优缺点,如果对数据安全性要求高,在实际开发中往往结合两者
使用。
- 持久化方式,RDB对整个内存做快照,AOF记录每次执行的命令。
- 数据完整性,RDB记录的数据不完整,两次备份之间会丢失。AOF相对完整,取决于刷盘策略。
- 文件大小,RDB会有压缩,文件体积小。AOF记录命令,文件体积很大。
- 宕机恢复速度,RDB由于文件小,恢复速度很快。AOF文件大,恢复速度很慢。
- 数据恢复优先级,AOF的数据完整性更好,所以它的恢复优先级更高。
- 系统资源占用,RDB的系统资源占用比较高 ,写操作的时候会大量占用CPU和内存的消耗。但是AOF主要占用磁盘I/O,但是当AOF重写的时候也会占用大量的CPU和内存资源。
- 使用场景,假如业务可以容忍数分钟的数据丢失就可以使用RDB,速度快。如果对数据安全性要求高,就可以使用AOF,但是一般情况下两者都要开启。