过期键删除策略
redis过期删除策略由惰性删除跟定期删除配合组成
在规定时间内,分多次遍历服务器中的各个数据库,并从数据库的expires
字典中随机检查一部分键的过期时间,并删除其中的键。
AOF、RDB和复制功能对过期键的处理
生成RDB文件
在执行SAVE
或者BGSAVE
命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中。
载入RDB文件
这里会区分主从服务器的
- 如果在主服务器模式下运行,载入RDB文件的时候,会对键进行检查,未过期的才会被载入到数据库中
- 如果在从服务器模式下运行,会全部载入数据库中。不过,因为主从服务器在进行数据同步的时候,从服务器的数据库会被清空,过期键对载入RDB文件的从服务器也不会造成影响
AOF文件写入
当服务器以AOF持久化模式运行时,如果数据库中某个键已经过期,但它还没被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生任何影响
当过期键被惰性删除或者定期删除之后,程序会向AOF文件追加(append)一条DEL命令,来显式记录该键被删除
AOF重写
在执行AOF重写过程中,会对键检查,已过期的键不会被保存到重写后的AOF文件中
复制
从服务器:
- 如果客户端请求从服务器,获取一个键,发现已过期,但是从服务器不会做任何处理,会把该键的值返回给客户端。
- 如果主服务器发来
DEL KEY
的命令,则会将对应的key删除
主服务器:
- 如果客户端请求主服务器,获取一个键,发现已过期,主服务器会将该键删除,并返回空值,并会向从服务器发送
DEL KEY
的命令
RDB
RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。RDB所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态
因为AOF文件的更新频率会比RDB文件更新频率更高,所以如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。只有AOF功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
AOF(Append Only File)
与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化时通过保存Redis服务器所执行的写命令来记录数据库状态的。
AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤
- 命令追加: 服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾
- AOF文件的写入与同步
AOF文件的载入与数据还原
- 创建一个不带网络连接的伪客户端
- 从AOF文件中分析并读取出一条写命令
- 使用伪客户端执行被读出一条写命令
- 一直重复步骤2和步骤3,直至AOF文件中的所有命令都被处理晚比为止
AOF重写
因为AOF持久化时通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容会越来越多,体积越来越大,如果不加以控制的话,体积过大的AOF很可能对Redis服务器、甚至整个宿主机造成影响,并且AOF文件的题体积越来越大,使用AOF文件来进行数据还原所需的时间就越多。
为了解决AOF文件体积膨胀的问题,redis提供AOF文件重写(rewrite)功能。通过该功能redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新的AOF通常比旧的AOF文件体积小的多
AOF文件重写的实现
AOF文件重写并不需要对现有的AOF文件进行任何读取、分析、写入操作,这个功能时通过读取数据库当前的数据库状态来实现的。
AOF后台重写
在子进程工作的目的:
- 子进程进行AOF重写期间,服务器进程(父进程)可以继续处理命令请求
- 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下保证数据的安全性
为了避免在后台重写AOF的期间,有新的数据写入,则造成丢失
为了解决这种数据不一致问题,redis设置了一个AOF重写缓冲区,这个缓冲区在分局武器创建子进程之后开始使用,当redis服务器执行一个写命令之后,它会同时将这个写命令发送给AOF缓冲区和AOF重写缓冲区
事件
文件事件
redis基于reactor模式开发了自己的网络事件处理器:这个处理器被称为文件事件处理器(file event handler):
- 文件事件处理器使用I/O多路复用程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器
- 当被监听的套接字准备好进行连接应答、读取、写入、关闭等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件
文件事件处理器的构成
I//O多路复用程序会将所有产生事件的套接字都放到一个队列里面,然后通过这个队列以有序、同步、每次一个套接字的方式向文件事件分派器传送套接字。
时间事件
redis的时间事件分为以下两类:
- 定时事件:让一段程序在指定的事件之后执行一次
- 周期性事件:让一段程序每隔指定时间就执行一次
实现
服务器将所有时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器