什么是数据库状态redis
redis是一个键值对的数据库服务器,服务器中一般包含中任意个非空的数据库,而每一个数据库又能够包含任意个键值对,为了方便起见,咱们将服务器中的非空数据库以及他们的键值对统称为数据库状态。数据库
RDB持久化的逻辑数组
RDB持久化就能够手动执行也能够根据服务器配置选项按期的执行,该功能能够将某个时间点上的数据库状态保存到一个RDB文件中,这个文件实际上是一个二进制的文件,经过这个文件能够还原生成RDB文件时的数据库状态。安全
RDB文件的建立服务器
有两个生成redisRDB文件的命令,一个是SAVE,一个是BGSAVE。SAVE命令是使用服务器进程来生成RDB文件,在生成RDB文件的时候,会阻塞全部的读写操做,服务器不能处理任何命令请求。BGSAVE命令是同过服务器进程派生出来一个子进程,而后有子进程负责建立RBD文件,服务器进程能够继续处理命令请求。并发
其实建立RDB文件的工做都是经过rdbsave函数实现的是不过两种命令以不一样的方式调用这个函数。app
SAVE命令执行时的服务器状态函数
其实这个很简单,咱们上面已经提到过SAVE命令或阻塞一切请求,固然拥抱口BGSAVE请求了,因此在执行SAVE期间,再次执行BGSAVE命令会被直接拒绝。工具
BGSAVE命令执行时的服务器状态性能
咱们知道BGSAVE命令是服务器的子进程来完成的,服务器进程能够继续接收和执行命令,可是再BGSAVE命令执行期间服务器处理SAVE、BGSAVE、BGREWRITEAOF三个命令的方式和平时有所不一样,主要有一下几种情形:
1.在BGSAVE命令执行期间,客户端发起的SAVE命令会被服务器拒绝。服务器禁止SAVE命令和BGDAVE命令同时执行是为了不父进程和子进程同时执行两个rdbsave调用,防止产生竞争条件。
2.在BGSAVE命令执行期间客户端发起BGSAVE命令会被服务器拒绝,由于同时执行两个BGSAVE命令也会产生竞争条件
3.在BGSAVE命令执行期间,客户端发起BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕以后执行
4.在BGREWRITEAOF命令执行期间,客户端发起BGSAVE命令会被服务器直接拒绝,主要是由于BGREWRITEAOF和BGSAVE命令都是由子进程来完成的,禁止他们同时执行知识一个性能方面的考虑,由于并发出两个子进程,而且这两个子进程同时进行大量的磁盘写入操做,并非什么好事情。
RDB文件的载入
对于RDB文件的载入就相对简单了,RDB文件的载入工做是在服务器启动的时候自动执行的,而且在服务器载入RDB文件期间,会一直处于阻塞状态,直到载入工做完成为止。
RDB自动间歇性保存
上面咱们讲了如何建立RDB文件,可是何时来建立RBD文件呢?除了手动的执行命令以外,咱们还能够经过配置来让服务器自动来建立RDB文件,咱们能够在redis的配置文件中经过如下配置来实现:
save 900 1 save 300 10 save 60 10000
用户能够经过save选项设置多个保存条件(固然能够超过三个了,十个八个均可以,由于这些保存条件实际上是保存在一个数组中的),可是只要其实任意一个条件知足,服务器就会执行BGSAVE命令。而上面的三条保存配置其实也是在咱们开启了RDB持久化可是没有配置相关保存条件下时服务器给的默认的配置。
RDB自动保存的触发原理
咱们知道了如何配置保存条件的,可是这个保存条件是怎么触发的呢?
其实服务器除了经过一个数据存储咱们的保存条件外,还会维持一个dirty的计数器,以及一个lastsave属性,其中dirty计数器用来统计距离上一次成功执行SAVE命令或者BGSAVE命令后服务器对数据库状态进行了多少次修改(包括写入,删除,更新等操做),而lastsave属性是一个UNIX的时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。这两个值都会在成功执行完BGSAVE命令后重置:dirty重置成0,lastsave更新为当前时间。
而对于条件的判断则是Redis服务器会周期性的操做函数serverCron默认每隔100毫秒执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工做就是检查save选项所设置的保存条件是否知足,若是知足则执行BGSAVe命令。必须同时知足的条件是:1.距离上一次成功执行保存的时间超过设置的时间,2.数据库状态的修改次数超过设置的修改次数
RDB的文件结构
暂略
AOF持久化的逻辑
与RBD持久化经过保存数据库中的键值对来记录数据库状态不一样,AOF持久化是经过保存redis服务器所执行的写命令来记录数据库状态的。
被写入到AOF文件的命令都是以Redis的命令请求协议格式保存的,由于Redis的命令请求协议是纯文本的,因此咱们能够直接打开一个AOF文件,里面保存的基本都是咱们执行的命令,可是会有一些SELECT命令,SELECT命令是用于指定数据库的,此命令是服务器自动添加的。
AOF持久化的过程
AOF持久化过程的实现能够分为命令追加、文件写入、文件同步三个步骤。
命令追加:当AOF功能打开的时候,服务器执行一条命令以后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的额末尾,可是aof_buf缓冲区的命令何时写入aof文件这个要根据额咱们的appendfsync的相关配置来决定
文件写入和同步:为了提升文件的写入效率,在现代的操做系统中,当用户调用write函数,将一些数据写入到文件的时候,操做系统一般会将写入数据暂时存放到一个内存缓冲区里面,等到缓冲区满了或者超过了执行的时限以后,才真正的将缓冲区中的数据写入到磁盘里面
咱们须要注意的是,Redis的服务器进程就是一个事件循环,这个循环中的文件时间负责接收客户端的命令请求,以及向客户端发送命令回复,而时间时间则负责执行向serverCron函数这样的须要定时运行的函数
由于服务器在处理文件事件时可能会执行写命令,使得这些内容被追加到aof_buf缓冲区里面,因此在服务器每次结束一个时间循环以前,它都会调用flushAppendOnlyFile函数,考虑是否须要将aof_buf缓冲区中的内容写入和保存到AOF文件里面。
flushAppendOnlyFile函数的行为是有服务器配置文件的appendfsync选项的值来决定的,appendfsync的值有三种:
1.always:将aof_buf缓冲区中的数据写入并同步到AOF文件。这种设置时最安全的,就变机器出现故障,也只是会丢失一个事件循环中所产生的命令数据
2.everysec:将aof_buf缓冲区的全部内容写入到AOF文件,若是上次同步AOF文件的时间距离如今超过1s,那么再次对AOF文件进行同步,而且这个同步操做有一个线程专门完成。这种设置,服务器在每一个事件循环中都要将aof_buf缓冲区中的全部内容写入到Aof文件,而且每隔1s就要在子线程中对AOF文件进行一次同步。从效率上来说everysec模式足够快,而且就算出现故障停机,数据库也只丢失一秒钟的命令数据。
3.no:在服务器的每一个事件循环钟都要将aof缓冲区中的全部内容写入到AOF文件,但不对AOF文件进行同步,什么时候同步有操做系统来同步,因此这种设置是若是服务器停机,将会丢掉上次AOF文件同步后的全部写命令数据。
AOF文件的载入和数据还原
由于AOF文件中包含了重建数据库状态所需的全部写命令,因此服务器只要读入并从新执行一边AOF文件里面保存的写命令,就能够还原服务器关闭以前的数据状态。
AOF重写
由于Aof持久化是经过保存被执行的写命令来记录数据库状态的,因此随着服务器事件的流逝,AOF文件内容会愈来愈大,文件体积也会也来越大,若是不加控制体积过大的AOF文件极可能对Redis服务器甚至宿主机形成影响。对于数据恢复来讲,AOF文件中会有不少冗余的命令,好比对某个key操做了八次,AOF文件中会记录八条写命令,可是咱们关心的只是最后一次命令执行后的数据状态,为了解决AOF文件体积膨胀问题,Redis提供了AOF重写功能。
AOF重写没有对进行AOF任何操做,只是对AOF重写时候的数据状态转成写命令保存起来,也就是说重写后的AOF文件中保存着可以换肤重写时数据库状态的最小的写命令数,这样就能够大大的减小文件的体积了。
须要注意的是在重写程序中在处理列表、哈希表、集合、有序集合这四种可能会带来多个元素的键时,会先检查包含元素的数量,若是数量超过了设置的常量值(这个值不通版本是不同的),就会用多条命令来记录这个键而不仅仅时一条命令。
由于Reids是单线程的,为了避免是AOF重写时阻塞服务器的正常运行,redis决定将AOF重写放到一个子进程中进行,这样作有两个好处:
1.子进程进行AOF重写期间,服务器进程(父进程)能够继续处理命令请求
2.子进程带有服务器进程的数据副本,使用子进程而不是线程,能够在避免使用所得状况下,保证数据得安全性
有个问题咱们要注意,在子进程AOF重写期间,服务器进程还须要继续处理命令请求,这个时候redis用来一个AOF重写缓冲区来解决这个问题,也就是说,在子进程AOF重写期间,服务器进程会进行三个工做:
1.执行客户端发来得命令
2.将执行后得写命令追加得AOF缓冲区
3.将执行后得写命令追加得AOF重写缓冲区
这样一来能够保证:
1.AOF缓冲区得内容会按期被写入和同步到AOF文件,对如今AOF文件得处理工做会如常进行
2.从建立子进程开始,服务器得全部写命令都会被记录到AOF重写缓冲区里面
当子进程完成AOF重写后,会向服务器进程发一个信号,并调用一个信号处理函数执行一下工做:
1.将Aof重写缓冲区中得全部内容写入到新得Aof文件中,这是新AOF文件所保存得数据库状态将和服务器当前得数据库状态保持一致
2.对新的AOF文件进行更名,原子的覆盖如今的AOF文件,完成新旧文件的交替
在整个AOF后台重写过程当中,只有信号处理的时候会对服务器进程(父进程)形成阻塞,其余时候AOF后台重写都不会阻塞父进程,这将AOF重写对服务器形成的影响讲到了最低。
RDB持久化和AOF持久化的对比
RDB优劣势
优点:
劣势:
AOF优劣势
优点:
劣势: