-
最新文章
-
热门文章
-
热评好文
-
最新评论
-
qq5b694d0c5c108:崔老师有意向写书吗?有意向的话可以加您微信探讨一下吗?
-
wx5ca8010b5f496:谢谢!也请关注我的秒杀专栏
-
目录
-
开篇
Redis作为最常用的内存数据库,通常来说数据存储在内存中,为了避免Redis服务器进程退出导致内存中的数据消失。Redis提出了持久化机制,也就是把内存中的数据保存到磁盘中,从而提高数据存储的可靠性。为此主流数据库会提供两类持久化方案,它们是“快照”存储和“日志”存储。相应地Redis提供了RDB持久化和AOF持久化与之对应。其中RDB是以快照的方式存储内存数据到磁盘上,而AOF是以日志追加的方式进行存储。下面就围绕这两种持久化方式展开如下内容:
RDB是Redis Database 的缩写,其作用是在某一个时间点,将Redis存储在内存中的数据生成快照并存储到磁盘等介质上,存在这个磁盘介质上的文件就是RDB文件。“快照”顾名思义就是好像照相一样保存当时的数据,这里的RDB文件是一个二进制的文件,并且是经过压缩的。因为RDB文件是保存在硬盘中的,即使Redis服务器进程退出,甚至运行Redis服务器的计算机宕机,但只要RDB文件仍然存在,Redis服务器就可以用它来还原数据库状态。如图1 所示,可以想象Redis数据库在时间轴上有位于不同时间点的时候都有一个数据库状态,可以把它们想象成一个个切片。图上标注出两个时间点的两个数据库切片,RDB持久化做的事情就是顺着绿色箭头的方向将数据库状态的“切片”以RDB文件的形式保存到磁盘中。
图1 将数据库状态保存为RDB文件
虽然说RDB是一个压缩过的二进制文件,但是它的文件结构也需要有基本的了解,这样有助于我们理解其发挥的作用。如表格1所示,RDB文件由5个部分组成,按照从左到右的顺序依次是:
文件最开头是“REDIS”部分,其长度为5个字节,保存着“REDIS”五个字符。通过这五个字符,程序可以在载入文件时可以判断所载入的文件是否是RDB文件。
接下来是“db_version”长度为4字节,是一个字符串表示的整数,它记录了RDB文件的版本号,例如:"0006"就代表RDB文件的版本为第六版。
“databases”中可以包含着零个或任意多个数据库。
“EOF”常量的长度为1字节,是 RDB文件正文结束的标识,当载入程序读取到个值的时,就意味着数据库的所有键值对都已经加载完毕了。
“check_sum”是一个8字节长的无符号整数,保存着一个校验和。这个校验和是通过对“REDIS”、“db_version”、“databases”、以及“EOF”四个部分的内容进行计算得出的。Redis服务器在载入RDB文件时,会将载入数据所计算出的校验和与check_sum所记录的校验和进行对比,以此来判断RDB文件是否损坏。
表格1 RDB的文件结构
如表格2所示,其表示一个databases部分为空的RDB文件:文件以"REDIS"开头,表示这是一个RDB文件,之后的"0006"表示数据库版本是第六版。因为databases为空所以这里没有数据库的信息,所以版本号之后直接跟着“EOF”常量,最后的6265312314761934562是文件的校验和。
表格2 RDB文件例子
在认识了RDB文件的结构以后,再来看看Redis 如何触发RDB持久化操作,以及其具体流程是如何的。这里包括三部分的内容,分别是save同步方式触发、bgsave 异步方式触发以及自动配置化的方式触发。
如图2所示,描述了save 同步方式持久化RDB的过程:
如图3所示,异步方式过程如下:
如图4所示,这种方式可以理解为读取配置文件的方式。看下面的三个步骤:
#900秒内有1次修改、300秒内有10次修改、60秒内有10000次修改
满足任何以上条件,触发RDB持久化。
save 900 1
save 300 10
save 60 10000
#当快照操作bgsave出错时,是否停止持久化?yes 表示“是”,no表示“否”。
stop-writes-on-bgsave-error yes
#是否压缩?yes表示“是”,no表示“否”,默认选择yes。
rdbcompression yes
#对rdb数据进行校验, 表示写入文件和读取文件时是否开启 RDB 文件检查。
#yes表示“是”,no表示“否”,默认选择yes。
#选择yes表示在Redis加载RDB需要检查文件是否损坏,如果存在损坏会停止启动。
rdbchecksum yes
#设置rdb的文件名
dbfilename dump.rdb
#RDB文件的路径,如果不单独指定,默认是redis的启动路径。
dir ./
关于RDB持久化恢复Redis数据方面也比较简单,将RDB持久化文件 (例如:dump.rdb) 移动到 Redis 安装目录并启动Redis服务就可以了。可以通过 Redis 中的“CONFIG GET dir”命令获取Redis的安装目录。
由于RDB是一个压缩的二进制文件,其代表Redis在某一个时间点上的快照。其适合数据库备份和全量复制的场景。比如定期给数据库进行备份,把RDB文件拷贝到其他的服务器上,以及用于灾备。同样是因为压缩的原因,RDB的加载速度比AOF也要快。
上面介绍了RDB的执行方式和流程,这种方式没有办法做到实时持久化的要求。因为无论是save还是bgsave每次运行都要消耗大量的资源(CPU、内存、磁盘)。随着数据库本身容量的增加每次备份的数据量也随之增加。同时RDB是二进制保存,当Redis版本演进过程中有多个格式的RDB版本,会存在老版本RDB与新版本格式兼容的问题。正式因为RDB的这些问题,Redis提出了AOF的持久化方式。AOF(append only file),是以日志的方式记录每次写入的命令,在Redis Server启动的时候会重新执行AOF文件中的命令,从而达到恢复数据的目的。AOF可以解决数据持久化的实时性问题,也是当前Redis主流的持久化方式。
上面提到了AOF持久化的过程就是日志不断追加的过程,这里通过图5 给大家介绍具体流程:
上面提到了Redis 会将命令先写入到AOF缓冲区,再写入AOF文件。这里介绍一下AOF缓冲区同步文件的三个策略。
always 策略:命令写入AOF缓冲区以后会调用系统fsync 操作同步到AOF文件,fsync完成后线程返回。这里的fsync是针对单个文件的操作,在进行磁盘同步的时候会阻塞直到写入磁盘完成以后返回,从而保证数据持久化的完成。
everysec 策略:命令写入AOF缓冲区以后调用write操作,write完成后线程返回。此操作会有专门线程执行每秒执行一次。这里的write操作会触发延迟写(delayed write)机制,Linux 内核提供页缓冲区来提高硬盘IO性能。也就是说write 操作写入系统缓冲区以后就返回了,同步硬盘依赖于操作系统调度机制完成。(Redis默认配置)
no策略:此种刷新策略是根据操作系统来决定的,也就是由操作系统来决定什么时候将缓冲区的数据写入到磁盘中。由于是操作系统来决定持久化,所以这种方式是不可控的。
AOF缓冲区会将Redis Client请求的命令源源不断地同步到AOF文件中,同时AOF文件会不断增大,这里就需要AOF重写。AOF重写就是把Redis进程内的数据转化为写命令同步到新的AOF文件的过程。其目的就是使重写后的AOF文件变得更小:
进程内已经超时的数据不会再写入AOF文件中。
旧AOF文件含有的无效命令,可以通过进程内的数据直接生成,新的AOF文件只保留最终的数据写入命令。例如就文件中存在三条命令,它们依次是“set hello A”、 “set hello B”和“set hello C”,对同一个key 进行负值只有最后一句“set hello C”是起效的,所以这三条命令会被“set hello C”一条命令替换,并且保存到新的AOF文件中。
另外,多条写命令可以合并成一个。例如依次存在三个命令:“lpush list A”、 “lpush list B”和“lpush list C”,这里就可以合并为一条命令“lpush list A B C”。
AOF重写不仅降低了文件的占用空间,同时更小的AOF也可以更快地被Redis加载。
说完了AOF重写的定义以后,下面来看看AOF重写的流程。一般而言有两种方式可以执行重写操作,分别是:bgrewriteaof 命令和AOF重写配置。
如图6 所示,整个执行过程由三步组成:
实际上是通过AOF的配置文件中的配置值来确定重写的时机。配置如下:
通过上面的配置可以得到AOF重写的机制如下:
当AOF文件当前尺寸大于AOF重写的最小尺寸的时候就触发重写机制。通过上面配置来形成表达式就是:aof-current-size> auto-aof-rewrite-min-size
当AOF文件当前尺寸减去AOF文件本身尺寸的值除以AOF文件本身的尺寸得到的结果大于AOF文件重写比率的时候就需要出发重写机制。
表达式就是:aof-current-size- aof-base-size/ aof-base-size > auto-aof-rewrite-percentage
由于Redis的配置文件中RDB是默认配置。AOF需要手动开启。需要到Redis的配置文件redis.conf中进行如下设置。
\#开启AOF模式 ,yes表示“开启AOF模式”。
appendonly yes
与RDB持久化文件恢复数据一样,只需要将AOF文件 移动到 Redis 安装目录,并启动Redis服务就可以在Redis启动的时候加载AOF文件恢复数据了。
通过上面对AOF的描述可以看出,AOF具有数据完整,安全性高(秒级数据丢失)等优点。同时AOF文件以追加日志文件的形式存在,且写入操作是以Redis协议格式保存的,因此其内容是可读性强,适合误删时的紧急恢复。不过,相对于RDB而言其文件尺寸较大,会占用更多Redis启动加载数据的时间。
前面介绍了RDB和AOF两种机制,这里将它们做一个简单对比。
启动优先级:假设Redis 同时打开了RDB和AOF持久化功能,当Redis重启的时候会优先加载AOF,因为AOF数据更新的频率更高,会保存更新的数据。
体积大小/恢复速度:RDB是使用二进制压缩的模式保存,因此体积会比较小,在Redis恢复的时候加载的速度也会更快。相反AOF写入的是日志的形式,因此体积会较大,恢复速度也会慢些。
数据安全性:RDB是以快照的模式保存数据,对数据的保存不是实时性的,会有丢失数据的可能性。而在这方面AOF的日志方式数据丢失的几率会比RDB好很多(例如:everysec)。
资源消耗:RDB显示需要消耗的资源会更大,因为每次将全量的数据保存到磁盘中。而AOF每次可以保存增量的Redis数据。
总结
本文从为什么需要数据库持久化作为切入点,谈到Redis中的两类数据库持久化机制:RDB和AOF。其中针对RDB持久化通过介绍RDB文件结构、触发持久化的机制和流程进行了阐述。其包括:save同步方式、bgsave同步方式和自动配置方式。针对AOF持久化,通过AOF持久化流程、缓冲区同步文件策略以及AOF重写机制进行了介绍。其中缓冲区同步策略包括:always策略、everysec策略和no策略。
把本文学习笔记的思维导图分享如下。
赞赏
0人进行了赞赏支持
2
收藏
Ctrl+Enter 发布
发布
取消