Pika命令耗时统计功能技术文档

背景

Pika 可以通过慢查询 (Slowlog) 来查询每个命令的执行时间,不过不能进行统计归类(例如多条set 命令的执行情况会依次展示出来,没有统计功能),并且 Pika 对各个命令的调用次数没有统计功能,只对总命令调用次数有统计功能。原因在于 Pika 没有实现 Redis 的 info Commandstats 命令,Redis 的这个命令可以统计各个命令的耗时情况以及调用次数(以微秒计),Pika 也需要支持这个命令

以下是 Redis 的 Info Commandstats:

其中 cmdstat_set 是命令名称,calls(命令调用次数),usec(命令耗时),usec_per_call(命令平均执行时间)

截屏2023-07-05 18.16.25.png

解决方案

Pika 目前已经支持慢查询命令只是没有统计的功能,我们可以用慢查询里面的对单个命令耗时统计功能函数,而Pika 所有的命令都装在Cmd_table 里面,我们可以用一个结构体放在 Cmd 基类中,里面封装 calls,usec 这两个变量来实现对命令的统计功能,执行 info Commandstats 命令时我们对相应的 cmd 判断,如果里面的 calls 不为0 则展示其信息,避免对未调用过的命令进行不必要的展示。

关键代码改动

include/pika_command.h

截屏2023-07-05 18.28.48.png

这里用 cmd_count 和 cmd_time_consuming 来统计对各个命令的总耗时和调用次数并初始化为 0,利用原子变量避免多线程安全问题.

src/pika_client_conn.cc

截屏2023-07-05 19.24.16.png

这里的 c_ptr->Execute 是命令的执行函数,在执行完这个函数后我们对时间进行统计,这里我用的慢查询那边的函数把结果存在 duration 中,然后从 CmdTable 中给相应的 cmd 的 count 和 time_consuming 修改值,从而实现功能.

src/pika_admin.cc

截屏2023-07-05 19.19.03.png

这个是命令本身的实现逻辑,利用 g_pika_cmd_table_manager->GetCmdTable() 返回一个 <std::string, std::unique_ptrcmd>的指针,遍历它判断每个命令的调用情况是否为 0,是的话跳过不打印,否则打印出相应信息并留小数点后两位。

实现情况

截屏2023-07-05 19.28.14.png

我们将慢查询的参数 slowlog-log-slower-than 设置为 0,来对每个命令的耗时进行查询,可见图中两次 set 的耗时分别是 140us 和 444us 两个值相加与我统计出来的 usec 的值 584 一样,平均耗时则为总耗时除以调用次数.

相关 PR: #1660

相关 Issue:#977