AOF
redis如何通过AOF进行写日志
redis AOF采用的是写后操作,也就是数据先写入内存中,再写入到AOF日志文件中。采用这样的好处是,可以避免当次操作,因为写日志而降低性能,采用写后操作,可以在写入日志时,不需要校验命令的正确性,保证写入到日志的命令都是正确的。坏处是:虽然没有降低当次请求的操作,但是写入日志还是在主线程中进行的,所以会影响到下次命令的性能。
AOF日志记录什么
在AOF日志中记录的就是操作的命令信息,例如一个操作 set hello world 对应记录到AOF日志中就是如下形式:
其中:
*3表示这个命令是由三部分组成(对应上面的命令 也就是set hello world)刚好三部分
$后面加数字,其中数字表示命令占用的多少字节
AOF的三种写回策略
Always 同步写回,也就是redis每执行一个命令后,马上将对应的命令写入到日志中
Everysec 每秒写回,每个命令执行完成后,只会将命令写入到AOF文件对应的内存缓存区中,每隔1秒之后,才会写入到磁盘
No 操作系统控制的写回,每个命令执行完成后,也是将命令写入到AOF文件对应的内存缓冲区中,写入到磁盘的操作由操作系统自身来控制
对于AOF日志来说,当我们一直进行写日志操作,AOF文件会越来越大,当我们往里追加数据的时候,性能会越来越慢这个时候需要怎么办呢?
AOF重写机制
重写的方式:就是读写内存中所有的数据,然后根据数据生成对应的命令,生成一份新的对应AOF文件,例如对于我们的一个key可能经过了很多次操作后,在没有重写的时候,AOF文件中对应的key有很多个文件操作,进行AOF重写之后,就只会保留最后一个操作,其结构如下所示:
这样AOF进行重写后,日志文件就变小了。
aof重写日志,是由主线程fork出一个bgrewriteaof线程来完成对应的操作,所以不影响对应的主线程操作。fork子线程出来后,对应的子线程会拿到主线程的内存数据,然后将内存数据转化为对应的每条执行写入到新的AOF文件中,其流程大致如下:
当在进行aof日志重写的过程中,主线程还是有出现客户端发送的命令,这个时候主线程在数据写入redis后,会将命令分别写入原AOF文件的缓冲区和AOF重写缓存区中,子线程会(copy on write)一份主线程中redis的数据,然后读取redis中的数据,将数据转化写入到磁盘中。
RDB
什么是RDB文件
redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器时使用。
生成RDB的三种方式
通过save命令来生成RDB文件,这个命令是在主线程中进行生成RDB文件,会阻塞主线程操作(不推荐使用)
通过bgsave命令来生成RDB文件,这个命令是通过主线程fork一个子线程来进行生成RDB文件,影响性能小
通过redis.conf中的配置文件来触发RDB文件生成,比如save 60 10000,那么从redis最近一次创建快照之后开始算起,当“60秒之内有10000次写入”这个条件被满足时,redis就会自动触发bgsave命令。如果设置多个save选项,只要其中一条满足,redis就会触发一次bgsave命令。
当进行RDB操作的时候我们能否进行数据的修改
当然如何是sava方式在主线程中进行生成RDB文件,所以就不存在这种情况,主线程只有等到RDB文件生成后,才能去执行其他的操作;当使用bgsave去对应生成RDB时,为了保证在RDB的过程中可以不影响主线程的操作命令,bgsave子进程会使用(copy on write)技术去生成对应的RDB文件,其流程如下所示:
也就是首先主线程fork一个bgsave子线程,此时子进程复制了主线程的页表,所以通过页表映射,能读到主线程的原始数据,所以此时是不存在真实数据复制操作的,只有当主线程修改了entry3的值的时候,这个时候触发(copy on write),会生成一个entry3的原始数据副本,bgsave继续读取的原数据信息,而主线程会把新数据或修改后的数据写到一个新的物理内存地址上,并修改主线程自己的页表映射。
什么是写时复制(copy on write)
是一种计算机程序设计领域的优化策略,也就是当有多个调用者,调用同一份数据时,他们获取的都是数据指针并且指向原始数据,当有一调用方修改某个数据时,此时会将修改的数据单独copy出一份出来给这个调用者,其他调用者还是使用原来的数据,操作也会其他调用者无感知。
领取专属 10元无门槛券
私享最新 技术干货