ITPub博客

首页 > 数据库 > 数据库开发技术 > 重新认识redis(三)

重新认识redis(三)

原创 数据库开发技术 作者:DBA修行之路 时间:2021-09-05 22:39:26 0 删除 编辑




点击上方“蓝字”,发现更多精彩。





重新认识redis(三)

持久化机制

实际生产中,redis最常见的便是被当作缓存使用,即应用数据存储在数据库中,然后同步存储一份副本到内存中,因为redis的数据是存储在内存中,而从内存中读取数据会非常快,这是redis的优点,但是如果服务器宕机,内存中的数据会全部丢失。虽然可以从数据库中进行数据恢复,但是这种做法一方面会给数据库带来很大压力,另一方面会导致需要使用数据的前端应用响应缓慢。因此就引入了redist的两大持久化机制,AOF日志和RDB快照。

AOF

学习AOF,从这几个方面进行入手,如下:

详细来说,即:

1.aof写入实现方式,写入时机?

2.aof的写入策略?

3.aof的优点?

4.aof的缺点?

5.针对缺点,aof做了哪些优化?


针对以上问题,逐个来学习吧。

aof日志与传统的wal(先写日志,后写数据)不同,他是先执行命令写数据,然后再记录日志,aof日志中记录的是redis中执行的命令,例如当执行set name zhangsan,则aof日志中记录的是下面这样的:


aof有三种写回策略,通过appendfsync配置项配置,有三个可选值:always,everysec,no。

always:同步写回,每个写命令执行完后立马同步将日志写回到磁盘中。保证基本不丢数据,但是会影响主线程性能。

everysec:每秒写回,每个写命令执行完后先将日志写入到aof文件的内存缓冲区中,每间隔一秒将缓冲区中的内容写入磁盘。最多丢失一秒的数据,是性能和数据防丢失之间的平衡。

no:操作系统控制写回:redis不控制写回时机,每个命令执行完毕后,只是将日志写入到aof文件的内存缓冲区中,由操作系统决定写入磁盘时机。性能最好,但是宕机时丢失数据较多。


aof能够防止数据丢失,多种数据写回策略使得在性能和数据防丢失方面有多种选择。但是随着接收命令越多,写入命令越多,aof文件也会越来越大,可能会导致性能问题,针对这个,redis做了优化,即aof重写机制。


aof重写机制指的是在重写时,redis根据数据库的最新数据创建一个新的aof文件。重写过程可以总结为"一个拷贝,两次日志。",拷贝指的是每次进行重写时,redis主线程会fork出后台的bgrewriteaof子进程,并同步拷贝父进程的页表面积虚实映射关系,这样,子进程便也能共享访问父进程的内存数据,然后bgrewriteaof子进程可以在不影响主线程的情况下拷贝数据记入重写日志。两处日志指的是日志会同时写入到目前正使用的aof日志的缓冲区和重写日志的缓冲区,这样,新的和旧的aof日志都不会丢失最新的操作。当拷贝数据的所有操作记录重写完成后,记录的最新操作也会写入新的aof日志中,此时,便可以用新的aof日志代替旧的aof日志了。



RDB

除了aof,redis还支持另外一种持久化方法:RDB,是Redis DataBase的缩写,内存快照,即将内存中的数据在某一时刻的状态记录。学习RDB需要考虑一下问题:

1.对哪些数据做快照?

2.进行RDB时,还可以操作数据嘛,redis是否会被阻塞?


快照可以分为两类,全量快照和增量快照,全量快照记录的是redis中当前的所有数据。增量快照记录的是上一次全量快照后被修改的数据。redis中生成RDB文件有两个命令:

save:在主线程中执行,会导致阻塞。

bgsave:创建一个子进程,专门用于写入RDB文件,避免了主线程的阻塞,是redis中RDB文件生成的默认配置。

RDB写入操作中,使用bgsave避免了阻塞问题,使得主线程可以正常接收请求,但是如果为了保证快照完整性,则只能进行读操作,而不能修改正在执行快照的数据,这是不合理的。因此,redis引入了操作系统提供的写时复制技术(Copy-On-Write,COW),r即如果主线程要修改某个数据时,会复制生成一份该数据的副本,然后主线程可以继续修改原来的数据,而bgsave子进程会将这个副本数据写入RDB文件。


知道RDB的实现方式等知识,还需要考虑一个问题,快照的频率。两次快照之间间隔时间太久,如果在此期间发生宕机等故障,期间的数据操作无法恢复,两次快照之间间隔时间太久,一方面频繁将全量数据写入磁盘,会给磁盘带来很大的压力,另一方面,虽然子进程创建后不会阻塞主进程,但是fork子进程这个过程中会阻塞主线程,而且主线程内存越大,阻塞时间也就越长。因此,在第一次做完全量快照后,只需要对修改的数据进行快照记录就行了,即增量快照。但是增量快照中需要引入额外的元数据信息用来记录修改操作。



强强联合

aof记录操作命令,实现,简单但是当数据量大时恢复慢,aof恢复快,但是频率不易把控,那么如何实现又快又好,既能快速恢复,又能降低开销并减少数据丢失呢?自然是强强联合了。redis4.0中提出了一个混合使用aof日志和内存快照的方法。内存快照以一定的频率执行,然后在两次快照之间,使用aof日志记录这期间的所有命令操作。

具体如下:

通过这种方式,可以兼顾RDB快速恢复的优势和aof操作简单的优势。



应用场景

最后,总结一下redis的aof和rdb的持久化选择问题。

1.如果允许分钟级别的数据丢失,可以只使用rdb方式持久化。

2.如果对性能和可靠性都要一定的要求的话,允许丢失少部分数据,可以选择aof的everysec配置选项。

3.如果数据不允许丢失,则选择内存快照和aof的混合使用。

4.如果只追求性能,数据丢失后可以从后端数据库重新刷入,则可以不进行持久化。




自问自答

Q:
aof为什么要先执行再记录?

aof日志实现时是之所以先执行命令,然后再将命令记录到日志中是有两个原因:

1.先执行命令,只有命令执行成功才会被记录到客户端,避免了出现记录错误命令的问题。

2.先执行命令再记录日志,不会对当前的写操作产生阻塞。


Q:
rdb为什么对写多读少的场景不友好?

rdb进行快照时,涉及一个写时拷贝的操作,如果数据修改较多,会造成更多的写时拷贝,会占用更多的内存,如果本身内存已经消耗较多的话,这将会造成资源的竞争和性能问题。

Q:
如何理解redis持久化过程中的不阻塞?

redis持久化过程中的不阻塞是指主线程完成fork出后台的bgrewriteaof子线程(aof日志)或bgsave子线程(rdb快照)。而在fork这一操作过程中,是会对主线程造成阻塞的。


结尾小结

周末也不能放松学习哈,今天学习了下redis的两种持久化方式,课程讲的比较详细,以前也知道reids有rdb和aof两种持久化方式,但是对于细节却不了解,今天算是涨知识了,这些,你学会了嘛。




END



扫码关注我
每天进步一点点,未来才可期,我们共同的目标是星辰大海。

赞一下你最美!



原文作者:DBA修行之路;如有侵权,请联系管理员删除。

上一篇: 重新认识redis(四)
下一篇: 重新认识redis(二)
请登录后发表评论 登录
全部评论

注册时间:2021-05-25

  • 博文量
    64
  • 访问量
    23948