目录
1.引言
服务器中的
serverCron
函数默认每隔
100
毫秒执行一次,这个 函数负责管理服务器的资源,并保持服务器自身的良好运转
2.serverCron的功能
2.1更新服务器时间缓存
服务器中有不少功能需要获取系统的当前时间,而每次获取系统的当前时间都需要执行一次系统调用,为了减少系统调用的执行次 数,服务器状态中的unixtime
属性和mstime属性被用作当前时间的缓存
truct redisServer {
// ...
//
保存了秒级精度的系统当前UNIX
时间戳
time_t unixtime;
//
保存了毫秒级精度的系统当前UNIX
时间戳
long long mstime;
// ...
};
serverCron
函数默认会以每
100
毫秒一次的频率更新
unixtime
属 性和mstime
属性,所以这两个属性记录的时间的精确度并不高:
服务器只会在打印日志、更新服务器的
LRU
时钟、决定是否执行持久化任务、计算服务器上线时间(uptime)这类对时间精确度要求不高的功能上。
对于为键设置过期时间、添加慢查询日志这种需要高精确度时间 的功能来说,服务器还是会再次执行系统调用,从而获得最准确的系统当前时间
2.2更新LRU时钟
lruclock
属性保存了服务器的
LRU
时钟,这个属性 和上面介绍的unixtime
属性、
mstime
属性一样,都是服务器时间缓存的 一种
struct redisServer {
// ...
//
默认每10
秒更新一次的时钟缓存,
//
用于计算键的空转(idle
)时长。
unsigned lruclock:22;
// ...
};
Redis
对象都会有一个
lru
属性,这个
lru属性保存了对象最后一 次被命令访问的时间
typedef struct redisObject {
// ...
unsigned lru:22;
// ...
} robj;
属性记录的时间减去 对象的lru
属性记录的时间,得出的计算结果就是这个对象的空转时间
redis> SET msg "hello world"
OK
#
等待一小段时间
redis> OBJECT IDLETIME msg
(integer)20
#
等待一阵子
redis> OBJECT IDLETIME msg
(integer)180
#
访问msg
键的值
redis> GET msg
"hello world"
#
键处于活跃状态,空转时长为0
redis> OBJECT IDLETIME msg
(integer)0
时钟的当前值可以通过
INFO server
命令的
lru_clock
域查看
redis> INFO server
# Server
...
lru_clock:55923
2.3更新服务器每秒钟执行命令次数
函数中的
trackOperationsPerSecond
函数会以每
100
毫秒一 次的频率执行,这个函数的功能是以抽样计算的方式,估算并记录服务 器在最近一秒钟处理的命令请求数量,这个值可以通过INFO status
命令 的instantaneous_ops_per_sec域查看
redis> INFO stats
# Stats
...
instantaneous_ops_per_sec:6
解析:上面的命令结果显示,在最近的一秒钟内,服务器处理了大概六个命令
2.4更新服务器内存峰值记录
struct redisServer {
// ...
//
已使用内存峰值
size_t stat_peak_memory;
// ...
};
每次serverCron函数执行时,程序都会查看服务器当前使用的内存 数量,并与stat_peak_memory保存的数值进行比较,如果当前使用的内 存数量比stat_peak_memory属性记录的值要大,那么程序就将当前使用 的内存数量记录到stat_peak_memory属性里面
INFO memory命令的used_memory_peak和 used_memory_peak_human两个域分别以两种格式记录了服务器的内存 峰值
redis> INFO memory
# Memory
...
used_memory_peak:501824
used_memory_peak_human:490.06K
2.5处理sigterm
在启动服务器时,Redis会为服务器进程的SIGTERM信号关联处理 器sigtermHandler函数,这个信号处理器负责在服务器接到SIGTERM信 号时,打开服务器状态的shutdown_asap标识
// SIGTERM
信号的处理器
static void sigtermHandler(int sig) {
//
打印日志
redisLogFromHandler(REDIS_WARNING,"Received SIGTERM, scheduling shutdown...");
//
打开关闭标识
server.shutdown_asap = 1;
}
每次serverCron函数运行时,程序都会对服务器状态的 shutdown_asap属性进行检查,并根据属性的值决定是否关闭服务器
truct redisServer {
// ...
//
关闭服务器的标识:
//
值为1
时,关闭服务器,
//
值为0
时,不做动作。
int shutdown_asap;
// ...
};
2.6管理客户端资源和数据库资源
1.管理客户端
erverCron函数每次执行都会调用clientsCron函数,clientsCron函数 会对一定数量的客户端进行以下两个检查:
·如果客户端与服务器之间的连接已经超时(很长一段时间里客户 端和服务器都没有互动),那么程序释放这个客户端。
·如果客户端在上一次执行命令请求之后,输入缓冲区的大小超过 了一定的长度,那么程序会释放客户端当前的输入缓冲区,并重新创建 一个默认大小的输入缓冲区,从而防止客户端的输入缓冲区耗费了过多 的内存
2.管理数据库
serverCron函数每次执行都会调用databasesCron函数,这个函数会 对服务器中的一部分数据库进行检查,删除其中的过期键,并在有需要时,对字典进行收缩操作,
2.7对持久化的影响
1.执行被延后的BGrewriteaOF
在服务器执行BGSAVE命令的期间,如果客户端向服务器发来 BGREWRITEAOF命令,那么服务器会将BGREWRITEAOF命令的执行 时间延迟到BGSAVE命令执行完毕之后
服务器的aof_rewrite_scheduled标识记录了服务器是否延迟了 BGREWRITEAOF命令
struct redisServer {
// ...
//
如果值为1
,那么表示有 BGREWRITEAOF
命令被延迟了。
int aof_rewrite_scheduled;
// ...
}
2.检查持久化操作的影响
服务器状态使用rdb_child_pid属性和aof_child_pid属性记录执行 BGSAVE命令BGREWRITEAOF命令的子进程的ID 这两个属性也可 以用于检查BGSAVE命令或者BGREWRITEAOF命令是否正在执行
struct redisServer {
// ...
//
记录执行BGSAVE
命令的子进程的ID
:
//
如果服务器没有在执行BGSAVE
,
//
那么这个属性的值为-1
。
pid_t rdb_child_pid; /* PID of RDB saving child */
//
记录执行BGREWRITEAOF
命令的子进程的ID
:
//
如果服务器没有在执行BGREWRITEAOF
,
//
那么这个属性的值为-1
。
pid_t aof_child_pid; /* PID if rewriting process */
// ...
}
检查流程
3.将AOF缓冲区中的内容写入AOF文件
如果服务器开启了AOF持久化功能,并且AOF缓冲区里面还有待写 入的数据,那么serverCron函数会调用相应的程序,将AOF缓冲区中的 内容写入到AOF文件里面
2.8 增加cronloops的值
服务器状态的cronloops属性记录了serverCron函数执行的次数
struct redisServer {
// ...
// serverCron
函数的运行次数计数器
// serverCron
函数每执行一次,这个属性的值就增一。
int cronloops;
// ...
}
cronloops属性目前在服务器中的唯一作用,就是在复制模块中实 现“每执行serverCron函数N次就执行一次指定代码”的功能
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/129582.html