redis的事件主要由两种fileEvent 也就是各种socked的异步操作,通过epoll网络模型监听。另外一种就是timeEvent事件,redis就有一个timeEvent事件,可以理解为定时器。
注册timeEvent事件时,事件函数是int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) ,此事件函数主要有以下操作:
在此函数中主要做一下工作:
(1)过期key的收集工作,收集的方式和rehash方式一样,分为active和lazy collection.
(2)软件狗–这地方还没明白意思,后面再看
(3) update 一些静态数据
(4)rehash 哈希表,也就是上面介绍的
(5)触发BGSAVE / AOF读写,以及处理中断的子进程,BGSAVE / AOF进程主要是数据持久化的操作,后面针对这两个再分别写一篇文章
(6) 处理不同类型的客户端超时操作
(7) Replication reconnection 应该是和集群操作有关,后面会专门看redis的集群操作
此事件函数中所有的操作一秒钟执行server.hz次,同时为了调节操作的执行频次,使用run_with_period(milliseconds)函数。
void databasesCron(void) {
/* Expire keys by random sampling. Not required for slaves
* as master will synthesize DELs for us. */
if (server.active_expire_enabled && server.masterhost == NULL)
activeExpireCycle();
在客户端进行写操作时,如果带有过期时间的参数,那么server端会在db->expires哈希表中,存储此key的过期时间,同时在主字典中保存value,但是key是公用一块内存。节省了内存消耗。
重要的操作在activeExpireCycle函数,此函数回收过时key,算法是动态的,如果有较多的过期key的话,会消耗cpu执行事件。
为了动态的执行此操作,定义了一下static变量,用来终止或者继续过期key的回收操作。如果有太多的过期key的话,一直回收也会带来客户端的阻塞,所以redis将其做了动态处理,比如说每次处理几个数据库,每次占用多少cpu时间。
见下面的代码:
void activeExpireCycle(void) {
/* This function has some global state in order to continue the work
* incrementally across calls. */
static unsigned