云原生日志数据分析上手指南
背景信息
本指南主要涉及阿里云云产品:
- 日志服务(SLS, https://www.aliyun.com/product/sls)
- 对象存储服务(OSS, https://www.aliyun.com/product/oss)
- Data Lake Analytics(DLA, https://www.aliyun.com/product/datalakeanalytics)
上述三款云产品均属于Serverless化的云原生服务型产品,无维护成本、高可用,简单配置即可在云上搭建起企业级的日志数据分析链路和应用。
日志作为一种特殊的数据,对处理历史数据、诊断问题以及了解系统活动等有着非常重要的作用。对数据分析人员、开发人员或者运维人员而言,日志都是其工作过程中必不可缺的数据来源。
通常情况下,为节约成本,我们会将日志设定一定的保存时间,只分析该时间段内的日志,此类日志称之为“热”日志。这种做法,短期内可以满足使用需求,但从长期来看,大量的历史日志被搁置,无法发挥其价值。
对于许多企业而言,对日志分析的需求特征通常为低时效和低频率。并且在一个企业中,为偶发性的日志分析去构建一套完整的日志分析系统,无论在经济成本还是运维成本上都是不划算的。如何在降低存储成本的同时满足大批量日志的分析需求,是摆在企业面前的一道难题。
实施方案
从用户角度,这套云原生日志数据分析方案非常轻量化。利用日志服务 LOG(Log Service,简称LOG/原SLS)来投递日志,阿里云对象存储服务(Object Storage Service,简称OSS)来存储日志,Data Lake Analytics(DLA)来分析日志。该方案有以下三个优势:
- LOG是针对实时数据一站式服务,在阿里集团经历大量大数据场景锤炼而成。提供日志类数据采集、智能查询分析、消费与投递等功能,全面提升海量日志处理/分析能力。LOG强大的日志投递能力,能够从源头对接各种类型的日志格式,并且稳定地将日志投递到指定的位置。
- OSS极低廉的存储成本,能够让您的日志文件存储任意长的时间。
- DLA强大的分析能力,Serverless的架构,按扫描量收费。DLA可以对投递到OSS上的日志按年、按月、按日进行多维度的分区,提高日志的命中率,降低扫描量,从而以极低的成本、极高的性能来完成大数据量历史日志分析。分析完的数据,还可以利用DLA的云上数据源打通能力,回流到多种云数据系统(RDS, OSS, Table Store, AnalyticDB,PolarDB等)中。
前提条件
在开始实施步骤之前,需要先完成以下准备工作。
- 参考文档LOG快速入门,开通日志服务、创建项目、创建日志库。
- 开通OSS服务、在日志服务项目所在的地域创建存储空间。
- 开通并初始化DLA服务。
实施步骤
步骤一:通过Logtail采集ECS日志
根据本示例中的日志文件特点,Logtail配置如下所示。本截图示例中是以正则表达式的方式进行采集和字段提取为例,当然,日志服务支持多种采集和提取方式,本文只是示例其中一种。
步骤二:投递日志到OSS
详细操作请参见投递日志到OSS,并且日志服务投递OSS使用Parquet存储的相关配置。
在OSS投递功能页面,配置各项参数,关于各项参数配置说明:https://help.aliyun.com/document_detail/29002.html
参数说明:
- OSS Bucket和OSS Prefix设置日志投递到OSS的哪个目录。
修改分区格式,将分区列的名字填入到目录中:
- 格式为分区列名=分区列值。
如图所示,修改分区格式默认值,即一级分区列的列名为year,列值为%Y; 二级分区列的列名为month,列值为%m;三级分区列的列名为day,列值为%d;如果分区粒度想到小时(每小时产生的数据量较大时),可以设置四级分区,列名为hour,列值为%H。 - 如果不使用分区列名=分区列值的形式也可以,即保留日志服务保留的默认分区格式:%Y/%m/%d/%H/%M,但是这里是到分钟级别的分区,粒度通常太小,可以改成%Y/%m/%d/%H%M,到天级别分区。
- 格式为分区列名=分区列值。
- 存储格式设置为parquet。
- 压缩方式设置为snappy,使用snappy算法对数据做压缩,可以减少OSS Bucket存储空间使用量。
日志数据投递到OSS中以后,就可以通过DLA读取并分析OSS中的日志。
步骤三:在DLA中创建OSS连接
登录DLA控制台,登录DMS,在DLA中创建一个到OSS的连接。语法如下:
_
CREATE SCHEMA oss_log_schema with DBPROPERTIES(
catalog='oss',
location = 'oss://myappbucket/sls_parquet/'
);
location:日志文件所在的OSS Bucket的目录,需以/
结尾表示目录。myappbucket是OSS Bucket名字。
步骤四:在DLA中创建指向OSS日志文件的外表(分区表)
如果在步骤二中,SLS投递到OSS分区配置的分区为year、month、day,则建表示例如下:
CREATE EXTERNAL TABLE sls_parquet (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS PARQUET
LOCATION 'oss://myappbucket/sls_parquet/';
注意:
- 新建表中的列名要和生成的parquet文件中设置的列名一致。
- 分区列的名称、顺序需要和步骤二:投递日志到OSS中的分区列一致。更多创建分区表信息,请参见通过DLA创建OSS分区表。
- LOCATION中,根据示例,OSS上文件路径示例应该类似:oss://myappbucket/sls_parquet/year=2019/month=01/day=01/,或者oss://myappbucket/sls_parquet/2019/01/01/,LOCATION应该指定到实际分区开始目录的父目录一层,即oss://myappbucket/sls_parquet/。
步骤五:使用命令添加、维护分区信息
步骤四外表创建成功后,执行MSCK REPAIR TABLE
将分区信息同步到DLA中。
MSCK REPAIR TABLE sls_parquet;
注意:
- MSCK命令只能识别符合DLA分区列命名规则的目录,即分区列的目录名为分区列名=分区列值,例如:oss://myappbucket/sls_parquet/year=2019/month=01/day=01/;
- MSCK命令可以一次性识别当前OSS上实际存在的符合分区命名规则的所有分区,如果后面OSS上有新增分区,需要再次执行上述MSCK命令;
- 可以通过SHOW PARTITIONS sls_parquet命令查看当前实际DLA能看到的分区情况,如果初次没有执行MSCK命令,SHOW PARTITIONS sls_parquet应该返回空,看不到任何分区,执行MSCK完后,再执行SHOW PARTITIONS sls_parquet应该返回当前OSS上实际符合分区命名规则的所有分区。
如果之前配置投递到OSS上的数据目录如:oss://myappbucket/sls_parquet/2019/01/01/
则执行:
ALTER TABLE sls_parquet ADD
PARTITION (year='2019', month='01', day='01')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/01/';
该命令只添加了一个分区:2019/01/01/
也可以一次添加多个分区:
ALTER TABLE sls_parquet ADD
PARTITION (year='2019', month='01', day='01')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/01/',
PARTITION (year='2019', month='01', day='02')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/02/',
PARTITION (year='2019', month='01', day='03')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/03/',
PARTITION (year='2019', month='01', day='04')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/04/';
该命令添加了四个分区。
注意:
- 可以通过SHOW PARTITIONS sls_parquet命令查看当前实际DLA能看到的分区情况,如果初次没有执行ALTER TABLE ADD PARTITION命令,SHOW PARTITIONS sls_parquet应该返回空,看不到任何分区,执行ALTER TABLE ADD PARTITION完后,再执行SHOW PARTITIONS sls_parquet应该返回实际添加的分区信息。
另外一个类似的例子,如果之前配置投递到OSS上的数据目录如:
oss://myappbucket/sls_parquet/2019-01-01
oss://myappbucket/sls_parquet/2019-01-02
oss://myappbucket/sls_parquet/2019-01-03
oss://myappbucket/sls_parquet/2019-01-04
则对应的DLA建表语句:
CREATE EXTERNAL TABLE sls_parquet (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (day STRING)
STORED AS PARQUET
LOCATION 'oss://myappbucket/sls_parquet/';
则执行如下语句添加分区:
ALTER TABLE sls_parquet ADD
PARTITION (day='2019-01-01') LOCATION 'oss://myappbucket/sls_parquet/2019-01-01/',
PARTITION (day='2019-01-02') LOCATION 'oss://myappbucket/sls_parquet/2019-01-02/',
PARTITION (day='2019-01-03') LOCATION 'oss://myappbucket/sls_parquet/2019-01-03/',
PARTITION (day='2019-01-04') LOCATION 'oss://myappbucket/sls_parquet/2019-01-04/';
步骤六:查询分区表数据
分区信息同步完成后,使用SELECT
语句对日志进行查询分析。例如,对于本示例中,查询sls_parquet表得到某一天查询最慢的5条语句。
SELECT original_sql, total_time
FROM sls_parquet
WHERE client != '' AND year='2019' AND month = '01' AND day = '01'
ORDER BY total_time DESC
LIMIT 5;
后续操作
上述示例中,日志数据投递OSS的存储格式为Parquet格式,除了Parquet格式,LOG还可以将投递文件的格式设置为JSON和CSV。详细的配置,请参见JSON格式和CSV格式。
JSON格式
- 当投递文件的格式设置为JSON且无压缩时,建表语句为:
CREATE EXTERNAL TABLE sls_json (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS JSON
LOCATION 'oss://myappbucket/sls_json/';
- 当投递文件的格式设置为JSON且使用标准Snappy压缩时,建表语句为:
CREATE EXTERNAL TABLE sls_json_snappy (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS JSON
LOCATION 'oss://myappbucket/sls_json_snappy/'
TBLPROPERTIES(
'text.compression'='snappy',
'io.compression.snappy.native'='true'
);
注意:
- 必须指定TBLPROPERTIES( 'text.compression'='snappy', 'io.compression.snappy.native'='true')的属性。
CSV格式
- 当投递文件的格式设置为CSV,不包含header,使用标准Snappy压缩时,建表语句为:
CREATE EXTERNAL TABLE sls_csv_snappy (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES(
'separatorChar'=',',
'quoteChar'='"',
'escapeChar'='\\'
)
STORED AS TEXTFILE
LOCATION 'oss://myappbucket/sls_csv_snappy/'
TBLPROPERTIES(
'text.compression'='snappy',
'io.compression.snappy.native'='true',
'skip.header.line.count'='0'
);
CREATE EXTERNAL TABLE sls_csv (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES(
'separatorChar'=',',
'quoteChar'='"',
'escapeChar'='\\'
)
STORED AS TEXTFILE
LOCATION 'oss://myappbucket/sls_csv/'
TBLPROPERTIES(
'skip.header.line.count'='1'
);
关于更多的文件格式对应的建表支持情况,请参考:https://yq.aliyun.com/articles/623246
更多参考
- Data Lake Analytics学习路径:https://help.aliyun.com/learn/learningpath/datalakeanalytics.html
- Data Lake Analytics知乎专栏:https://zhuanlan.zhihu.com/data-lake-analytics
- 阿里云Data Lake Analytics产品专栏:https://yq.aliyun.com/teams/396
- 云栖社区:https://yq.aliyun.com/topic/138
1元10TB的数据分析流量包和流量包优惠活动:https://et.aliyun.com/bdad/datalake