Redis的AOF日志 您所在的位置:网站首页 redis阻塞命令有哪些 Redis的AOF日志

Redis的AOF日志

2023-11-14 14:22| 来源: 网络整理| 查看: 265

Redis是个基于内存的数据库。那服务一旦宕机,内存中的数据将全部丢失。通常的解决方案是从后端数据库恢复这些数据,但后端数据库有性能瓶颈,如果是大数据量的恢复,1、会对数据库带来巨大的压力,2、数据库的性能不如Redis。导致程序响应慢。所以对Redis来说,实现数据的持久化,避免从后端数据库中恢复数据,是至关重要的。

目前Redis的持久化有两大机制:AOF日志以及RDB快照。

AOF日志是什么?

AOF是“写后”日志,Redis先执行命令,把数据写入内存,然后才记录日志。日志里记录的是Redis收到的每一条命令,这些命令是以文本形式保存。

AOF日志为什么是“写后”日志?

为了避免额外的检查开销,Redis在想AOF里面记录日志的时候,并不会先去对这些命令进行语法检查,所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis在使用日志恢复数据时,就可能出错。

AOF“写后”日志的优缺点?

优点:

“写后”日志可以避免记录错误命令的情况。它是在命令执行后才记录日志,所以不会阻塞当前的写操作。

缺点:

如果一个命令执行完后,还没记录日志就宕机了,那么这个命令和相应的数据就有丢失的风险。AOF虽然避免了对当前命令的阻塞,但可能会对下一个操作带来阻塞风险。因为AOF日志也是在主线程中执行的,并且是写入磁盘。 如何控制AOF写入磁盘策略?

AOF机制提供了三个选择,也就是AOF配置想appendfsync的三个可选值:

always:同步写回。每个写命令执行完,立马同步地将日志写回磁盘。everysec:每秒写回。每个命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘。no:操作系统控制写回。每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。 三种写回策略的优缺点?

AOF文件格式?

这是redis的aof日志的一条命令:set 333 ddddds

“*3”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3 set”表示这部分有 3 个字节,也就是“set”命令。

AOF文件损坏怎么办?

当主线程正在讲内存中的命令写入aof日志时候,系统突然断电,会造成aof的日志损坏。可能就是只写了“*3”,但是后面后面没来及写入就停电了。这时候使用命令redis-check-aof  可以修复aof文件,原理就是字符串检索,如果这时候只写了“*3”,但后面没数据量,就会将“*3”截去,然后文件修复完毕。

AOF文件会带来哪些“性能问题”? 文件系统本身对文件大小有限制,无法保存过大的文件。如果文件太大,之后再往里面追加命令记录的话,效率也会变低。如果宕机,AOF中记录的命令要一个个被重新执行,用于故障恢复,如果日志文件太大,整个恢复过程会非常缓慢。 日志文件太大了怎么办?

AOF有重写机制:Redis根据数据库的现状创建一个新的AOF文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录他的写入。并且重写机制具有“多变一”功能,就是说旧日志文件中的多条命令,在重写后的新日志变成一条命令。如下图:

AOF重写会阻塞吗?

AOF重写过程是由后台进程bgrewriteaof来完成的。主线程fork出后台的bgrewriteaof子进程,fork会把主线程的内存拷贝一份给bgrewriteaof子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。

所以aof在重写时,在fork进程时是会阻塞住主线程的。

AOF日志何时会重写?

有两个配置项控制AOF重写的触发:

auto-aof-rewrite-min-size:表示运行AOF重写时文件的最小大小,默认为64MB。auto-aof-rewrite-percentage:这个值的计算方式是,当前aof文件大小和上一次重写后aof文件大小的差值,再除以上一次重写后aof文件大小。也就是当前aof文件比上一次重写后aof文件的增量大小,和上一次重写后aof文件大小的比值。 重写日志时,有新数据写入咋整?

重写过程总结为:“一个拷贝,两处日志”。在fork出子进程时的拷贝,以及在重写时,如果有新数据写入,主线程就会将命令记录到两个aof日志内存缓冲区中。如果AOF写回策略配置的是always,则直接将命令写回旧的日志文件,并且保存一份命令至AOF重写缓冲区,这些操作对新的日志文件是不存在影响的。(旧的日志文件:主线程使用的日志文件,新的日志文件:bgrewriteaof进程使用的日志文件)

而在bgrewriteaof子进程完成会日志文件的重写操作后,会提示主线程已经完成重写操作,主线程会将AOF重写缓冲中的命令追加到新的日志文件后面。这时候在高并发的情况下,AOF重写缓冲区积累可能会很大,这样就会造成阻塞,Redis后来通过Linux管道技术让aof重写期间就能同时进行回放,这样aof重写结束后只需回放少量剩余的数据即可。

最后通过修改文件名的方式,保证文件切换的原子性。

在AOF重写日志期间发生宕机的话,因为日志文件还没切换,所以恢复数据时,用的还是旧的日志文件。

总结操作:

主线程fork出子进程重写aof日志子进程重写日志完成后,主线程追加aof日志缓冲替换日志文件

温馨提示:这里的进程和线程的概念有点混乱。因为后台的bgreweiteaof进程就只有一个线程在操作,而主线程是Redis的操作进程,也是单独一个线程。这里想表达的是Redis主进程在fork出一个后台进程之后,后台进程的操作和主进程是没有任何关联的,也不会阻塞主线程。

主线程fork出子进程的是如何复制内存数据的?

fork采用操作系统提供的写时复制(copy on write)机制,就是为了避免一次性拷贝大量内存数据给子进程造成阻塞。fork子进程时,子进程时会拷贝父进程的页表,即虚实映射关系(虚拟内存和物理内存的映射索引表),而不会拷贝物理内存。这个拷贝会消耗大量cpu资源,并且拷贝完成前会阻塞主线程,阻塞时间取决于内存中的数据量,数据量越大,则内存页表越大。拷贝完成后,父子进程使用相同的内存地址空间。

但主进程是可以有数据写入的,这时候就会拷贝物理内存中的数据。如下图(进程1看做是主进程,进程2看做是子进程):

在主进程有数据写入时,而这个数据刚好在页c中,操作系统会创建这个页面的副本(页c的副本),即拷贝当前页的物理数据,将其映射到主进程中,而子进程还是使用原来的的页c。

在重写日志整个过程时,主线程有哪些地方会被阻塞? fork子进程时,需要拷贝虚拟页表,会对主线程阻塞。主进程有bigkey写入时,操作系统会创建页面的副本,并拷贝原有的数据,会对主线程阻塞。子进程重写日志完成后,主进程追加aop重写缓冲区时可能会对主线程阻塞。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有