您的位置:首页 > 数据库 > Redis

redis学习笔记->时间事件管理

2017-04-11 20:04 288 查看
一、redis时间缓存

在server结构体内,有两个成员,缓存下系统的当前时间

redisServer
{
time_t unixtime;        /* Unix time sampled every cron cycle. */
long long mstime;       /* Like 'unixtime' but with milliseconds resolution. */
}
在初始化iniServer()函数内,以及系统定时调用serverCron()函数内,会调用updateCachedTime()更新缓存的时间。
void updateCachedTime(void) {
server.unixtime = time(NULL);
server.mstime = mstime();
}


二、执行定时事件

server结构体内,有个 server.hz成员,时间事件serverCron()函数每次调用完会返回1000/server.hz,时间事件处理器将当前时间会加上这个值,作为下次触发serverCron()函数的时间点。这以为着,每秒钟,会调用server.hz次serverCron()函数。

serverCron()函数内会调用一些定时事件,比如检查客户端,统计命令次数等等。有的事件不需要每秒执行1000/server.hz次,因此需要使用run_with_period(milliseconds)宏,代表着每隔milliseconds秒执行一次该事件。

#define run_with_period(_ms_) if ((_ms_ <= 1000/server.hz) || !(server.cronloops%((_ms_)/(1000/server.hz))))
// 每隔100毫秒记录服务器执行命令的次数
run_with_period(100) trackOperationsPerSecond();
其中server.cronloops再每次serverCron()函数返回之前会自增一次。

三、定时事件

检查客户端

// 检查客户端,关闭超时客户端,并释放客户端多余的缓冲区
clientsCron();

void clientsCron(void) {

// 客户端数量
int numclients = listLength(server.clients);

// 要处理的客户端数量
int iterations = numclients/(server.hz*10);

// 至少要处理 50 个客户端
if (iterations < 50)
iterations = (numclients < 50) ? numclients : 50;

while(listLength(server.clients) && iterations--) {
redisClient *c;
listNode *head;

/* Rotate the list, take the current head, process.
* This way if the client must be removed from the list it's the
* first element and we don't incur into O(N) computation. */
// 翻转列表,然后取出表头元素,这样一来上一个被处理的客户端会被放到表头
// 另外,如果程序要删除当前客户端,那么只要删除表头元素就可以了
listRotate(server.clients);
head = listFirst(server.clients);
c = listNodeValue(head);
/* The following functions do different service checks on the client.
* The protocol is that they return non-zero if the client was
* terminated. */
// 检查客户端,并在客户端超时时关闭它
if (clientsCronHandleTimeout(c)) continue;
// 根据情况,缩小客户端查询缓冲区的大小
if (clientsCronResizeQueryBuffer(c)) continue;
}
}


数据库操作

// 对数据库执行删除过期键,调整大小,以及主动和渐进式 rehash
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)
// 清除模式为 CYCLE_SLOW ,这个模式会尽量多清除过期键
activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);

/* Perform hash tables rehashing if needed, but only if there are no
* other processes saving the DB on disk. Otherwise rehashing is bad
* as will cause a lot of copy-on-write of memory pages. */
// 在没有 BGSAVE 或者 BGREWRITEAOF 执行时,对哈希表进行 rehash
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
/* We use global counters so if we stop the computation at a given
* DB we'll be able to start from the successive in the next
* cron loop iteration. */
static unsigned int resize_db = 0;
static unsigned int rehash_db = 0;
unsigned int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL;
unsigned int j;

/* Don't test more DBs than we have. */
// 设定要测试的数据库数量
if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum;

/* Resize */
// 调整字典的大小
for (j = 0; j < dbs_per_call; j++) {
tryResizeHashTables(resize_db % server.dbnum);
resize_db++;
}

/* Rehash */
// 对字典进行渐进式 rehash
if (server.activerehashing) {
for (j = 0; j < dbs_per
4000
_call; j++) {
int work_done = incrementallyRehash(rehash_db % server.dbnum);
rehash_db++;
if (work_done) {
/* If the function did some work, stop here, we'll do
* more at the next cron loop. */
break;
}
}
}
}
}

还有定时记录日志,统计服务器命令,内存信息等等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: