您现在的位置是:首页 >技术教程 >redis设计与实现读书笔记(2)网站首页技术教程
redis设计与实现读书笔记(2)
今天看的是关于单机数据库,RDB持久化以及AOF持久化的内容。
关于单机数据库
1.默认数据库数量
redis的服务器默认是会创建16个数据库,每个客户端访问的时候都要指定自己的目标数据库。
select可以切换目标数据库。
注意事项
到目前为止,Redis仍然没有可以返回客户端目标数据库的命令。虽然redis-cli客户端会在输入符旁边提示当前所使用的目标数据库,但如果你在其他语言的客户端中执行Redis命令,并且该客户端没有像redis-cli那样一直显示目标数据库的号码,那么在数次切换数据库之后,你很可能会忘记自己当前正在使用的是哪个数据库。当出现这种情况时,为了避免对数据库进行误操作,在执行Redis命令特别是像FLUSHDB这样的危险命令之前,最好先执行一个SELECT命令,显式地切换到指定的数据库,然后才执行别的命令。
2.数据库键空间
数据库的键空间其实就是一个字典,redis对于键的操作,实际上都是通过对键空间字典的操作来实现的。
3.键的过期时间
redis中有一个expires字典保存了所有键的过期时间,这个字典叫过期字典。
4.过期键删除策略
主要是要3种删除策略,分别是定时删除,惰性删除,定期删除。
定时删除:设置计时器,在键到期后,立刻删除,定时删除可以让键在过期的时候就立马被删除,不会继续留在数据库对于内存是很友好的,但是创建大量的计时器,和删除过期键的行为都会影响cpu的性能,特别是在有大量请求访问的情况下,更是会出问题。
惰性删除:过期键在被访问的时候才会被删除,它的好处是不会在删除其他无关的过期键上花费任何CPU 时间,坏处就是要是有过期键一直没有被访问,它就一直不会被删除,这样就会导致内存的严重浪费。
定期删除:每隔一段时间,检查过期键并且删除它。定期删除是上面两种策略的整合和折中:
但是定期删除的问题是需要设计好删除操作的时长和频率,不然就会退化成上面两种删除。
redis实际使用的删除策略
redis实际使用的删除策略是定期和惰性删除结合。
AOF,RDB和复制功能对于过期键的处理
RDB:
生成RDB文件的时候不会保存过期键,载入RDB的时候也不会载入过期键。只有在从服务器载入RDB的时候会载入过期键,但是在后面的主从同步的时候数据也会清除。
AOF
在进行AOF持久化的过程中,并不会对过期键不会有什么影响,只有当过期键被删除的时候,才会向AOF中加一条del命令,在AOF重写的时候,过期键不会保存进AOF中。
复制情况
在复制情况下,对于过期键的删除是由主服务器控制的,也就是说主服务器碰到过期键访问或者定期删除过期键的时候才会删除过期键,并且向所有从服务器发送一个del命令,从服务器只有收到主服务器发送过来的del命令才会删除键,从服务器过期键被访问不会进行删除过期键。
RDB持久化
1.RDB文件的创建
一般来说是有两个命令可以用作生成RDB文件,一个的SAVE,一个是BGSAVE.
两者的区别
SAVE命令会阻塞redis服务器进程;
BGSAVE命令会使用子进程用于生成RDB文件不会阻塞服务器进程,所以一般来说在服务器进行定期持久化的时候使用的一般都是BGSAVE命令。
2.RDB文件的载入
对于RDB文件来说载入工作一般是在服务器启动的时候自动执行,是由redis检测到RDB文件存在,就会自动载入RDB文件。值得一提的是,redis服务器如果开启了AOF持久化功能的话,一般来说是会优先使用AOF文件还原数据库,这是因为AOF的更新频率比RDB文件更新频率高。
BGSAVE和BGREWRITEAOF这两个命令不能同时进行。BGSAVE命令正在执行,BGREWRITEAOF会延迟到BGSAVE命令完成后进行,BGREWRITEAOF在执行的话,BGSAVE会被拒绝。
自动间隔性保存的条件,默认条件是60秒进行了1000次修改,300秒进行了10次修改,900秒内进行了一次修改。
服务器通过dirty计数器,记录着从上一次保存RDB文件后有多少次修改操作。lastsave记录着上次操作的时间。
AOF持久化
1.AOF持久化的实现
命令追加:在AOF持久化功能打开的情况下,服务器执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。
写入与同步
在服务器每一次结束一个事件循环之前,会考虑要不要进行把aof_buff缓冲区的内容写入与同步到AOF文件中。
3种策略
always:把aof_buff缓冲区全部写入和同步
everysec:把aof_buff缓冲区全部写入,如果距离上一次同步超过一分钟的话就进行同步
no:把aof_buff缓冲区全部写入,什么时候同步操作系统决定。
在上面这三种模式中,第一种只可能丢失一个事件循环数据,第二种会丢失一秒钟的数据,第3个会丢失上一次同步后的所有数据。
AOF载入
创建一个伪客户端向服务器发送AOF保存的各种命令,通过这些命令来重新还原服务器之前的数据。
2.AOF重写
因为在服务器一直运行的时候AOF文件会越来越大,存储了一些无用的命令,所以使用AOF重写命令来实现AOF文件体积的减少。重写的AOF文件只会有必要的能还原数据库数据的基本命令,也就是只有向数据库存储数据的命令。
AOF后台重写过程
服务器会开启一个子进程来进行AOF文件的重写,在子线程进行重写的时候还会有一个AOF重写缓冲区,在重写过程中,对于写命令会同时向重写缓冲区和AOF缓存区都追加命令,这样在重写过程中也可以保证AOF文件正常运行。当重写完成后把重写缓存区同步到重写的AOF文件中再把这个文件替换旧文件就完成了重写。
redis事件
redis主要需要处理的事件有两个,一个是文件事件,一个是时间事件。
文件事件
文件事件处理器使用I/O多路复用程序来同时监听多个套接字,根据当前套接字执行的任务来为套接字关联不同的事件处理器。
主要的任务有连接应答,读取,写入,关闭。
尽管多个文件事件可能会并发地出现,但IO多路复用程序总是会将所有产生事件的套接字都放到一个队列里面,然后通过这个队列,以有序,同步,每次一个套接字的方式向文件事件分派器传送套接字。当上一个套接字产生的事件被处理完毕之后,IO多路复用程序才会继续向文件事件分派器传送下一个套接字。
IO多路复用底层实现
有四个库,自动选择性能最高的I/O多路复用函数库来实现。
分别是select,epoll,evport,kqueue.
对于文件事件来说,主要是两种事件,读事件和写事件。
对于这两种事件的优先级来说,是读事件大于写事件。
对于redis的主要文件处理器
大体来说,就是上面这些处理器。
时间事件
redis的时间事件有两类
定时事件:让一段程序在指定的时间之后执行一次。
周期性事件:让一段程序每隔指定时间就执行一次。
redis只使用了周期性事件。
服务器将所有时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。
无序链表并不影响时间事件处理器的性能
在目前版本中,正常模式下的Redis服务器只使用serverCron一个时间事件,而在benchmark模式下,服务器也只使用两个时间事件(也就是无序链表只有一到两个元素)。在这种情况下,服务器几乎是将无序链表退化成一个指针来使用,所以使用无序链表来保存时间事件,并不影响事件执行的性能。
时间事件的应用实例:serverCron
1.更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等。
2.清理数据库中的过期键值对。
3.关闭和清理连接失效的客户端口
4.尝试进行AOF 或 RDB持久化操作。
5.如果服务器是主服务器,那么对从服务器进行定期同步。
6.如果处于集群模式,对集群进行定期同步和连接测试。、
事件的调度与执行
时间事件和文件事件的处理流程。
等待文件事情,处理产生的文件事件,处理已经到达的时间事件。
具体规则:
1.aeApiPoll()函数的最大阻塞时间由到达时间最接近当前时间的时间事件决定,这个方法既可以避免服务器对时间事件进行频繁的轮询(忙等待),也可以确保aeApiPoll函数不会阻塞过长时间。
2.当文件事件处理完成后,没有到达的时间事件,会再次等待并处理文件事件。
3.事件处理是同步,有序,原子性的。
4.因为时间事件处理一般在文件事件后,所以一般时间事件处理时间比设定的时间晚一点。