当前位置: 首页 > 工具软件 > redis-aux > 使用案例 >

redis(三:redis RDB&AOF)

皇甫飞宇
2023-12-01

redis一般都是用来做数据缓存。但是当redis宕机,内存里的数据就会丢失。所以redis里的数据也要做持久化操作。

第一时间想到的是从数据库里获取。但是这个操作首先需要频繁访问数据库,给数据库带来压力,而且数据是从数据库里读取的,性能自然不能跟从redis比。

redis是采用rdb和aof实现数据持久化。

AOF : 写后日志。即先执行命令,再把执行的日志保存到日志文件里。AOF里存的是redis收到的每一条命令。关于写后日志,避免额外的redis检查开销,如果执行失败就不会写入aop文件。恢复数据也不会说有命令异常的困扰。

缺点  :  第一:如果AOF刚写完数据,服务器立马宕机还没写入AOF,则下次服务器恢复数据,这一块的数据就丢失了。   第二:如果写入操作时数据量很大,则该操作会阻塞主线程,影响后续的命令操作。

为此redis提供了三种写回策略:

1 always 同步写回,命令执行完后,命令立马写入磁盘。

2 everysecond  每秒将命令写入磁盘。但是宕机的话有一秒的数据丢失。

3 no   操作系统控制什么时候写回,aof文件先存入缓冲区,再决定何时存入磁盘。性能好,但是宕机时会丢失很多数据。

AOF也有文件过大的烦恼: 1 文件系统对文件大小有限制,无法存储过大的文件。 2 文件过大,对后续的命令追加,效率会变低。  3 当redis宕机恢复数据,aof文件过大影响redis效率。

于是有了AOF重写机制:  读取数据库里的键值对,用命令记录记录每一条数据的写入。一个key被多次执行,最终记录下来的是执行后键值对最新的状态,把之前对应这个key的操作汇总,这个key也只会保存这么一条命令,日志回复时也只需要执行这一条。

aof重写入磁盘是有后台线程bgrewriteAof执行,避免阻塞主线程。

执行重写时,主线程fork出一条bg子进程,fork会把主线程的内存拷贝给bg子进程,子进程不影响主线程的情况下将数据写成操作并写入磁盘。

服务器里存在两份日志,AOF的日志和AOF重写的日志。AOF保证新写入的命令不丢失,aof重写采用额外的线程进行数据重写,不会影响主线程。

RDB: 内存快照 ,内存里的数据在某一刻的记录,以文件的方式写入磁盘  dump.rdb。

redis database的简称。 把内存里的全量数据写入磁盘很消耗时间,这时候就要考虑rdb过程是否会阻塞主线程。redis提供了save方法和bgsave方法。save会阻塞线程,bgsave会在后台fork出子进程,避免阻塞子进程。

生成快照的过程中能操作数据么,读肯定可以,写呢?

如果快照的数据量很大,写入磁盘需要1一分钟,这一分钟里总不可能让客户端不能操作内存数据吧,所以这一分钟快照里,数据时要发生变化的。照这样说那快照的数据不是不同步了。

这里redis采用了操作系统写时复制技术,copy-onwrite技术,执行快照的同时,处理读写。如果快照期间主线程修改了数据,那这块数据就被复制出来,生成数据副本,bgsave线程会把副本数据写入RBD文件,这些操作期间,主线程依然可以执行对内存数据的读写操作。

每次快照的间隔时间怎么控制:

如果两次快照之间修改了数据,改完之后服务器宕机了,然而这部分数据还没有做快照,那这部分数据就丢失了。所以这个时间尽可能的小,但是如果时间做快照的间隔时间太短,也会给服务器带来压力。

一方面频繁的将数据写入到磁盘,多个快照一起竞争有限的的磁盘带宽,前面还没做完后面又开始了。另一方面,主线程forkbgsave线程也是会发生阻塞的,这个阻塞的时间跟主线程的大小成正比,频繁的fork也会导致主线程阻塞。

针对这些问题,redis采用增量快照。就是第一次做全面快照,后续的快照只会操作那些发生改变的内容。避免每次全量快照的开销。但是每次记录那些数据发生了变更,如果数据量变更巨大,那又是一个消耗内存的点。

 redis4.0引入了 rdb和aof一起执行的方法。内存快照以一定的时间间隔执行,这两次快照之间的数据改变用AOF保存。既可以用到RDB文件快速恢复的优势,又享受到AOF只记录操作命令的优势。

 类似资料: