時間序列異常檢測機制的研究

 ADDOPS團隊籍鑫璞 360雲計算算法

女主宣言運維

本文出自於ADDOPS團隊,該文章的做者籍鑫璞主要負責360 HULK雲平臺運維自動化和智能運維方面的工做。本文提出了一種高效的LVS流量異常檢測算法,幫助ops同事更加精準的判斷業務流量突增突減等非正常狀態。但願該文章能給你們對異常檢測的理解有所啓發,後續會有做者對機器學習落地運維創新的系列文章,敬請期待。機器學習

PS:豐富的一線技術、多元化的表現形式,盡在「HULK一線技術雜談」,點關注哦!ide

前言wordpress

雙十一剛過,阿里還有京東就在瘋狂地show(秀)他們的技術有多牛逼。無可厚非,兩家公司在應對guagngu節的時候都有本身的一套針對不一樣場景的策略。試想一下,假如雙十一那每天貓的主頁訪問不了,那馬爸爸不得損失好多個億。爲了防止這樣的狀況出現,除了瘋狂擴容之外,一套理想的異常檢測機制也是很是很是重要的。學習


異常檢測的場景不少,例如硬件的故障檢測、流量的異常點的檢測等場景。這篇博客咱們針對的是時間序列的異常檢測。時間序列異常的檢測算法有不少,業界比較流行的好比普通的統計學習方法--3σ原則,它利用檢測點偏移量來檢測出異常。好比普通的迴歸方法,用曲線擬合方法來檢測新的節點和擬合曲線的偏離程度,甚至有人講CNN和RNN技術應用到異常點的檢測。雲計算


經過普通的閾值來檢測lvs流量異常的方法效果比較差,本篇文章提出了一種新的檢測算法,下面將重點介紹咱們在實踐過程當中的經驗。spa


1.net

數據分析3d

獲取過去7天的lvs流量的數據,咱們能夠大體將趨勢分爲兩種:


一種是以下圖的具備週期性的數據,這種狀況更多須要考慮週期性給數據帶來的影響。

圖片


而另外一種以下圖的隨機的數據,不具備週期性,這種狀況須要採用和週期性不同的策略來檢測。

圖片


2

檢測機制的研究

因爲曲線就有周期性和非週期性的兩種趨勢,因此咱們的檢測機制須要可以處理兩種方式。


下面咱們將詳細介紹每一個算法。


 

算法

短時間環比(SS)


對於時間序列(是指將同一統計指標的數值按其發生的時間前後順序排列而成的數列)來講,T時刻的數值對於T-1時刻有很強的依賴性。好比流量在8:00不少,在8:01時刻的機率是很大的,可是若是07:01時刻對於8:01時刻影響不是很大。


首先,咱們可使用最近時間窗口(T)內的數據遵循某種趨勢的現象來作文章。好比咱們將T設置爲7,則咱們取檢測值(now_value)和過去7個(記爲i)點進行比較,若是大於閾值咱們將count加1,若是count超過咱們設置的count_num,則認爲該點是異常點。image.png

上面的公式涉及到threshold和count_num兩個參數,threshold如何獲取咱們將在下節進行介紹,而count_num能夠根據的需求進行設置,好比對異常敏感,能夠設置count_num小一些,而若是對異常不敏感,能夠將count_num設置的大一些。


動態閾值


業界關於動態閾值設置的方法有不少,今天介紹一種針對咱們lvs流量異常檢測的閾值設置方法。一般閾值設置方法會參考過去一段時間內的均值、最大值以及最小值,咱們也一樣應用此方法。取過去一段時間(好比T窗口)的平均值、最大值以及最小值,而後取max-avg和avg-min的最小值。之因此取最小值的緣由是讓篩選條件設置的寬鬆一些,讓更多的值經過此條件,減小一些漏報的事件。image.png


長期環比(LS)


上面短時間環比參考的是短時間內的數據,而僅僅有短時間內的數據是不夠的,咱們還須要參考更長時間內數據的整體走勢。


一般使用一條曲線對該趨勢進行擬合來反應曲線的走勢,若是新的數據打破了這種趨勢,使曲線變得不平滑,則該點就出現了異常。曲線擬合的方法有不少,好比迴歸、moving average 等等。在這篇文章中,咱們使用EWMA,即指數權重移動平均方法來擬合曲線。在EWMA種,下一點的平均值是由上一點的平均值,加上當前點的實際值修正而來。對於每個EWMA值,每一個數據的權重是不同的,最近的數據將擁有越高的權重。


有了平均值以後,咱們就可使用3-sigma理論來判斷新的input是否超過了容忍範圍。比較實際的值是否超出了這個範圍就能夠知道是否能夠告警了。

expAverage = pd.stats.moments.ewma(data, com=50) 

stdDev = pd.stats.moments.ewmstd(data, com=50)

if abs(data.values[-1] - expAverage.values[-1]) > 3 * stdDev.values[-1] :

    print "異常"


同比(chain)


不少監控項都具備必定的週期性,其中以一天爲週期的狀況比較常見,好比lvs流量在早上4點最低,而在晚上11點最高。爲了將監控項的週期性考慮進去,咱們選取了某個監控項過去14天的數據。對於某個時刻,將獲得14個點能夠做爲參考值,咱們記爲xi,其中i=1,...,14。


咱們先考慮靜態閾值的方法來判斷input是否異常(突增和突減)。若是input比過去14天同一時刻的最小值乘以一個閾值還小,就會認爲該輸入爲異常點(突減);而若是input 比過去14天同一時刻的最大值乘以一個閾值還大,就會認爲該輸入爲異常點(突增)。

if new_value > max(過去14天同一時刻的值) *  max_threshold:

    print "突增"

if new_value < min(過去14天同一時刻的值) *  min_threshold:

    print "突減"

靜態閾值的方法是根據歷史經驗得出的值,實際中如何給max_threshold和min_threshold是一個須要討論的話題。根據目前動態閾值的經驗規則來講,取平均值是一個比較好的思路。


同比振幅(CA)


同比的方法遇到下圖的現象就不能檢測出異常。好比今天是11.18日,過去14天的歷史曲線必然會比今天的曲線低不少。那麼今天出了一個小故障,曲線下跌了,相對於過去14天的曲線仍然是高不少的。這樣的故障使用方法二就檢測不出來,那麼咱們將如何改進咱們的方法呢?一個直覺的說法是,兩個曲線雖然不同高,可是「長得差很少」。那麼怎麼利用這種「長得差很少」呢?那就是振幅了。


怎麼計算t時刻的振幅呢? 咱們使用x(t) – x(t-1) 再除以 x(t-1)來表示振幅。舉個例子,例如t時刻的流量爲900bit,t-1時刻的是1000bit,那麼能夠計算出掉線人數是10%。若是參考過去14天的數據,咱們會獲得14個振幅值。使用14個振幅的絕對值做爲標準,若是m時刻的振幅[m(t) – m(t-1)]/m(t-1)大於amplitudethreshold而且m時刻的振幅大於0,則咱們認爲該時刻發生突增,而若是m時刻的振幅大於amplitudethreshold而且m時刻的振幅小於0,則認爲該時刻發生突減。image.png


 

算法組合

上面介紹了四種方法,這四種方法裏面,SS和LS是針對非週期性數據的驗證方法,而chain和CA是針對週期性數據的驗證方法。那這四種方法應該如何選擇和使用呢?下面咱們介紹兩種使用方法:


1、根據週期性的不一樣來選擇合適的方法。這種方法須要首先驗證序列是否具備週期性,若是具備週期性則進入左邊分支的檢測方法,若是沒有周期性,則選擇進入右分支的檢測方法。image.png

上面涉及到了如何檢測數據週期的問題,可使用差分的方法來檢測數據是否具備週期性。好比取最近兩天的數據來作差分,若是是週期數據,差分後就能夠消除波動,而後結合方差閾值判斷的判斷方法來肯定數據的週期性。固然,若是數據波動範圍比較大,能夠在差分以前先對數據進行歸一化(好比z-score)。


2、不區分週期性,直接根據「少數服從多數」的方法來去檢測,這種方法比較好理解,在此就不說明了。image.png


3

總結

這篇文章介紹了咱們在lvs異常檢測中使用的方法,也許這些方法還不夠解決全部的場景,你還須要在此基礎上去不斷豐富算法,才能達到比較好的效果。所謂,理論結合實際,具體的問題須要具體的分析,才能將理論應用於實踐。

參考文獻:


1.https://jiroujuan.wordpress.com/2013/10/09/skyline-anomalous-detect-algorithms/ 

2.http://chuansong.me/n/2032667

3.http://blog.csdn.net/g2V13ah/article/details/78474370