云原生日志数据分析上手指南

云原生日志数据分析上手指南

背景信息

本指南主要涉及阿里云云产品:

上述三款云产品均属于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等)中。

云原生日志数据分析上手指南

前提条件

在开始实施步骤之前,需要先完成以下准备工作。

实施步骤

步骤一:通过Logtail采集ECS日志

详细操作请参见通过Logtail采集ECS日志

根据本示例中的日志文件特点,Logtail配置如下所示。本截图示例中是以正则表达式的方式进行采集和字段提取为例,当然,日志服务支持多种采集和提取方式,本文只是示例其中一种。
云原生日志数据分析上手指南

模式选择完整正则模式,需要提供完整正则表达式。
云原生日志数据分析上手指南

步骤二:投递日志到OSS

详细操作请参见投递日志到OSS,并且日志服务投递OSS使用Parquet存储的相关配置
OSS投递功能页面,配置各项参数,关于各项参数配置说明:https://help.aliyun.com/document_detail/29002.html

云原生日志数据分析上手指南

云原生日志数据分析上手指南

参数说明:

  • OSS BucketOSS 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'
);
  • 云原生日志数据分析上手指南
  • 当投递文件的格式设置为CSV无压缩,且包含header时,建表语句为:
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

更多参考

1元10TB的数据分析流量包和流量包优惠活动:https://et.aliyun.com/bdad/datalake

上一篇:基于webpack4搭建的react项目框架


下一篇:DLA SQL技巧:行、列转换和JSON数据列展开