天天看點

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           
SLS機器學習最佳實戰:時序異常檢測和報警

上圖中的藍色折線表示:每分鐘平均請求成功的量;綠色折線表示:每分鐘平均請求失敗的量;紅色的折線表示:每分鐘平均請求的延遲。通過上圖中的曲線可知,針對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           
SLS機器學習最佳實戰:時序異常檢測和報警

上圖中表示每分鐘$\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           
SLS機器學習最佳實戰:時序異常檢測和報警

上圖表示使用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           
SLS機器學習最佳實戰:時序異常檢測和報警

上圖中 $\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           
SLS機器學習最佳實戰:時序異常檢測和報警

上圖中的結果是使用 ts_predict_arma 函數,使用 arma(p=5,q=1) 的參數進行學習,得到上圖的曲線,其中藍色折線表示:原始的觀測序列,紅色折線表示:時序模型的預測曲線,綠色區域表示可靠的緻信區間。

估計有的同學會有如下問題?

  1. 為何紅色折線與藍色折線抖動的幅度差距有點大呢?
  2. 為何藍色折線超出了綠色區域,但是卻沒有被标記為異常點呢?

疑問說明?️?️?️

  1. 預測和實際之間的差異是為何???

    圍觀過

    的同學估計就有答案了哈!!

内部在進行時序模組化之前,預先對原始資料進行一個平滑操作,該操作是對調用方是透明的,具體的結果如下:

* 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           
SLS機器學習最佳實戰:時序異常檢測和報警

這時您再看下是不是就相似了很多了。

  1. 實際值超出了置信區間,卻沒有标記為異常點,卻是為何???

    日志服務(SLS)内部采取多種政策對異常點進行檢測,盡可能的準确率、降低誤報率。算法的具體原理原理說明型文章

    。對此感興趣的同學可以 釘釘:悟冥。

設定報警執行個體分析

時序函數有何不同之處??

  • 标準的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)           
SLS機器學習最佳實戰:時序異常檢測和報警

上述結果就是一個二維數組的結構,需要手動進行展開操作

  • 手動展開操作
* 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)           
SLS機器學習最佳實戰:時序異常檢測和報警
  • 我們不關心預測,隻關心最近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           
SLS機器學習最佳實戰:時序異常檢測和報警
  • 确定最近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端,可以使用如下的操作。

SLS機器學習最佳實戰:時序異常檢測和報警

具體的配置如下:

SLS機器學習最佳實戰:時序異常檢測和報警

PS: 上述截圖還是舊版本的告警設定,新的告警系統功能強大,敬請期待哈!

Tips

  • 一般情情況下,我就單獨針對告警設定一個儀表盤,将時序的告警規則嵌入在頁面中,針對現有的報警一目了然,我的具體截圖如下:
    SLS機器學習最佳實戰:時序異常檢測和報警

硬廣時間

日志進階

阿裡雲日志服務針對日志提供了完整的解決方案,以下相關功能是日志進階的必備良藥:

  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

更多日志進階内容可以參考:

日志服務學習路徑

聯系我們

糾錯或者幫助文檔以及最佳實踐貢獻,請聯系:悟冥

問題咨詢請加釘釘群:

SLS機器學習最佳實戰:時序異常檢測和報警