作者:章建(处知)
概述
日志服务 SLS 是云原生观测和分析平台,为 Log、Metric、Trace 等数据提供大规模、低成本、实时的平台化服务。SLS 提供了多地域支持 [ 1] ,方便用户可以根据数据源就近接入 SLS 服务,减少不必要网络延迟以及公网费用。然而,当前 SLS 并不支持跨域(更准确说是跨 project)进行查询和分析,如果需要将不同地域的数据进行联合查询或分析,该怎么办呢?
当前的做法是:通过加工任务将不同地域的数据复制到同一个 project 下(查询要求写到同一个 logstore)。然而,对于联合查询或分析不频繁的场景来说(比如定期生成报表),这样做成本显然太高(额外全量数据的存储费用和公网流量费用),而且比较繁琐(为每个地域的 logstore 创建加工任务)。有没有更好的方式解决这种问题呢?
为了解决上面的问题以及其他相关的问题,我们推出了 StoreView 相关的功能。StoreView 允许将多个 project(支持跨域)的 logstore 数据组合成一个虚拟的 logstore 使用,不仅支持跨 project 的联合查询和分析,还支持以 ad-hoc 的方式对数据进行隔离、富化以及对齐等。下面通过具体实例对 StoreView 功能加以详细说明,主要分为查询和分析两大块。
数据准备
本文测试数据来自两个不同地域的 project,具体信息说明如下:
为了方便测试 StoreView 功能,上面两个数据集的 schema 故意引入了两类不一致的地方,即字段 UnitsSold 的类型以及计价相关字段名称(walmart 采用 usd 计价,rtmart 采用 rmb 计价)。
查询
联合查询
首先,在任意一个支持 StoreView 功能的地域创建如下 StoreView 定义:
等待一分钟左右后,就可以在控制台像使用 logstore 一样来使用新建的 StoreView all_market_data 了。
从上面的执行结果(日志条目数量以及 historgram 的柱状图)不难看出,StoreView all_market_data 的查询结果和预期是完全匹配的。
数据隔离
当前 SLS 仅支持 logstore 级别的授权,即要么对整个 logstore 有读或写权限,要么没有。但有时用户希望某些子账号仅仅能访问 logstore 中的部分数据,之前是无法做到的。但有了 StoreView 功能后,这个就比较容易实现了。比如,不允许某个子账号访问 walmart-market 和 rtmart-mart 的全部数据,但允许他访问来自 China 的 market 数据,那么可以定义如下 StoreView:
上面的 StoreView定义中,对每个 logstore 加上了查询条件,限定了 StoreView 只能读取 Country 字段为 China 的数据。具体查询效果如下所示:
通过上面的查询对比可以知道,StoreView market_data_from_china 只能看到来自 China 的 market data,而其他地域的数据是无法查询到的。因此,StoreView 提供了灵活的数据隔离能力。
数据富化
当前 StoreView 联合查询多个 logstore 时,返回的是用户原始日志数据,而数据本身可能缺少一些重要的区分特性,比如日志数据具体来自那个底层的 logstore。因此,StoreView 还支持通过 SPL 语句进行数据富化以及加工操作(当前仅仅支持 where 和 extend 算子)。比如,希望 market_data_from_china 返回的结果中,可以显示具体数据来自底层哪个 logstore,则可以定义如下 StoreView:
上图红框中,| 线后面便是 SPL 语句,它为日志扩展了 logstoreName 字段,具体执行效果如下:
可以看到,返回的结果中增加了字段 logstoreName。当然,上面的 SPL 语句仅仅是为了说明富化功能,logstore 以及 project 信息其实已经自动包含在了日志的 tags 中了。另外,extend 算子是动态新增字段到返回结果中的,这种字段不能用于查询过滤,否则会报错。
分析
联合分析
除了能够基于 StoreView 对跨 project 进行联合查询外,还可以进行联合分析,比如对 Country 为 China 的 market 数据,按照 ItemType 统计订单的数量:
可以看到,对 StoreView 进行 SQL 分析和对 Logstore 进行 SQL 分析并没有什么区别。
meta columns
同 StoreView 进行查询类似,进行 SQL 分析时,服务端自动提供了两个 meta columns:project 和 logstore。通过这两个字段,用户可以在 SQL 中识别数据具体来自哪个 project 以及 logstore(可以在 where 条件中通过 project 或者 logstore 过滤 StoreView 的结果)。比如,当需要按照 project 对 StoreView 中的结果进行分析统计时,可以采用如下 SQL:
column 类型兼容处理
使用 SQL 分析时,对于 StoreView 下所有 logstore 共有的 column,如果它们的类型一致,那么在分析时不会有歧义。但如果类型不一致时,可能出现什么问题呢?比如上面 walmart-market 和 rtmarkt-market 两个 logstore 中都包含 column UnitsSold,但其中是一个 long 类型,另一个为 text 类型(本来也应该为 long,但创建索引时,配错了类型)。比如,按 Country 统计卖出货物的总件数:
上图中的 SQL,会报错,即参数不符合 sum 函数的要求。这是因为,当多个 logstore 定义了不同类型的同名 column 时,服务端会将这种 column 统一为 text 类型。因此,上面的 SQL 只要对 UnitsSold 做个类型转换,就能正常工作了。
column 自动补齐
StoreView 中,不仅存在类型不兼容的 column,还可能存在 column 名称没有对齐的情况,比如 logstore#1 包含(column#1, column#2),logstore#2 包含(column#2, column#3, column#4)。那么 StoreView 会包含哪些 column 呢?答案是:(column#1, column#2, column#3, column#4)。对于 logstore#1,column#3 和 column#4 会自动设置为 null;而对于 logstore#2,column#1 则会自动设置为 null。
对于上面的 SQL 结果,rtmart-market 因为没有包含 TotalRevenueUsd,所以 TotalRevenueUsd 列为 null;相反,对于 walmart-market,TotalRevenueRmb 列则为 null。
column 扩展和加工
对于 rtmart-market 和 walmart-market 两个 logstore 的所有数据,如果按照 region 统计 TotalRevenue,该怎么操作?因为 rtmart-market 的 TotalRevenueRmb 列和 walmart-market的 TotalRevenueUsd 列,不仅名称不一样,计价单位也不一样,要统计总收入,需要统一到相同的货币,比如采用如下 SQL:
虽然上面的 SQL 可以工作,但每次统计都要输入这么复杂的语句,显然不太方便,是否有更好的做法呢?必须有,和上面查询进行数据富化类似,StoreView 允许通过 SPL 句法对 SQL column 进行扩展,比如定义如下 StoreView:
上面 StoreView 定义中,通过 SPL 将 TotalRevenueRmb 和 TotalRevenueUsd 统一到相同语义的新增列 TotalRevenue,基于 StoreView all_aligned_market_data 按照 Region 统计总收入的 SQL 可以简化为:
总结
通过上面的实例分析可以看到,SLS StoreView 功能为用户提供了极为便捷的跨 project 查询和分析能力,用户不再需要通过创建加工任务来汇聚数据,节省了用户的使用成本。另外,StoreView 还集成了数据隔离的能力,提供了方便灵活的数据授权方式。当然,因为跨 project 进行查询和分析,会涉及到跨域读取数据,整个处理链路受网络影响可能较大。后期我们会不断完善 StoreView 的易用性、稳定性和性能,让用户基于 StoreView 就能轻松愉悦地查询分析全地域的数据,真正做到数据分析不受地域边界的限制。
相关链接:
[1] 多地域支持
https://help.aliyun.com/zh/sls/product-overview/supported-regions