redis是属于内存数据库,所有数据保存在内存中
服务器进程推出后则数据库状态清除
数据库状态:非空数据库和键值对
- 手动执行RDB保存
-
根据服务器配置选项定期执行RDB保存
-
生成一个经过压缩生成的二进制文件,将某一时刻数据库状态保存在RDB文件中,存储在磁盘上
-
加载
生成RDB
有两个命令可以生成RDB文件,一个是SAVE,另外一个是BGSAVE
区别是看是否创建子进程,看是否阻塞了服务端响应客户端请求
- SAVE命令会阻塞redis服务器进程,知道rdb文件创建完毕为止,在阻塞期间不处理任何客户端请求,客户端请求都存放在缓存之中。
- BGSAVE命令会派生一个子进程负责RDB文件的创建,主进程继续处理客户端的请求
在进行BGSAVE命令时候,有三种命令要特殊处理
- SAVE拒绝,防止主进程和子进程通过是进行rdbSave,导致竞争条件的产生
- BGSAVE拒绝,也会产生竞争条件
- BGREWRITEAOF 都需要子进程进行 都需要大量的IO操作
加载
服务器自动执行的,只要在启动时候,服务器检测到AOF文件或者是RDB文件,都会执行加载,恢复之前的数据库状态
- 如果redis配置中开启aof持久化功能,首先加载aof文件,因为aof更新频率高,更好
- 只有在aof关闭下,加载rdb文件
服务器载入rdb文件期间会一直处于阻塞状态,直到加载完成
自动间隔性保存
通过设置服务系统的参数(SAVE选项),通过调用BGSAVE实现RDB保存。
----------------------------------------------------------------------------------------------------------------------------------------
AOF持久化
AOF持久化是通过保存redis服务器所执行的写命令来记录数据库状态的。
在AOF文件中只有select是自动添加的(切换数据库),其他命令都是客户端发送的命令。
服务器启动时候先加载和执行AOF文件所保存的指令来恢复数据库的状态。
AOF持久化功能实现可以分为三个步骤:命令追加 文件写入 文件同步
下面讲一个重点就是操作系统对写文件的操作
为提高文件写入的效率,当用户调用write时候,将一些数据写入文件时候,操作系统通常会先将数据写入到内存缓冲区中,当过了一定时间或者是内存缓冲区满了或者是强制同步时候,才将内存缓冲区中的数据写入到文件之中。
虽然提高了文件写入的效率,但是在这个过程中,如果机器发生宕机,内存缓冲区所保存的数据都会清空。
fsync fdatasync强制同步
写入AOF文件中命令一般是除了查询命令以外
appendfsync可选值
- always 将aof_buf内存缓存区所有内容写入并且马上同步到AOF文件中
- everysec 将
- no 将所有aof_buf缓冲区内容写入到AOF文件中,但并不主动同步,只有当内存缓存区已满时候才被动同步
AOF载入
为了优化AOF文件的空间大小以及AOF加载时间,所有可以采用AOF重写,减少指令的冗余。
AOF重写的本质就是遍历数据库K-V
- 创建AOF文件
- 判断是否为空(遍历数据库)
- 写入select语句
- 判断是否过期键值对
- 重写
- 如果有过期时间 也要加上expire语句
AOF重写(涉及大量文件写入操作,耗时大,阻塞时间长) 所以可以创建子进程,将AOF重写操作放置在子进程中执行。
Q:为什么是在子进程中,而不是创建子线程
在不加锁的情况下,更加好的保证数据安全,因为redis一般都是单线程的,所以CPU数目不是redis发展的瓶紧
Q2重写的过程中,主进程仍接收/处理客户端请求
- 执行客户端发来的命令
- 将执行后的写命令追加到AOF缓冲区中
- 将执行后的写命令追加到AOF重写缓冲区中
- AOF缓冲区的内容会定期被写入和同步在AOF文件中,对现有的AOF文件进行处理
- 从创建子进程开始,主进程执行的所有写命令都要记录到AOF重写缓冲区中,当子进程遍历完毕后,向父进程发送信号,然后父进程将AOF重写缓冲区命令加载写到AOF文件中(阻塞状态)。然后通过原子操作将新旧AOF文件进行替换。