首页 > 其他分享 >更快更强,SLS 推出高性能 SPL 日志查询模式

更快更强,SLS 推出高性能 SPL 日志查询模式

时间:2024-08-21 17:15:21浏览次数:8  
标签:场景 查询 过滤 SPL 日志 SLS where

作者:无哲

引言

随着数字化进程的持续深化,可观测性一直是近年来非常火热的话题,在可观测的三大支柱 Log/Trace/Metric 中,日志(Log)数据一般是最为常见的,企业迈向可观测性的第一步,也往往始于日志数据的采集上云。日志完成收集后,最直接的需求就是从海量日志数据中检索分析出有价值的信息。随着日志数据量的不断增长,数据种类不断增多并日益朝着非结构化、多场景、多模态等方向演进,传统的日志搜索方式已经越来越难以满足不同场景下多样化、个性化的分析需求。

日志数据的查询分析需求是多样化的

日志(Log)数据作为可观测场景中最基础的数据类型之一,具备以下特点 :

  • 不可变: 日志数据一旦产生就不会被再次修改,是对事件原始信息的忠实记录,往往结构不太固定。
  • 数据随机: 比如异常事件日志、用户行为日志,一般天然就是随机的、难以预测的。
  • 来源多样: 日志数据种类繁多,不同来源的数据难以具有统一的 Schema。
  • 业务复杂: 不同的业务参与方对数据的理解不同,写日志过程中难以预见到后期具体的分析需求。

这些因素导致日志数据在采集过程中往往并不存在一个理想的数据模型可以用来预处理日志数据,因此更常见的做法是直接采集存储原始的日志数据,这可以称为是一种 Schema-on-Read 的模式,或者是所谓的寿司原则(The Sushi Principle:Raw data is better than cooked, since you can cook it in as many different ways as you like)。

这种直接存储原始数据的做法,意味着在分析的时候往往需要动态实时的对数据进行处理(比如 json 处理、正则提取、数学计算等等);而且由于不同分析人员对数据特征缺乏先验知识,一般也需要对数据先进行一定的探索式分析。

也就是说,在日志查询分析的过程,既需要能够展现非结构化的文档结构,又需要丰富的算子进行实时处理,同时最好还能够便捷的支持级联式、探索式的分析方式。

理想的日志查询语法应该是什么样的

日志数据分析通常可以分为两大类场景:

一类是查询类场景,或者说是搜索场景、纯过滤场景,即按照特定的条件过滤掉不需要的日志,并针对符合条件的日志直接输出日志原文。

一类是分析类场景,主要包括聚合分析(比如 sum、sort)、关联分析(比如多个表 join),需要对数据进行更复杂的计算,输出结果一般是表格模式。

这里我们重点关注纯查询过滤的场景,在 SLS 中既可以用传统的搜索语法(如 Key:XXX ),也可以在标准 SQL 中使用 where 语句(如 * | select * where Key like '%XXX%'),两种方式各有优点,却也都有着各自的局限性。

对于查询语法来说,天然就是为过滤搜索场景而生的,但是可惜表达能力有限,只能支持关键词匹配,以及多个条件的 And/Not/Or 的逻辑组合,无法支持更为复杂的处理逻辑。

而对于 SQL 语法来说,优点是表达能力强,但 SQL 是表格模型,不便于查看原始日志结果(因为要将字段对齐,输出结果中对于不存在的列就会填充大量 null),而且对于 select * 这样的语句,也只能输出开启字段索引的字段。

详细对比如下:

纯查询场景的挑战 搜索查询语法 标准SQL语法
需要复杂的处理逻辑 弱,主要就是支持关键词匹配 强,具备丰富的处理函数和算子,如正则匹配、json提取
输出内容是非结构化的 强,输出的是原文,便于查看 弱,输出的是表格模式,不存在的字段全部要补空值,不利于查看
翻页逻辑 简单,控制台可以直接点,API传递offset+lines即可 较复杂,需要在SQL中通过limit x,y的方式,并且要指定排序方式
查看结果的时间分布 简单,histogram柱状图直观展示出不同时间的分布 较复杂,需要在SQL中按照时间分组求和,再按时间排序,然后再画线图查看
结果中输出所有原文字段 输出的是原文,天然包含所有字段 较麻烦,select * 只能输出建了字段索引的列
获取部分字段 不支持 select指定列即可
计算出新的列 不支持 select中可以计算新的列
多级级联处理能力 无法表达 可以通过with语句、SQL嵌套,但写起来较为复杂

既然两种方式各有所长,那么我们是否可以结合这两种方式的优点,支持一种新的查询语法,既能遵从文档模型(直接输出日志原文、不按表格模式、不要求所有输出列有索引),又能支持各种好用的 SQL 算子,同时还能够支持一种更便捷的级联处理(而不需要复杂的多层嵌套)呢?

SPL 管道式查询语言

SPL(详见 SPL 概览 [ 1] ),即 SLS Processing Language,是 SLS 对日志查询、流式消费、数据加工、Logtail 采集、以及数据 Ingestion 等需要数据处理的场景,提供的统一的数据处理语法。

SPL 基本语法如下:

Status:200 | extend urlParam=split_part(Uri, '/', 3)

其中 是数据源,对于日志查询的场景,指的就是索引查询语句。 是 SPL 指令,支持正则取值、字段分裂、字段投影、数值计算等多种丰富的操作,具体参考 SPL 指令介绍 [ 2]

从语法定义上可以看到,SPL 是支持多个 SPL 指令组成管道级联的。对于日志查询的场景来说,在索引查询语句之后,可以根据需要通过管道符不断追加 SPL 指令,从而获得类似 Unix 管道处理文本数据的体验,对日志进行灵活的探索式分析。

SPL 能做什么?

筛选字段获得更精确的视图

在查询日志的时候,往往是带着某个目的去检索,这个时候一般是只关心其中的部分字段。这时就可以使用 SPL 中的 project 指令,只保留自己关心的字段。(或者使用 project-away 指令,移除不需要看到的字段)

实时计算出新的字段

使用 Extend 指令,可以基于已有字段加工提取出新的字段,可以使用丰富的函数(这些大部分是和 SQL 语法通用的)进行标量处理。

Status:200 | extend urlParam=split_part(Uri, '/', 3)

同时也可以根据多个字段计算出新的字段,比如计算两个数字字段的差值。(注意字段默认是被视为 varchar,进行数字类型计算的时候要先通过 cast 转换类型)

Status:200 | extend timeRange = cast(BeginTime as bigint) - cast(EndTime as bigint)

并且也可以在后续管道中,再对这个计算后的值进行 where 判断过滤:

Status:200 
| where UserAgent like '%Chrome%'
| extend timeRange = cast(BeginTime as bigint) - cast(EndTime as bigint)
| where timeRange > 86400

自由的展开半结构化数据

SPL 提供了 parse-json、parse-csv 这样的指令,可以将 json、csv 类型的字段,直接完全展开出为独立的字段,之后就可以直接对这些字段进行操作。省去了书写字段提取函数的开销,在交互式查询场景中这种写法是更为便捷的。

SPL 之前已经在扫描查询模式上全地域支持,详见扫描查询 [ 3] 。扫描查询可以不依赖索引,直接扫描原始日志数据计算。下图中这个例子,就是在原始日志数据上,通过 SPL 管道完成了模糊过滤、json 展开、字段提取等多种操作。

当前扫描模式 SPL 难以处理大规模数据

扫描模式具备很好的灵活性,但最大的问题是性能不足,特别是面对大规模数据时难以在有限时间内处理完。现有的扫描查询限制单次最多扫描 10 万行,超出限制后需要控制台手动点击触发下一次扫描(或者 SDK 触发下一次调用)。

由于性能受限,导致现有的 SPL 查询在使用上存在以下问题:

  • 对于过滤结果较为稀疏的查询,由于单次扫描的原始数据量太少,很难在有限时间内扫描到结果。
  • 查询界面的直方图展示的是索引过滤后的结果(以及扫描进度),而无法展示出 SPL 条件过滤后的最终结果分布。
  • 无法支持针对最终过滤后的结果随机翻页,只能按照已经扫描的原文的 offset 进行连续翻页扫描。

这些约束,导致扫描模式下的 SPL,面对具备较大规模的日志数据,使用体验较差,也就很难发挥出实际用处。

极致优化,高性能 SPL 模式

为了从根本上改善 SPL 查询的执行性能,真正发挥出 SPL 灵活计算的优势。我们从计算架构、执行引擎、IO 效率等多个方面对 SPL 查询进行了重大优化。

计算下推,并行化加速

首先要在架构上解决水平扩展的问题。原有的架构下,因为存储节点不具备复杂表达式的计算能力,只能将原始数据全量拉取到计算节点处理,大数据量的读取、传输、序列化是很大的瓶颈。

在查询场景下,实际单次请求每次需要的最终结果行数是比较少的(一般单次请求 100 行以内,超出后通过翻页请求获取),关键在于当 SPL 语句中包含 where 条件的时候,就存在从大量数据中计算 where 条件过滤的过程。为了能够处理大规模数据并减少传输开销,我们就需要将 where 条件的计算下推到各个 shard 所在的存储节点上处理。相应的,也就必须要求存储节点具备对 SPL 中丰富算子的高效处理能力。

为此我们在存储节点上,引入 C++ 向量化计算引擎,在存储节点上读取了原始的数据后,直接原地就可以进行高效的过滤计算。只有对满足 where 条件的日志,才需要进行剩余的 SPL 计算并输出最终结果。

计算下推之后,整个的处理能力就可以随着 shard 数目水平扩展,同时也大幅减少了存储节点和计算节点之间的数据传输、网络序列化开销。

向量化计算,多级火箭加速

计算下推解决了按 shard 水平扩展的问题,接下来我们还要进一步的大幅提升每个 shard 上的处理能力。

扫描模式的 SPL,最大性能瓶颈还是在于直接扫描读取原始的行数据。这样读放大会比较严重,IO 效率很低。正如使用 SQL 分析能力时需要开启字段索引(并开启统计),这些字段的数据就可以被高效的读取和计算,那 SPL 同样也可以基于字段索引来进行高性能的数据 IO,然后再基于 SIMD 向量化技术进行高性能计算,同时在过程中尽可能减少额外计算量。

以图中的 SPL 为例,在下推到存储节点后,会经过“多级火箭”进行层层加速:

  • 按照查询时间范围过滤(当数据量非常大时,建议选择必要的时间范围进行分析)。
  • 处理第一级管道 Status:200 ,关键词索引条件过滤(这个是最快的,有索引过滤条件尽量写上过滤条件)。
  • 处理 SPL 中的 where 过滤条件,基于字段索引(并开启统计),高效读取对应的数据。
  • 向量化高性能计算,获得过滤结果,然后再计算剩余的 SPL 部分,得到最终结果
  • 同时在计算过程中,如果发现过滤结果行数已经满足要求,则尽量提前终止(特别对于高命中率的情形,可以尽量减少不必要的计算)。

经过这些优化之后,高性能 SPL 的执行性能相比扫描模式,得到了质的飞跃。

高性能 SPL 的性能表现

我们以单个 shard 处理 1 亿行数据为例,来评估高性能 SPL 的性能表现。在线上真实环境创建一个 Logstore,10 个 shard,查询时间范围内有 10 亿数据。(服务访问日志数据)

选取如下几个典型的场景:

场景 1:通过字符串函数处理后过滤

SPL 语句:* | where split_part(Uri, '#', 2) = 'XXX'

场景 2:短语查询、模糊查询

SPL 语句:* | where Content like '%XXX%'

场景 3:json提取子字段,然后再过滤

SPL 语句:  * | where json_extract_scalar(Params, 'Schema') = 'XXX'

在上述语句中选择不同的比较参数,构造出不同的命中率的场景(比如命中率 1%,指的是原始 10 亿条数据中,有 1000 万条满足 where 条件的结果数据),并请求前 20 条满足条件数据(对应 GetLogs 接口的 API 参数是 offset=0, lines=20),测试平均耗时。

命中率 场景1 耗时 场景2 耗时 场景3 耗时
1% 52 ms 73 ms 89 ms
0.1% 65 ms 94 ms 126 ms
0.01% 160 ms 206 ms 586 ms
0.001% 1301 ms 2185 ms 3074 ms
0.0001% 2826 ms 3963 ms 6783 ms

可以看出:

  • 当命中率较高时,不同场景下都有很好的性能表现,甚至可以接近关键词索引查询。
  • 当命中率很低时,由于要实时计算大量数据,需要更长一些的执行时间,具体实际性能表现和数据字段的长度、语句中算子复杂度、命中结果在原始数据的分布位置等因素都有关。
  • 整体来看,高性能 SPL 对于数十亿级别的日志量级,可以在数秒内完成计算。

控制台交互升级,展示过滤后结果的直方图

高性能模式 SPL,由于计算性能有了大幅提升,因此控制台展示 histogram,直接展示的是整个 SPL 语句过滤后的结果分布。(意味着整个范围内的数据也进行了全量的计算)

举个例子,原始日志有 1000 万条,SPL 语句是 Status:200 | where Category like '%xx%',符合 Status:200 条件的日志是 10 万条,这其中再符合 where Category like '%xx%' 条件的日志是 1000 条,则查询界面上 histogram 柱状图展示的是这最终的 1000 条日志随时间的分布情况。

相应的,和纯索引查询模式下的交互完全相同,高性能模式 SPL 支持随机翻页,也支持点击柱状图直接跳转到对应区间的查询结果。

API 调用简化,统一的 offset 语义

在高性能 SPL 模式下,调用 GetLogs 通过 SPL 语句查询日志时,offset 直接表示的就是过滤后的结果偏移量,从而大大简化了 API 调用方式。也就是说,使用上,和纯索引查询完全统一。直接按照过滤后最终结果的 offset 来翻页即可。

使用说明

如何开启高性能 SPL?

无须显式指定运行模式。当 SPL 语句中所有参与 where 条件计算的列,全都已经创建了字段索引(并开启了统计),则自动按照高性能模式执行;否则以扫描模式执行。

是否计费?

高性能 SPL 模式,查询本身不产生任何额外费用。

标签:场景,查询,过滤,SPL,日志,SLS,where
From: https://www.cnblogs.com/alisystemsoftware/p/18372127

相关文章

  • 日志收集分析和告警在故障排查中的重要性
    日志收集分析和告警在故障排查中的重要性在数字化时代,软件服务的稳定性至关重要。即便是像网易云音乐这样的大型平台,也难免遇到突发的技术故障。例如,在8月19日下午,网易云音乐疑似出现服务器故障,导致网页端出现502BadGateway报错,App也无法正常使用。这种情况不仅严重影响......
  • mysql 二进制日志总结
    常用sql语句查看二进制日志文件位置SHOWVARIABLESLIKE'log_bin_basename';查看二进制日志文件的索引文件位置SHOWVARIABLESLIKE'log_bin_index';查看二进制日志文件的过期天数SHOWVARIABLESLIKE'expire_logs_days';//取值范围0-99默认0关闭列出MySQL......
  • 火语言RPA流程组件介绍--输出日志
    输出日志......
  • 机械学习—零基础学习日志(如何理解概率论3)
    随机变量的函数分布一维随机变量分布,可以看到下图,X为不同情况的概率。而x如果是大于等于X,那么当x在40以内时,没有概率,为0。当x变大,在40-80之间,那么x大于X的概率为,0.7,所以随着x增大,概率会越来越高。同时概率是如下图所示,为离散型,间断性增加的。对于不同类型的,比如离散型,连续......
  • 【待做】【安全框架】【日志管理平台】
    为了更好的了解各业务系统的运行状态,企业通常需要搭建统一的日志中心,并将各业务系统的系统日志、应用程序日志和安全日志传送到日志平台。系统管理员和业务负责人通过日志,可以详细了解服务器软硬件信息、系统运行状况以及风险,从而及时采取对应的应对措施。一、对比传统的日志管......
  • 使用对比!SLS 数据加工 SPL 与旧版 DSL 场景对照
    作者:灵圣概述如前一篇《SLS数据加工全面升级,集成SPL语法》所述,SLS数据加工集成了SLS数据处理语法SPL。与旧版本数据加工DSL相比,SPL在处理非结构化数据的场景中,其语法简洁度上有很多提升,比如中间类型保持、字段引用、无缝兼容SQL函数等。这里我们继续讨论在不同的数......
  • svnhook---在提交前检查用户是否填入需要的日志
    一:svnhook机制svn的hook机制,跟其他很多类似的工具一样,hook机制的本身就是在某个具体的时机所触发的内容,类似于事件驱动的回调。举个简单的例子,我们使用svncommit的时候如果希望对日志的信息进行判断,如果日志中没有包含指定的信息,提示相关的错误信息,不允许提交。这样的场景,就是h......
  • 记录一次达梦日志报错解析Server page chack error
    数据库宕机,日志报错Serverpagechackerror 很明显是数据页的问题,需要定位到相关表,删除重建根据线程号T0000000000003539136中的 3539136去慢SQL中查对应的脚本下载慢日志,找线程号对应的脚本,用到了11次复制出来脚本,找到对应的表使用DTS把数据迁移到备份表上 再删除......
  • MongoDB Profiling慢日志详解
    MongoDB的Profiler类似MySQL的SlowLog和GeneralLog的结合,通过设置不同的Profiling级别,来决定记录哪些实例执行过的CURD、配置和管理命令。Profiler会将搜集的内容记录在每个被Profiled的数据库中,名为system.profile的capped固定集合中。开启Profiling会对数据库性能造成一定的损......
  • 基于“日志审计应用”的 DNS 日志洞察实践
    作者:羿莉(萧羿)基础背景DNS(DomainNameSystem)[1]是任何网络活动的基础。它将易于记忆的域名转换为机器能够理解的IP地址。监控DNS服务可以帮助用户识别网络活动并保持系统安全。出于合规和安全性的考虑,公司通常要求对网络日志进行存储和分析。通过DNS日志,可以清晰......