背景
Pika 可以通过慢查询 (Slowlog) 来查询每个命令的执行时间,不过不能进行统计归类(例如多条set 命令的执行情况会依次展示出来,没有统计功能),并且 Pika 对各个命令的调用次数没有统计功能,只对总命令调用次数有统计功能。原因在于 Pika 没有实现 Redis 的 info Commandstats 命令,Redis 的这个命令可以统计各个命令的耗时情况以及调用次数(以微秒计),Pika 也需要支持这个命令
以下是 Redis 的 Info Commandstats:
其中 cmdstat_set 是命令名称,calls(命令调用次数),usec(命令耗时),usec_per_call(命令平均执行时间)
解决方案
Pika 目前已经支持慢查询命令只是没有统计的功能,我们可以用慢查询里面的对单个命令耗时统计功能函数,而Pika 所有的命令都装在Cmd_table 里面,我们可以用一个结构体放在 Cmd 基类中,里面封装 calls,usec 这两个变量来实现对命令的统计功能,执行 info Commandstats 命令时我们对相应的 cmd 判断,如果里面的 calls 不为0 则展示其信息,避免对未调用过的命令进行不必要的展示。
关键代码改动
include/pika_command.h
这里用 cmd_count 和 cmd_time_consuming 来统计对各个命令的总耗时和调用次数并初始化为 0,利用原子变量避免多线程安全问题.
src/pika_client_conn.cc
这里的 c_ptr->Execute 是命令的执行函数,在执行完这个函数后我们对时间进行统计,这里我用的慢查询那边的函数把结果存在 duration 中,然后从 CmdTable 中给相应的 cmd 的 count 和 time_consuming 修改值,从而实现功能.
src/pika_admin.cc
这个是命令本身的实现逻辑,利用 g_pika_cmd_table_manager->GetCmdTable() 返回一个 <std::string, std::unique_ptrcmd>
的指针,遍历它判断每个命令的调用情况是否为 0,是的话跳过不打印,否则打印出相应信息并留小数点后两位。
实现情况
我们将慢查询的参数 slowlog-log-slower-than
设置为 0,来对每个命令的耗时进行查询,可见图中两次 set 的耗时分别是 140us 和 444us 两个值相加与我统计出来的 usec 的值 584 一样,平均耗时则为总耗时除以调用次数.
相关 PR: #1660
相关 Issue:#977