SLS机器学习最佳实战:时序异常检测和报警-阿里云开发者社区

开发者社区> 阿里云存储服务> 正文
登录阅读全文

SLS机器学习最佳实战:时序异常检测和报警

简介: 日志服务团队具备强大的日志采集功能,针对建立索引的日志进行快速的查询和分析能力。基于此,我们团队将时序数据分析功能整合到日志服务中去,结合更加强大的告警功能,帮助用户根据自己的业务需求,快速的构建报警规则,提高效率。

文章系列链接



背景

针对实时采集的日志数据,如何从实时的日志中监控服务的稳定性;如何及时的将服务的异常通知到相关人员;如何根据一段时间内的时序日志消除抖动,更好的提高企业运维人员的效率。。。等等这些问题,都需要建立在如何快速且尽可能准确的发现异常。

日志服务团队具备强大的日志采集功能,针对建立索引的日志进行快速的查询和分析能力。基于此,我们团队将时序数据分析功能整合到日志服务中去,结合更加强大的告警功能,帮助用户根据自己的业务需求,快速的构建报警规则,提高效率。

指标说明

  • 实验对象

    • 以SLS杭州Region的oplog为例
  • 针对集群稳定性的关注指标

    • 最近1小时内请求状态成功的平均延时
    • 最近1小时内请求异常数量

异常检测实际案例分析

一个平稳态例子

最近1小时内请求状态成功的平均延迟

* and region: hangzhou | 
select  
    date_trunc('minute', __time__ - __time__ % 60) as t, 
    count_if(Status=200) as succ, 
    count_if(Status>200) as err, 
    avg(Latency) as Latency  
from log GROUP BY t order by t limit 10000

image.png

上图中的蓝色折线表示:每分钟平均请求成功的量;绿色折线表示:每分钟平均请求失败的量;红色的折线表示:每分钟平均请求的延迟。通过上图中的曲线可知,针对succ或这err这两个指标进行判断,却不能得到很好的判断,因此,将上述指标综合考虑一下,得到一个异常占比指标。

* and region: hangzhou | 
select 
    time, 
    err*1.0 / (succ + err) as ratio 
from ( 
    select 
        __time__ - __time__ % 30 as time, 
        count_if(Status > 200) as err, 
        count_if(Status=200) as succ 
    from log GROUP BY time ) limit 2000

image.png

上图中表示每分钟$\frac{err}{succ + err}$的统计结果图,可以真实上述曲线进行时序建模,自动发现异常。具体的操作如下:

* and region: hangzhou | 
select 
    ts_predicate_arma(time, ratio, 5, 1, 1, 1, 'avg') 
from ( 
    select 
        time, 
        err*1.0 / (succ + err) as ratio 
    from ( 
        select 
            __time__ - __time__ % 30 as time, 
            count_if(Status > 200) as err, 
            count_if(Status=200) as succ 
        from log GROUP BY time order by time) ) limit 2000

image.png

上图表示使用ts_predict_arma函数,对时序ratio 曲线建立时序统计模型 arma(p=5,q=1) ,并利用SLS(日志服务)中内置的异常检测策略,得到的检测结果。其中蓝色线表示实际的 ratio 时序状态,红色曲线表示针对历史数据学习得到的有效的预测曲线,浅绿色的区域表示有效的预测置信区间,红色的空心点表示发生异常的时间点。

一个抖动较大例子

针对杭州弹内集群该统计指标的状态

* and region: hangzhou_corp | 
select 
    time, 
    err*1.0 / (succ + err) as ratio 
from ( 
    select 
        __time__ - __time__ % 30 as time, 
        count_if(Status > 200) as err, 
        count_if(Status=200) as succ 
    from log GROUP BY time order by time ) limit 2000

image.png

上图中 $\frac{err}{err + succ}$ 的抖动较为异常,分析下日志,大部分是因为请求时产生了400或者401的错误(用去请求的参数不对、或者是权限异常、或是心跳部分异常)。这种折线,可以使用时序统计模型么?来来来,具体的操作如下:

* and region: hangzhou_corp | 
select 
    ts_predicate_arma(time, ratio, 5, 1, 1, 1, 'avg') 
from ( 
    select 
        time, 
        err*1.0 / (succ + err) as ratio 
    from ( 
        select 
            __time__ - __time__ % 30 as time, 
            count_if(Status > 200) as err, 
            count_if(Status=200) as succ 
        from log GROUP BY time )) limit 2000

image.png

上图中的结果是使用 ts_predict_arma 函数,使用 arma(p=5,q=1) 的参数进行学习,得到上图的曲线,其中蓝色折线表示:原始的观测序列,红色折线表示:时序模型的预测曲线,绿色区域表示可靠的致信区间。

估计有的同学会有如下问题?

  1. 为何红色折线与蓝色折线抖动的幅度差距有点大呢?
  2. 为何蓝色折线超出了绿色区域,但是却没有被标记为异常点呢?

疑问说明?️?️?️

  1. 预测和实际之间的差异是为何???
    围观过SLS机器学习介绍(01):时序统计建模SLS机器学习介绍(03):时序异常检测建模的同学估计就有答案了哈!!

内部在进行时序建模之前,预先对原始数据进行一个平滑操作,该操作是对调用方是透明的,具体的结果如下:

* and region: hangzhou_corp | 
select 
    ts_smooth_fir(time, ratio, 'rectangle', 5, 1, 'avg') 
from ( 
    select 
        time, 
        err*1.0 / (succ + err) as ratio 
    from ( 
        select 
            __time__ - __time__ % 30 as time, 
            count_if(Status > 200) as err, 
            count_if(Status=200) as succ 
        from log GROUP BY time order by time )) limit 2000

image.png
这时您再看下是不是就相似了很多了。

  1. 实际值超出了置信区间,却没有标记为异常点,却是为何???
    日志服务(SLS)内部采取多种策略对异常点进行检测,尽可能的准确率、降低误报率。算法的具体原理原理说明型文章SLS机器学习介绍(03):时序异常检测建模。对此感兴趣的同学可以 钉钉:悟冥

设置报警实例分析

时序函数有何不同之处??

  • 标准的SQL函数,需要针对指定的字段进行查询和输出,一般格式如下:

    select a, b, c from table;
    ===>
    a | b | c
    ---------
    1 | 2 | 4
    3 | 2 | 1
    1 | 3 | 2
    2 | 6 | 4
  • SLS针对时序函数提供了内置展开操作(这里需要重点感谢下 @马云雷 大神!),得到的结果如下:

    select ts_predict_arma() from table;
    ===>
    unixtime | src | pred | upper | lower | prob
    ---------------------------------------------
    1.0      | 1.0 | 1.0  | 1.2   | 0.75  | 0.0  
    2.0      | 1.0 | 1.0  | 1.2   | 0.75  | 0.0  

说明: 针对时序函数,我们提供了一套原生接口,可以按照一定的格式返回一个元素,使用者需要针对需要自定展开操作,由于单节点放回容量有限,若用户的请求返回结果过大,超过了单节点容量限制,则不能成功返回。

使用异常检测函数进行报警

  • 使用原生函数获取结果
  * and not Status:200 and region: hangzhou | 
select 
    ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key 
from  ( 
    select 
        __time__ - __time__ % 30 as time, 
        count_if(Latency > 50000000) + 1 as Latency 
    from log GROUP BY time)

image.png
上述结果就是一个二维数组的结构,需要手动进行展开操作

  • 手动展开操作
  * and not Status:200 and region: hangzhou | 
select 
        key1[1] as stamp, 
        key1[2] as src, 
        key1[3] as pred, 
        key1[4] as up, 
        key1[5] as low, 
        key1[6] as prob 
from  (
    select 
        ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key 
    from  ( 
        select 
            __time__ - __time__ % 30 as time, 
            count_if(Latency > 50000000) + 1 as Latency 
        from log GROUP BY time)), unnest(key) as t(key1)

image.png

  • 我们不关心预测,只关心最近2分钟的异常检测的结果

    • 去掉预测的数据
    • 找到最近2分钟的状态
  * and not Status:200 and region: hangzhou | 
  select 
      stamp, src, pred, up, low, prob 
  from  ( 
      select 
          key1[1] as stamp, 
          key1[2] as src, 
          key1[3] as pred, 
          key1[4] as up, 
          key1[5] as low, 
          key1[6] as prob 
      from  (
          select 
              ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key 
          from  ( 
              select 
                  __time__ - __time__ % 30 as time, 
                  count_if(Latency > 50000000) + 1 as Latency 
              from log GROUP BY time)), unnest(key) as t(key1) ) 
          where is_nan(src) = false order by stamp DESC limit 4

image.png

  • 确定最近2分钟内的是否有异常
  * and not Status:200 and region: hangzhou | 
  select 
      sum(prob) as sumProb 
  from  ( 
      select 
          stamp, prob 
      from ( 
          select 
              key1[1] as stamp, 
              key1[2] as src, 
              key1[3] as pred, 
              key1[4] as up, 
              key1[5] as low, 
              key1[6] as prob 
          from (
              select 
                  ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key 
              from  ( 
                  select 
                      __time__ - __time__ % 30 as time, 
                      count_if(Latency > 50000000) + 1 as Latency 
                  from log GROUP BY time)), unnest(key) as t(key1) ) 
                  where is_nan(src) = false order by stamp DESC limit 4)

最终将上述查询作为一个告警的SQL,在日志服务的Web端,可以使用如下的操作。
image.png

具体的配置如下:
image.png

PS: 上述截图还是旧版本的告警设置,新的告警系统功能强大,敬请期待哈!


Tips

  • 一般情情况下,我就单独针对告警设置一个仪表盘,将时序的告警规则嵌入在页面中,针对现有的报警一目了然,我的具体截图如下:
    image.png

硬广时间

日志进阶

阿里云日志服务针对日志提供了完整的解决方案,以下相关功能是日志进阶的必备良药:

  1. 机器学习语法与函数: https://help.aliyun.com/document_detail/93024.html
  2. 日志上下文查询:https://help.aliyun.com/document_detail/48148.html
  3. 快速查询:https://help.aliyun.com/document_detail/88985.html
  4. 实时分析:https://help.aliyun.com/document_detail/53608.html
  5. 快速分析:https://help.aliyun.com/document_detail/66275.html
  6. 基于日志设置告警:https://help.aliyun.com/document_detail/48162.html
  7. 配置大盘:https://help.aliyun.com/document_detail/69313.html

更多日志进阶内容可以参考:日志服务学习路径


联系我们

纠错或者帮助文档以及最佳实践贡献,请联系:悟冥
问题咨询请加钉钉群:

001

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

阿里云存储基于飞天盘古2.0分布式存储系统,产品多种多样,充分满足用户数据存储和迁移上云需求。

官方博客
存储产品
客户案例