如何解决查询分析与流处理两种场景下的数据口径差异

您在使用阿里云日志服务(SLS)查询分析和和流处理时,难免会碰到数据口径差异,您可以使用两种时间戳(__time__和__receive_time__)解决。

问题现象

在使用日志服务查询分析时,难免会碰到源端时间字段同步到目标端之后,发生时间不一致的问题。例如:

  • SLS一周前的数据同步到MaxCompute之后,相同的时间间隔数据条数不一致。

  • SLS的数据通过数据加工同步到另一个Logstore之后,在目标端找不到设置时间间隔中的数据。

可能原因

  • 在查询分析模式下,日志数据按照一定的时间窗口或数据量进行批处理,并输出结果。在这种模式下,数据被收集和聚合后进行分析,可以进行复杂的查询和计算。

  • 在流处理模式下,日志数据以流的形式连续到达,并立即进行处理。下游的流式任务根据__receive_time__字段进行筛选和处理。这种模式下,数据流实时处理,可以立即响应和反馈结果。

如图所示,对于两种不同模式,同样都是从2023-05-24的00:00到18:00,流模式是包含绿色数据块的,但查询分析中是不包含绿色数据块的。也就是说,查询分析和流模式所使用的数据口径是不一样的,直接使用相同数据间隔没有办法得到一致的结果。

image.png

解决方案

SLS数据的数据时间

  • __time__(日志时间):日志时间是指日志的发送时间或者数据的创建时间,例如用户访问网页的时间、商品的出售时间等等。在SLS中,主要有两种使用方法:

    • Logtail:Logtail是阿里云日志服务提供的一种轻量级日志采集工具。Logtail采集日志时,会自动在日志数据中添加创建时间。如果这个时间戳和应用程序日志时间的定义不一样(例如,事务日志是在事件发生之后基于数据库记录创建的,但业务需要定义数据中的create_time字段为日志时间),Logtail支持设置时区偏移,或者通过插件配置将日志行中的时间字段(业务时间)转换为__time__字段的值。

    • API/SDK:使用API或SDK向日志服务写入日志时,可以显式地指定__time__字段的值(默认是发送时间)。

  • __receive_time__(到达时间) :到达时间是指表示日志到达并保存到服务端的时间。在日志服务中,到达时间是一个系统标签(Tag),不允许修改。如果在创建Logstore的时候,开启了管理Logstore的功能,那么服务端就会在收到日志时自动添加时间戳作为日志标签字段。这个时间戳一般和业务处理无关。如果数据没有记录日志时间,则可以考虑使用到达时间,因为他在进入日志服务之后就不会发生变化。如图所示,如果日志在数据管道中没有延迟,那么就可以将到达时间作为日志发生的近似时间。

image.png

当一条日志数据到达日志服务时,日志服务将日志时间(字段名称为__time__)和到达时间(字段名称为__tag__:__receive_time__)做差,日志服务通过计算它们之间的差值把日志分为如下两类:

  • 如果差值位于(-180,900](单位:秒)范围内,说明是实时数据。这意味着日志数据可以立即使用和分析,适用于实时监控和快速响应的场景。

  • 如果差值位于[-7*86400,-180](单位:秒)范围内,说明是历史数据。这意味着日志数据已经存在一段时间,适用于补数据、性能分析和长期趋势分析等场景。

SLS的两种使用场景

通过记录这两种时间戳,我们可以在日志服务中进行不同的操作和分析,适用于两种不同的使用场景:

  1. 查询和分析

在常见的业务场景中,使用__time__字段可以按照日志时间进行查询和排序,以便在特定时间范围内检索和分析日志数据。

  1. 流处理功能

使用__receive_time__字段可以通过流式消费(加工、投递、消费、计算)进行数据处理,还能帮助我们了解日志数据到达系统的延迟情况,判断日志数据的实时性和延迟程度。

使用这两种时间戳有助于我们更好地理解和分析日志数据,从而满足不同的应用场景和需求。同时,它们还使得在日志服务中进行实时监控、故障排查和性能分析等操作变得更加便捷。

方案示例

下列两个问题的解决方案分别用SQL和SPL解决。关于SPL,更多参见SPL概述

  1. 用流式消费怎样计算满足__time__窗口条件的日志行数。

    在SLS的查询界面查询2023-05-23的00:00到18:00的数据N条,假设到达服务端的延时是1分钟,对于流式处理可以使用__receive_time__获得同样的N条日志。

    • SQL

      * | select * from log where __time__ >= to_unixtime('2023-05-23 00:00:00')  and  __time__ <  to_unixtime('2023-05-23 18:00:00')
    • SPL

      * | where "__tag__:__receive_time__" >= to_unixtime('2023-05-23 00:01:00')  and  __time__ <  to_unixtime('2023-05-23 18:01:00')

  2. 用查询分析怎样计算满足__receive_time__窗口条件的日志行数。

    在SLS的数据加工界面设置处理2023-05-23的00:00到18:00的数据N条,假设到达服务端的延时是1分钟,对于查询分析可以使用__time__获得同样的N条日志。

    • SQL

      * | select * from log where __time__ >= to_unixtime('2023-05-22 23:59:00')  and  __time__ <  to_unixtime('2023-05-23 17:59:00')
    • SPL

      * | where "__tag__:__receive_time__" >= to_unixtime('2023-05-23 00:00:00')  and  "__tag__:__receive_time__" <  to_unixtime('2023-05-23 18:00:00')