背景
众所周知,在许多行业中,例如电力行业、化工行业、气象行业、地理信息等行业,都需要对所关注对象进行监测、检查与分析。在此过程中,数据“无”往往也代表被监测对象的一种状态,比如说服务不可用、运行时不存在错误等等。
每一种“无”有其特定的、符合业务逻辑的特定含义。所以“无”也是一种需要能够被展示、监测的对象。对于“无”的监测往往是基于“有”进行的,即单位时间内“有”的聚合值为0,即是该段时间内“无”的存在。
电力行业、化工行业、气象行业、地理信息等行业中,时间序列数据库常常被用于各类型实时监测、检查与分析设备所采集、产生的数据。而在鸿鹄中,相类似的功能也被提供,如仪表盘、告警等。
用户能够通过在仪表盘中创建图表对所关注对象进行监控、使用告警以觉知所监控对象发生了错误、并组合多个仪表盘的图表对监控对象进行错误分析与解决。
在目前常见的时间序列数据库中,方法time_bucket被提供以便用户将单位时间(日、时、分等)内的数据进行聚合,以提供足够的数据将对监控对象的运行情况在图表中确切地反映出来。
然而time_bucket有其局限性。当单位时间内,不存在任何数据时,time_bucket无法返回该时间段内的数据,即在结果集中,对应时间段内没有任何数据。
此现象造成绘制图表时,缺少数据的时间段的取值表现为前后两个有数据的时间段的数据的平均值,而隐藏了没有数据的事实。
因此,在时间序列数据库中,方法time_bucket_gapfill被提供。当单位时间内没有数据值,返回值中仍然会有该时间段的记录,只是记录的聚合值为空。基于这样的结果集,图表绘制时能够明确显示出数据不存在的情况。
鸿鹄已支持time_bucket的使用,详细信息可以参见使用手册;尚不支持time_bucket_gapfill的使用。因此针对“无”的展示、监测,需要通过组合查询语句达成。
场景举例
在一般的网络应用的监控中,服务的可用性(Availability)是一个极其重要的指标。一般有两种方式对服务可用性进行检查:
1、在服务外建立可用性测试(Availability Test)机制,定期调用服务的健康检查(Health Check)API,以确定服务的运行状态。Amazon Web Services和Microsoft Application Insight均有此类功能。
-
此机制在测试机制被服务器拒之门外时无法使用
2、在服务内实现定期向指定数据库上报可用性数据的机制。如使用opentelementry
-
此机制在防火墙屏蔽了外部应用对服务的调用时可以采用
-
此机制在服务不可用时,无法向指定数据库上报数据
正如上述描述,在第二种情况下,如果服务不可用,则无法向指定数据库上报数据,因此造成了数据缺失,而这数据缺失恰恰又反映了服务不可用。
试想一下以下的场景。某服务运行时,每隔15秒向鸿鹄报告一次可用性数据,格式如下:
其中_time表示发送报告的时间;availability表示运行状态,固定为1,表示运行中。
假设在9:37:59,服务由于未知原因奔溃并重启,在9:39:01重启完毕。在此情况下,鸿鹄中不会有该服务在9:38:00~9:39:00的可用性数据。原因是应用崩溃了,可用性报告机制不可用。
此时,如果仅用time_bucket作聚合,如:
则在结果集中看到该服务在9:38:00之前以及9:39:00之后有数据条目,但是在9:38:00~9:39:00之间没有数据。
这个结果是符合预期的。不过对于鸿鹄仪表盘的图表来说,这个结果集并不那么友好。因为9:38:00~9:39:00之间的“没有数据即是服务不可用”是业务逻辑,其本身超越了作图的范畴。因此,我们看到的结果是9:37:00、9:39:00的数据被认为是图上的两个点,直接对这两个点进行连线,从而掩盖了9:38:00没有数据事实。
然而真实的服务可用性状态是下图所示的情况:
为了让图表真实地反映服务运行的状态,必须把“没有数据即是服务不可用”的业务逻辑引入结果集,即9:38:00~9:39:00之间必须包含数据且对应的可用性数据值为0
解决方案
1、使用generate_series序列。其中generate_series的第一参数、第二参数表示起始值与结束值,第三参数表示步长,通过DATE_ADD生成时间序列,如:
上述代码生成了以当前时间为基准,过去一个小时内,以1分钟为单位的时间序列。
2、使用time_bucket对生成序列进行聚合,并赋与默认值,如:
上述代码中 0 AS availability是默认值。
3、使用time_bucket对现有数据进行聚合,如:
4、使用外联,进行最终聚合,如
上述代码将2、3进行左外联,将时间序列缺失的数据以默认值填充。
完整示例:
将上述代码应用于鸿鹄仪表盘的图表中,即获得以下展示效果:
优点
相对time_bucket_gapfill灵活,可以赋与默认值,而不是空,便于最终展示。
缺点
需要手动控制generate_series生成的开始、结束、步长,需要额外代码适应不同的时间范围。
代码结构相对复杂。
总结
在一般的概念中,“有”往往是人关注的焦点。然而,“无”通常也是不可被忽视的。某些“无”的状态也是衡量一个对象是否可用、正常的一个重要指标,然而“无”并不是一个能直接衡量的指标,它只能通过“有”的不存在来体现。而“有”的不存在往往只能通过统计、聚合来达成。
在时序数据库中,一些开箱即用的方法被提供以用来处理“无”。而在鸿鹄,甚至现有的主流云平台,例如Microsoft Azure上,往往将“无”体现为没有数据,而不能直接操作,甚至“无”被埋没在“有”的汪洋大海中,而无法被识别。为了将“无”这根针从“有”的大海中捞出来,可以通过手动生成时间序列并组合现有数据的方式,将“无”反映出来。