a)保存
1.将客户端请求的命令转换为网络协议格式
2.将协议内容字符串追加到变量server.aof_buf中
3.当AOF系统达到设定的条件时,会调用aof_fsync(文件描述符号)将数据写入磁盘
其中第三步提到的设定条件,就是AOF性能的关键点。目前Redis支持三种保存条件机制:
1.AOF_FSYNC_NO:不保存
此模式下,每执行一条客户端的命令,都会将协议字符串追加到server.aof_buf中,但不会执行写入磁盘。
写入只发生在:
1.Redis被正常关闭;
2.Aof功能关闭;
3.系统写缓存已满,或后台定时保存操做被执行
上面三种状况都会阻塞主进程,致使客户端请求失败。
2.AOF_FSYNC_EVERYSECS:每一秒保存一次
由后台子进程调用写入保存,不会阻塞主进程。若是发生宕机,那么最大丢失数据会在2s之内的数据。
这也是默认的设置选项。
3.AOF_FSYNC_ALWAYS:每执行一个命令都保存一次
这种模式下,能够保证每一条客户端指令都被保存,保证数据不会丢失。但缺点就是性能大大降低,由于每一次操做都是独占性的,须要阻塞主进程。
b)读取
AOF保存的是数据协议格式的数据,因此只要将AOF中的数据转换为命令,模拟客户端从新执行一遍,就能够还原全部数据库状态。
读取的过程是:
1.建立模拟的客户端
2.读取AOF保存的文本,还原数据为原命令和原参数。而后使用模拟的客户端发出这个命令请求。
3.继续执行第二步,直到读取完AOF文件
AOF须要将全部的命令都保存到磁盘,那么这个文件会随着时间变得愈来愈大。读取也会变得很慢。Redis提供了AOF的重写机制,帮助减小文件的大小。
实现的思路是:
LPUSH list 1 2 3 4 5
LPOP list
LPOP list
LPUSH list 1
最初保存到AOF文件的将会是四条指令。但通过AOF重写后,会变成一条指令:redis
同时,考虑到为了在AOF重写时,不影响AOF的写入增长了AOF重写缓存的概念。也就是说Redis在开启AOF时,除了将命令格式数据写入到AOF文件,同时也会写入到AOF重写缓存。这样AOF的写入、重写就作到了隔离,保证了重写时不会阻塞写入。
c)AOF重写流程
1.AOF重写完成会向主进程发送一个完成的信号
2.会将AOF重写缓存中的数据所有写入到文件中
3.用新的AOF文件,覆盖原有的AOF文件。
d)AOF缺点
1.AOF文件一般会大于相同数据集的RDB文件
2.AOF模式下性能与RDB模式下性能高低,主要取决于AOF选用的fsync模式
下面给出客户端请求RedisServer时,server端持久化的部分操做图解。
4、Redis数据库的实现
Redis是一个键值对数据库,称为键空间。实现这种KV形式的存储,Redis使用了两种数据结构类型:一、字典,Redis字典使用的是哈希表实现,本来不许备详细介绍Redis哈希表的实现。但发现Redis在实现哈希表时,提供了一个很好的rehash方案,这个方案思路很好,甚至能够衍生到其余各个应用中使用,方案的名称叫“渐进式Rehash”。
实现哈希表的方法大同小异,但为什么各个开源软件老是去开发本身独有的哈希数据结构呢?从研究PHP内核的哈希实现与Redis哈希实现,发现应用场景决定了必须定制才能更好的发挥性能。
a)PHP主要应用于WEB场景,在WEB场景针对单次请求数据之间是隔离的,而且哈希的数量是有限的,那么进行一次rehash也是很快的。因此PHP内核使用阻塞形式rehash,即rehash进行中将不能对当前哈希表进行任何操做。
b)在来看Redis,常驻进程,接收客户端请求处理各项事务,而且操做的数据是相关且数据量较大的,若是使用PHP内核的那种方式就会出现:对哈希表进行rehash时,此时将阻塞全部客户端请求,并发性能会大大降低。