在網際網路設計架構過程中,日誌非同步落庫,儼然已經是高併發環節中不可缺少的一環。為什麼說是高併發環節中不可缺少的呢? 原因在於,如果直接用mq進行日誌落庫的時候,低併發下,生產端生產資料,然後由消費端非同步落庫,是沒有什麼問題的,而且效能也都是異常的好,估計tp99應該都在1ms以內。
但是一旦併發增長起來,慢慢的你就發現生產端的tp99一直在增長,從1ms,變為2ms,4ms,直至send timeout。尤其在大促的時候,我司的系統就經歷過這個情況,當時mq的傳送耗時超過200ms,甚至一度有不少timeout產生。
考慮到這種情況在高併發的情況下才出現,所以今天我們就來探索更加可靠的方法來進行非同步日誌落庫,保證所使用的方式不會因為過高的併發而出現介面ops持續下降甚至到不可用的情況。
此種方案由於使用了非同步方式,且由於非同步的discard policy策略,當大量資料過來,緩衝區滿了之後,會拋棄部分資料。此種方案適用於能夠容忍資料丟失的業務場景,不適用於對資料完整有嚴格要求的業務場景。
來看看具體的實現方式:
然後在log4j.xml中,為此類進行配置:
最後就可以按照如下的方式進行正常使用了:
注意: 此處需要注意log4j的乙個效能問題。在log4j的conversionpattern中,匹配符最好不要出現 c% l%萬用字元,壓測實踐表明,這兩個萬用字元會導致log4j打日誌的效率降低10倍。方案一很簡便,且剝離了介面直接依賴mq導致的效能問題。但是無法解決資料丟失的問題(但是我們其實可以在本地搞個策略落盤來不及處理的資料,可以大大的減少資料丟失的機率)。但是很多的業務場景,是需要資料不丟失的,所以這就衍生出我們的另一套方案來。
方案二:增量消費log4j日誌
此種方式,是開啟worker在後台增量消費log4j的日誌資訊,和介面完全脫離。此種方式相比方案一,可以保證資料的不丟失,且可以做到完全不影響介面的ops。但是此種方式,由於是後台worker在後台啟動進行掃瞄,會導致落庫的資料慢一些,比如一分鐘之後才落庫完畢。所以適用於對落庫資料實時性不高的場景。
具體的實現步驟如下:
首先,將需要進行增量消費的日誌統一打到乙個資料夾,以天為單位,每天生成乙個帶時間戳日誌檔案。由於log4j不支援直接帶時間戳的日誌檔案生成,所以這裡需要引入log4j.extras元件,然後配置log4j.xml如下:
之後在**中的申明方式如下:
private static logger businesslogger = logge***ctory.getlogger("file_rolling_logger");
最後在需要記錄日誌的地方使用方式如下:
businesslogger.error(jsonutils.tojsonstring(mymessage))
這樣就可以將日誌列印到乙個單獨的檔案中,且按照日期,每天生成乙個。
然後,當日誌檔案生成完畢後,我們就可以開啟我們的worker進行增量消費了,這裡的增量消費方式,我們選擇randomaccessfile這個類來進行,由於其獨特的位點讀取方式,可以使得我們非常方便的根據位點的位置來消費增量檔案,從而避免了逐行讀取這種低效率的實現方式。
注意,為每個日誌檔案都單獨建立了乙個位點檔案,裡面儲存了對應的檔案的位點讀取資訊。當worker掃瞄開始的時候,會首先讀取位點檔案裡面的位點資訊,然後找到相應的日誌檔案,從位點資訊位置開始進行消費。這就是整個增量消費worker的核心。具體**實現如下(**太長):
此種方式由於worker掃瞄是每隔一段時間啟動一次進行消費,所以導致資料從產生到入庫,可能經歷時間超過一分鐘以上,但是在一些對資料延遲要求比較高的業務場景,比如庫存扣減,是不能容忍的,所以這裡我們就引申出第三種做法,基於記憶體檔案佇列的非同步日誌消費。
方案三:基於記憶體檔案佇列的非同步日誌消費
由於方案一和方案二都嚴重依賴log4j,且方案本身都存在著要麼丟資料,要麼入庫時間長的缺點,所以都並不是那麼盡如人意。但是本方案的做法,既解決了資料丟失的問題,又解決了資料入庫時間被拉長的尷尬,所以是終極解決之道。而且在大**過程中,此種方式經歷了實戰檢驗,可以大面積的推廣使用。
在實際使用的時候,arrayblockingqueue作為核心佇列,顯然是全域性加鎖的,後續我們考慮公升級為無鎖佇列,所以將會參考netty中的有界無鎖佇列:mpscarrayqueue。預計效能將會再好一些。
上面就是在進行非同步日誌消費的時候,我所經歷的三個階段,並且一步一步的優化到目前的方式。雖然過程曲折,但是結果令人歡欣鼓舞。
你所不知道的日誌非同步落庫
在網際網路設計架構過程中,日誌非同步落庫,儼然已經是高併發環節中不可缺少的一環。為什麼說是高併發環節中不可缺少的呢?原因在於,如果直接用mq進行日誌落庫的時候,低併發下,生產端生產資料,然後由消費端非同步落庫,是沒有什麼問題的,而且效能也都是異常的好,估計tp99應該都在1ms以內。但是一旦併發增長...
你完全沒了解過的日誌非同步落庫
在網際網路設計架構過程中,日誌非同步落庫,儼然已經是高併發環節中不可缺少的一環。為什麼說是高併發環節中不可缺少的呢?原因在於,如果直接用mq進行日誌落庫的時候,低併發下,生產端生產資料,然後由消費端非同步落庫,是沒有什麼問題的,而且效能也都是異常的好,估計tp99應該都在1ms以內。但是一旦併發增長...
logback 日誌非同步配置
5level logger 5line msg n d.log 10 這種同步寫入的方式勢必會影響業務的執行效率。幸運的是,logback 提供了非同步的方式來解決這個問題,logback spring.xml 配置如下 5level logger 5line msg n d.log 10 0 51...