本文总结了大规模日志全局分析的需要,并讨论了SLS现有的典型分析方案并延伸到 SLS 介绍原始数据处理方案 Schedueld SQL 功能与最佳实践。
大规模日志全局分析需求
大规模及时的数据
随着时间的推移,基于时间的数据(日志)数量惊人。以 SLB 以七层访问日志为例,每个HTTP/HTTPS 记录一个访问请求 access log,假设每天有1000万条数据,每年有36亿条数据。一方面,长期的数据存储需要巨大的存储空间,尽管它控制了存储成本,但它也失去了有价值的历史数据。另一方面,大量的数据将造成分析上的性能压力。
大多数时序数据都具有及时性。历史数据可以接受分钟或小时的精度,而新生成的数据需要更高的精度(如监控和在线问题调查)。数据操作和分析师需要存储大量的数据进行分析,历史数据直接 TTL 删除是最糟糕的选择。
例如 Elasticsearch rollup、时序数据库的降精度用于解决这部分问题。
在各种场景中使用数据
在多种场景下,可以使用相同的日志:
- 实时数据需要支持关键字报警和时序数据 ML 检查日志上下文查询。
- 在亚秒延迟粒度方面,有全文关键词查询和交互式 SQL 需要统计分析。
- 以天为单位,需要对日志进行操作分析,计算转化率,设计操作策略。
- 一周前情况下,一周前产生的数据将不再被触及。除了支持偶尔的历史指标查看外,还需要在审计场景中存储所有日志。
一个数据,多处使用,既要满足业务需求,又要关注成本。
定制业务分析
云上日志设施面对的客户群呈现多样化,自定义的业务需求举例如下:
- 电子商务:计算7天留存率,业务访问 SQL 审计日志对用户信息脱敏等。
- 在线教育:多平台终端(android、ios、PC)埋点数据规则,课堂生命周期内异常诊断等。
- 游戏:根据游戏数据分发存储,全文搜索支持工单调查等。
阿里云 SLS 是云原生观测分析平台Log/Metric/Trace等数据提供大规模、低成本、实时平台服务,一站式数据采集、处理、分析、报警可视化和交付功能。我们将以业务为目标的数据处理总结为两种需求:
- ETL:预处理非结构化日志,为日志信息添加业务字段分发添加到日志信息中。
- 分析:查询和查询全局数据表 SQL 支持布尔搜索分析,window、aggregate 操作等。
SLS 典型的分析方案
对于 ETL、除了交互式分析,分析这两种计算任务还需要常驻操作模式来处理结果落盘。
根据不同的业务需求,总结了几种常见的业务需求 SLS 数据分析方案。
数仓 "T 1"
对于结果实时不敏感的业务,采用数仓方案较多:
- 数据通过 SLS 实时入库,集中存储。
- 全托管数据投递 MaxCompute。
- 小时或天级的计算任务,生成下游表,生成业务报表等结果。
流计算
以 Flink、Spark Streaming(continuous mode)、Kafka Streams 以数据处理语义为代表的实时计算系统(exactly-once)、修正计算结果的能力很强。将使用该方案 SLS 百 ms 秒级端到端延迟的 pub/sub 能力:
- 实时推送数据 SLS 日志库。
- 启动多个流量计算任务 shard 实时消费数据。
- 根据算子组合的情况计算流计算任务(stateless、statefull、groupby 等)切割多个拓扑执行可能涉及数据 shuffle、watermark、state store 等机制。
该方案在算子丰富度、实时能力、性能等方面表现全面,是一把牛刀,比如电商实时大屏幕场景。
若抱着挑刺的眼光看:
- 计算引擎层平衡,但缺乏存储层优化。例如:一个 logstore 上运行 10 无论实际需要纳入计算范围的数据是多少,个流计算操作最终都需要 10 从业务角度度来看,所有数据流量的订阅都有网络和计算资源的浪费。
- 对于日志用户来说,在参数配置、性能调优、问题 Debug 复杂性(复杂性往往是通用和强大的另一面)。在复杂的场景中,DevOps-er 了解业务需求后,需要设置高级参数,选择好 state store 等。
- 计算集群部署方法,特别是对于自建集群和稀疏数据的应用,其成本有影响,如 JobManager/TaskManager 需要摊销等角色资源。
做流式消费的自建程序
还是围绕 SLS 的 pub/sub 能力,以 SLS SDK 方式调用 PullData API,例如:
- 通过 Logstash/Flume 加载等开源软件 SLS source connector。
- 通过函数计算(SLS 提供 FC 好处是触发器) Serverless 的 runtime,极端弹性计费。
- 通过 SLS 的 consumer group library 自动负载平衡处理数据,failover。
以上适用于行处理场景,适用表面需要注意:
- 在大多数情况下,该方案不涉及全局计算(窗口、聚集),即使可以实现。
- 自建程序和开源软件需要操作和维护人力和固定机器的成本。
查询和分析自建程序
在 SLS 在流式存储中,开启了索引分析功能,带来了全文索引、列式下推、SQL 加持计算能力。
该方案调用 SLS GetLogs API,常驻程序部署,定时触发器设置,周期调度任务执行:
- 调用 API 读取 SLS 索引和计算数据。
- 读取计算结果并写入目标进行存储。
除操作和维护程序外,用户还需要考虑以下要求:
- SQL 由于计算量大,运行可能会超时,失败时需要调度层的重试支持。
- 延迟时报警支持。
- 调度元信息(schedule_time 等)持久化。
- web console 管理需求。
- 如何将 SQL 计算结果 exactly-once 入库。
本文后续重点介绍 Scheduled SQL,本质上是对该方案的服务,对上述问题有更全面的考虑。
SLS 告警
是的,你没看错。少数用户用户 SLS 报警曲线救国,图为全托管、免运维。
SLS 报警功能支持定时策略的设置,实施多个策略 SQL 获取结果并将结果发送到内置 logstore(internal-alert-history)或自定义网关/webhook。
需要注意的是,报警的主要设计场景是根据触发策略和值班表向接收者传达事件的小计算结果。对于严格的业务,不推荐这种做法(可以注意 Scheduled SQL 迁移功能):
- 报警结果可能会出现数据截断(1) MB 内)、 exactly-once 等问题。
- 告警 1.0 是串行调度,一次计算延迟后,多次执行实例 SQL 时间窗口会出现空洞。
SLS 原始数据处理方案
用图片描述 SLS 原始数据处理功能如下:

stream 模型
例如通过 Flink、自建消费组程序 SLS 基于数据分析 stream 模型。这是 SLS 最基本的存储形式(也称为) LogHub),可以理解为 append-only 的 log 结构,通过 多个 shard 组合实现 IO 以及存储水平的扩展。
LogHub 与开源软件 Kafka 功能形态相似,SLS 底层是共享分布式存储(盘古),避免了 Kafka 在机器磁盘空间 re-balance、机器更换和存储规模的一些缺陷。
stream 机器数据场景下存储模型有多种优点:
- 写入模型简单,不需要 commit 机制,自然支持流式写入,客户端(移动设备,Agent)友好。
- append-only 为满足业务高并发、高吞吐的需要,保证了写入吞吐的设计上限。
- FIFO 的 changelog 该模式满足了大多数日志和指标数据的生成和使用场景。
对流数据 ETL 场景,SLS 支持数据处理功能,可实现数量支付和全托管的银行处理需求。本文不介绍,可参考SLS 数据处理的设计与实践。
table 模型
当 stream 写入数据后,对 shard 内的数据,可以同时构建一份包括倒排、列存、bitmap 索引数据等信息。shard 内 stream 数据相当于文本,索引今天有两种形式:
- Logstore (with index):表结构适用于日志模型,条数据由多组 key-value pair 组成。
- Metricstore:对于指标类型数据有针对性优化,有序排列存储支持快速指标计算,高压缩率低存储成本。
例如 Logstore,在计算时称为 append-only Table 模型。在 SLS 场景下有以下优势:
- 计算效率高,时间(一级索引)过滤、计算下推都可以直接利用 index 进行,节省网络、计算的性能开销与计算成本。当然,index 会有构建费用,SLS 的一份 index 数据可以服务于多个业务场景(告警、仪表盘、全文搜索、监控)来摊销成本。
- OLAP 解决确定性问题,按照条件过滤取到数据后,直接进行计算即可,不需要考虑流计算中 watermark、trigger 与 window 配合、state store 数据膨胀(特定场景)等复杂问题。
Scheduled SQL 让 SQL 可调度
SLS 的每一次 SQL 计算针对预定的一片数据做处理,因此,对全部时间区间(从现在开始一直到未来)数据的 SQL 分析依赖于上层调度,也就是将要介绍的新功能 Scheduled SQL,它支持标准SQL、SLS 查询和分析语句,按照调度规则周期性执行,并将运行结果写入到目标库中。可用于以下场景:
- 定时分析数据:根据业务需求设置分析语句,定时执行,并将分析结果存储到目标库中。
- 全局聚合:对全量、细粒度的数据进行聚合存储,汇总为存储大小、精度适合的数据,相当于一定程度的有损压缩数据。例如按照秒级别对 36 亿条数据进行聚合存储,存储结果为 3150 万条数据,存储大小为全量数据的0.875%。
- 投影与过滤:对原始数据的字段进行筛选,按照一定条件过滤数据并存储到目标Logstore中。该功能还可以通过数据加工实现,数据加工的DSL语法比SQL语法具备更强的ETL表达能力,更多信息请参见加工原理。
Scheduled SQL 相比于自建程序调用 SLS API 而言,有以下优势:
- SQL 运行 timeout 提升至 600 秒,单次最大处理百亿级数据。
- 计算资源池可选:免费(project 级 15 并发)、付费(弹性扩展,参考SQL 独享实例)。
- 最小 1 分钟周期执行,支持常驻或固定时间区间内调度运行。
- 支持灵活的查询时间窗口参数配置,满足多样化需求。
- exactly-once 写入目标库。
- 完善的作业实例查看、重试支持(控制台、API)。
- 全托管运行,自动处理多种异常,调度不收费。
- 实例执行失败集成 SLS 告警通知。
Scheduled SQL 功能介绍
工作机制
Scheduled SQL 涉及以下几个重要概念:
- 作业:一个 Scheduled SQL 任务对应一个作业,包括调度策略、计算规则等信息。
- 实例:一个 Scheduled SQL 作业按照调度配置按时生成执行实例。每一个实例对原始数据进行 SQL 计算并将计算结果写入目标库。实例ID 是其唯一标识。
- 创建时间:实例的创建时间。一般是按照您配置的调度规则生成,在补运行或追赶延迟时会立即生成实例。
- 调度时间:由调度规则生成,不会受到上一个实例执行超时、延迟、补运行等情况的影响。大部分场景下,连续生成的实例的调度时间是连续的,可处理完整的数据集。
流计算里有大量篇幅用于处理数据计算的一致性、完整性问题,Scheduled SQL 则是一种以 small-batch 模拟常驻计算的方案,针对这两个问题的设计是:
- 计算一致性
-
- SQL 每次执行会对应到确定的时间窗口,由此得到确定数据集再调度 SQL 计算。Scheduled SQL 实例运行时,SQL 查询的时间窗口是基于调度时间渲染得到,左闭右开格式,与实例的创建时间、执行时间无关。例如调度时间为
2021/01/01 10:00:00,SQL时间窗口的表达式为[@m - 10m, @m),则实际的SQL时间窗口为[2021/01/01 09:50:00, 2021/01/01 10:00:00)。 - SQL 计算的结果在插入目标时,需要考虑数据重复可能带来的业务影响。对于 append 模式写,例如 Scheduled SQL 结果写 Logstore,写入客户端与 SLS 服务端实现了 exactly-once 协议。对于 overwrite 模式写,更容易做到原子性,未来会规划 Scheduled SQL 写数据库的支持。
- SQL 每次执行会对应到确定的时间窗口,由此得到确定数据集再调度 SQL 计算。Scheduled SQL 实例运行时,SQL 查询的时间窗口是基于调度时间渲染得到,左闭右开格式,与实例的创建时间、执行时间无关。例如调度时间为
- 数据的完整性
-
- 作业上设置延迟执行参数从业务上给与指导,在实例的调度时间点上,往后延迟 N 秒才真正开始触发实例运行,而实例查询的时间范围不受延迟参数影响。例如设置调度间隔为每小时、延迟执行为30秒,那么一天生成24个实例,其中某实例的调度时间为
2021/4/6 12:00:00,执行时间为2021/4/6 12:00:30。这个设计在大部分场景下可以解决数据迟到问题,但对于写 logstore 存储(数据写入后将无法更新)来说,完全避免延迟问题是难以实现的。极端情况下,数据迟到问题可通过事后的实例重试来补结果。 - 将 SQL 查询的时间窗口按分钟对齐(例如整分钟),以保证在 SLS 索引模型优化(batch log-group 组成倒排 doc)时依然能保证绝对的计算准确。
- 作业上设置延迟执行参数从业务上给与指导,在实例的调度时间点上,往后延迟 N 秒才真正开始触发实例运行,而实例查询的时间范围不受延迟参数影响。例如设置调度间隔为每小时、延迟执行为30秒,那么一天生成24个实例,其中某实例的调度时间为
调度场景
Scheduled SQL 作业依次调度多个实例执行,无论是正常被调度还是被动异常实例重试的情况,同时只有一个实例处于运行中,不存在多个实例并发执行的情况。
在 SLS 数据场景下,主要的几种调度场景如下:
- 场景一:实例延迟执行
无论实例是否延迟执行,实例的调度时间都是根据调度规则预先生成的。虽然前面的实例发生延迟时,可能导致后面的实例也延迟执行,但通过追赶执行进度,可逐渐减少延迟,直到恢复准时运行。
- 场景二:从某个历史时间点开始执行Scheduled SQL作业
在当前时间点创建Scheduled SQL作业后,按照调度规则对历史数据进行处理,从调度的开始时间创建补运行的实例,补运行的实例依次执行直到追上数据处理进度后,再按照预定计划执行新实例。
- 场景三:固定时间内执行Scheduled SQL作业
如果需要对指定时间段的日志做调度,则可设置调度的时间范围。如果设置了调度的结束时间,则最后一个实例(调度时间小于调度结束时间)执行完成后,不再产生新的实例。
- 场景四:修改调度配置对生成实例的影响
修改调度配置后,下一个实例按照新配置生成。一般建议同步修改SQL时间窗口、调度频率等配置,使得实例之间的SQL时间范围可以连续。
- 场景五:重试失败的实例
正常情况下,一个Scheduled SQL作业按照调度时间的递增顺序生成执行实例。如果实例执行失败(例如权限不足、源库不存在、目标库不存在、SQL语法不合法),系统支持自动重试,当重试次数超过您配置的最大重试次数或重试时间超过您配置的最大运行时间时,重试结束,该实例状态被置为失败,然后系统继续执行下一个实例。
您可以对失败的实例设置告警通知并进行手动重试。您可以对最近7天内创建的实例进行查看、重试操作。调度执行完成后,系统会根据实际执行情况变更实例状态为成功或失败。
Scheduled SQL 在访问日志上的应用
场景需求
在阿里云上,SLB/OSS 的被用到很多的基础计算、存储服务。在使用过程中如果要得到细粒度可观察性,都绕不过访问日志,在深度使用后您可能会有体感:
- 访问日志与 request 数一比一关系,数据量很大,造成存储成本增加并拖慢计算。
- 访问日志有时效性,近 15 天日志需要交互式查询分析支持,历史数据需要具备降精度的指标查询能力。
- 访问日志有留存的需求,需要长期存储以备审计。
整体方案
以 SLB 七层访问日志为例,这里介绍一种实践:
- 基于 Scheduled SQL 功能,将历史原文数据压缩为低精度数据,支持长期的索引存储并大大提升分析效率。
- 根据业务需要,原文数据支持全局搜索和无损的 SQL 分析,可以设置存储周期为 15天。
- 历史数据原文投递到 OSS,支持极低成本存储,低频的审计捞数据操作也是方便的。
整体方案图如下:
OSS投递操作步骤参考将日志服务数据投递到OSS。
Scheduled SQL 配置使用增强型资源池,默认 STS 角色授权,最终计算结果写同区域 Logstore:
使用Scheduled SQL时,建议根据业务情况,同时兼顾数据实时性和准确性。
- 考虑数据上传日志服务存在延迟情况,您可以结合数据采集延迟以及业务能够容忍的最大结果可见延迟,设置执行延迟和SQL时间窗口(结束时间往前一点),避免实例执行时SQL时间窗口内的数据未全部到达。
- 建议SQL时间窗口按分钟对齐(例如整分钟、整小时),以保证上传局部乱序数据时的数据准确度。
在这里每分钟调度一次 SQL 计算最近一分钟窗口的数据,并设置延迟执行(如果对于实时性要求不高,建议这个值设置大一些):
Scheduled SQL 写出到目标 Logstore 数据的结果如下图,其中 tag 字段是系统默认添加的信息,用于数据的搠源。
Scheduled SQL 调度生成的实例信息在任务管理页面可以查看,对于失败的任务可以做重试。
方案效果
- 功能体验上:
- 热、温数据存储、分析,支持交互式查询、分析的能力,保留了灵活性。
- 冷数据分析,支持分钟粒度的自定义指标查询(例如本文是 host、method、status 维度统计),可以快速实现问题分析,同样查询范围延迟降低两个数量级。
- 冷数据存储,以压缩格式投递到 OSS 存储,保留了审计能力。
- 存储成本上:在永久存储的背景下,存储量降低到之前的 1/1000,OSS 上的压缩格式存储且做到极低的单价。
原文链接 本文为阿里云原创内容,未经允许不得转载。