背景算法
任何一個產生環境的IT系統若是要長久下去,必須對其進行監控告警。常見的實現分爲三個部分服務器
在過去,對於第一、2兩點咱們已經積累很是多的文章和工具來談論如何來實施一個「監控系統」。可是對於如何有效檢測異常卻很是缺乏行業經驗的積累。若是要對有效進行量化的話主要是兩個指標:微信
通常來講,誤警率能夠放寬一些。雖然可能會產生狼來了的結果,可是稍微多一兩條告警並不會產生什麼實質的危害。須要卡控得比較嚴格的是漏警的狀況。一旦監控系統漏警了,每每意味着一塊兒責任事故和不小的損失。網絡
曲線分類架構
首先,我不是一個理論工做者,對於自迴歸,方差等術語沒有特別偏好,也沒有通篇使用數學符號表達含義的表達能力。從經驗觀測的角度,我所知的曲線大概分爲下面三類(該分類絕對不是完整分類):併發
而所須要作的監控也通常分爲兩類:運維
性能監控主要關注併發處理的請求數,以及與延時的關係。而可用性監控若是可能的話,首選成功率。若是咱們能夠知道最近一段時間內500的HTTP返回顯著上升了,基本上能夠判定系統出了可用性的問題了。若是對URL作一個分類,而後某一個分類裏500顯著上升那麼這個推斷就更加精確了。這種異常檢測幾乎也無需太複雜的算法了,甚至一個絕對的閾值就能夠了。工具
特別注意的是成功率的曲線不必定非要在一個調用的地方有一個錯誤碼之類的東西,它能夠是來自同一個流程上兩個環節的數據。好比一個成功的業務過程,須要通過a,b,c三個點。咱們若是知道a點的調用量,b點的調用量,也就至關於知道了a點的成功率了。因此大部分時候,咱們是能夠計算出成功率曲線的。性能
可是有的時候,好比由於組織架構的緣由,沒法要求咱們的監控對象必須是某類曲線。假設咱們是一個互聯網的監控服務提供商,好比監控寶。咱們沒法要求咱們的用戶必須提供HTTP的成功率曲線給咱們,用戶只能給咱們HTTP調用的絕對數量。而後僅憑這麼一條調用量的曲線來檢測是否有異常。優化
本文的討論對象是當咱們僅有「調用量曲線」的時候,如何依靠算法檢測出異常。
整體思路
通常來講,所謂的算法來實現所謂的智能,有兩條道路。
對於算法檢測異常出告警這件事情來講,直覺智慧仍是佔了上風的。和高維度的聚類之類的場合不一樣,業務/系統指標的曲線對於異常能夠很是可視化地體現出來。若是咱們以算法爲第一位,直覺放第二位的話,會產生這樣的狀況:
從明哲保身但求無過的角度來看,算法必須可以到達和運維人員肉眼觀察曲線類似的效果,不然沒法向「人」交代。在知足了這個前提下,纔去看那些單曲線沒法感知的,可是綜合多個曲線可能能夠推測出的系統性故障。
如網站的訪問人數之類的業務指標,自己具備週期性的波峯波谷,並且很是容易受到營銷事件的影響。好比下面這個曲線
曲線自身就一直在震盪,在這樣的曲線上如何檢測異常?異常長什麼樣?好比這個
這段區間的數據掉底了(數據爲零),這是很是顯而易見的異常。
這個異常就須要放大了才能觀察出來。在降低的過程當中,忽然陡降了一點,而後又有一個緩慢回升。
這個異常幾乎肉眼沒法分辨。若是不是那個時間點真的出了故障,也很難從曲線上找出來。
上面也是兩個真實的故障。全部上述的故障,人的肉眼能夠發現出來基本上我認爲都是由於人在觀察曲線的時候對於曲線的平滑和不平滑的交界處很是敏感。咱們的算法第一位的需求是要把人肉眼能夠觀察出來的波動,鋸齒,坑都檢測出來。
除了上面的這些狀況以外,還有一類異常,可能就會比較難以捕捉,不如:
上面的圖示一條曲線的七天疊加,也就是根據七天的規律,基本上波形是一致的。可是假如在紅線處,業務曲線實際上應該有一個波峯的時候,是一條水平線過去的,那是該告警呢,仍是不告警呢?若是單純看一根線是徹底沒有平滑不平滑的問題的,由於幾乎是直的。從歷史統計的角度來看,這樣平過去的狀況確定是異常了的,須要告警出來。更極端的的一些狀況,好比這個時間點有營銷資源的投放,案例曲線應該有明顯的擡升,可是實際曲線和往日差很少,那是否是也表明了異常?這樣的一些狀況的處理,我認爲是算法檢測的加分項,本職工做把人肉眼能夠觀察到的波動捕捉到就能夠了,對於第二種狀況就能作到多好就作到多好,實在沒檢測出來,也是能夠理解的,由於確實很難。
statistical process control
咱們搞工程的是沒有本事從新發明什麼算法的。IT系統的業務數據的監控告警,看似很新鮮,其實這是一個早就被研究多年的成熟領域了。它的名字叫statistical process control(基於統計的流程控制),簡稱SPC。最先的奠定人是 Walter Shewhart ,他發明的Shewhart Control Chart是最先的用於告警的曲線控制圖。在這個基礎之上,由於工業質量控制領域用途普遍,有了很是深刻的發展。著名統計軟件SAS,甚至有一個專門的工具SAS/QC用於這個領域。
最基本的shewhart control chart長成這個樣子:
假設這張圖表明瞭鑽探領域裏打的孔的孔徑。由於鑽頭的大小是固定的,因此孔徑應該會在一個範圍上下波動。在正常的狀況下,這個波動應該在一個合理的範圍。在鑽頭損壞的狀況下,波動應該會超過這個合理的範圍。咱們要作的告警就是檢測到鑽頭損壞這樣的場景。怎麼作?
根據shewhart control chart,首先須要根據歷史的統計數據獲得一個平均孔徑的大小。以及在鑽頭良好的狀況下,實際打的孔徑在這個平均上下波動的方差。什麼是方差?
對應的方差就是
http://en.wikipedia.org/wiki/Standard_deviation
在統計上,方差的含義就是表明了一組數據的振動幅度。利用這些鑽頭良好狀況下的值得出的良好狀況下的振動幅度,咱們就能夠知道什麼是「合理的範圍」。好比,拍個腦殼,在兩倍振幅以內是合理的。振幅也就是歷史值的方差,數學符號叫sigma,因此能夠說在「兩個sigma」以內。因而乎,咱們能夠在圖上標記一個上界和下界。若是觀測的值超過了上界或者下界,那麼可能就是一個異常點。
用拍腦殼的方式決定「兩個sigma」也是很是不科學的。實際使用中,這個n sigma的n如何肯定也是頭大的問題。對於這個問題,咱們能夠用反推的方法來解決。在給定歷史數據的狀況下,先計算出sigma,而後再計算出歷史數據相對於歷史的平均值每一個點是幾倍的sigma。根據這些歷史數據對應的sigma的倍數(統計上叫zscore),咱們能夠知道大部分的歷史數據都是n個sigma以內的,從而把n求出來。
shewhart control chart的問題
shewhart control chart不是包治百病的,沒有任何一種control chart是適合全部類型的曲線的。shewhart control chart的適用範圍是:
到這裏就須要引入行業特性了。若是咱們監控的是HTTP請求量這樣的曲線的話。通常來講都會有如下特徵:
而咱們的目標就是,結合shewhart control chart開創的基本思想,與咱們監控的曲線的特徵,選擇一個最合適的算法來檢測出異常。
週期性規律
最容易被想起來利用的是週期性規律。好比,下面這個故障場景:
對比昨日和今日的曲線,咱們發如今非故障的時候兩條曲線基本重合,和故障的時候下跌明顯。那麼很容易就想到,爲何不用昨日的曲線,或者歷史的平均值來預測今日的曲線呢?
的確是能夠的,好比咱們能夠用過去7天的平均值來做爲今日的預測值。而後用過去7天的數據與預測值比較得出方差,用方差來肯定上下界。效果差很少是這樣的:
首先對於時間點xx:yy,咱們用過去3天的歷史數據得出一個平均值。而後咱們能夠用這些平均值得出一條預測曲線,也就是上圖中的綠色的線。而後用黃色的實際值作對比。咱們能夠發如今業務穩定的狀況下,近期的歷史是能夠很好的預測今天的實際曲線的。
可是實際查看歷史三天的曲線,咱們能夠發現上下是有波動的。這些波動就會形成方差的不穩定。
咱們能夠看到,三條曲線比較重合的時候,方差很是小,而有些時間點上方差變大很是大。
方差波動的後果就是咱們很難用方差來肯定所謂的「合理範圍」。
殘差 = 實際值 - 預測值
波動幅度 = 殘差 / 方差
上面這張圖就是波動幅度的曲線,而標了紅色方框的區域是故障時間段。能夠看到從統計特徵上來講,是明顯的,可是不夠明顯。用這種方式來告警,可能就會產生比較多的誤警。
實際使用的過程當中能夠考慮幾個優化:
這些優化能夠有改善,可是沒法從根本上克服業務自己的不規則上下波動形成的統計特徵的模糊。更要命的是由於業務常常總體上下移動,好比周末和節日。這些總體的上下會進一步擴大方差,使得原本異常的波動被認爲在合理的範圍以內,從而形成漏警。而咱們知道,漏警是致命的。
因此直接用歷史值的週期性規律來作預測和告警是很難作的,由於業務可能會昨日重複今日,可是積極上升中的業務不會每日都同樣。