04.17 一個百億級日誌系統是怎麼設計出來的?

日誌是記錄系統中各種問題信息的關鍵,也是一種常見的海量數據。


一個百億級日誌系統是怎麼設計出來的?


日誌平臺為集團所有業務系統提供日誌採集、消費、分析、存儲、索引和查詢的一站式日誌服務。

主要為了解決日誌分散不方便查看、日誌搜索操作複雜且效率低、業務異常無法及時發現等等問題。

隨著有贊業務的發展與增長,每天都會產生百億級別的日誌量(據統計,平均每秒產生 50 萬條日誌,峰值每秒可達 80 萬條)。日誌平臺也隨著業務的不斷髮展經歷了多次改變和升級。

本文跟大家分享有贊在當前日誌系統的建設、演進以及優化的經歷,這裡先拋磚引玉,歡迎大家一起交流討論。

原有日誌系統

有贊從 2016 年就開始構建適用於業務系統的統一日誌平臺,負責收集所有系統日誌和業務日誌,轉化為流式數據。

通過 Flume 或者 Logstash 上傳到日誌中心(Kafka 集群),然後供 Track、Storm、Spark 及其他系統實時分析處理日誌。

並將日誌持久化存儲到 HDFS 供離線數據分析處理,或寫入 ElasticSearch 提供數據查詢。

整體架構如圖 2-1 所示:


一個百億級日誌系統是怎麼設計出來的?


圖 2-1:原有日誌系統架構

隨著接入的應用越來越多,接入的日誌量越來越大,逐漸出現一些問題和新的需求,主要在以下幾個方面:

  • 業務日誌沒有統一的規範,業務日誌格式各式各樣,新應用接入無疑大大的增加了日誌的分析、檢索成本。
  • 多種數據日誌數據採集方式,運維成本較高。
  • 日誌平臺收集了大量用戶日誌信息,當時無法直接的看到某個時間段,哪些錯誤信息較多,增加定位問題的難度。
  • 存儲方面。

關於存儲方面:

  • 採用了 ES 默認的管理策略,所有的 Index 對應 3*2 Shard(3 個 Primary,3 個 Replica)。

有部分 Index 數量較大,對應單個 Shard 對應的數據量就會很大,導致有 Hot Node,出現很多 bulk request rejected,同時磁盤 IO 集中在少數機器上。

  • 對於 bulk request rejected 的日誌沒有處理,導致業務日誌丟失。
  • 日誌默認保留 7 天,對於 SSD 作為存儲介質,隨著業務增長,存儲成本過於高昂。
  • 另外 Elasticsearch 集群也沒有做物理隔離,ES 集群 OOM 的情況下,使得集群內全部索引都無法正常工作,不能為核心業務運行保駕護航。

現有系統演進

日誌從產生到檢索,主要經歷以下幾個階段:

  • 採集
  • 傳輸
  • 緩衝
  • 處理
  • 存儲
  • 檢索

詳細架構如圖 3-1 所示:


一個百億級日誌系統是怎麼設計出來的?


圖 3-1:現有系統架構

日誌接入

日誌接入目前分為兩種方式:

  • SDK 接入:日誌系統提供了不同語言的 SDK,SDK 會自動將日誌的內容按照統一的協議格式封裝成最終的消息體,並最後最終通過 TCP 的方式發送到日誌轉發層(Rsyslog-Hub)。
  • HTTP Web 服務接入:有些無法使用 SDK 接入日誌的業務,可以通過 HTTP 請求直接發送到日誌系統部署的 Web 服務,統一由 Web Protal 轉發到日誌緩衝層的 Kafka 集群。

日誌採集


一個百億級日誌系統是怎麼設計出來的?


現在有 Rsyslog-Hub 和 Web Portal 做為日誌傳輸系統,Rsyslog 是一個快速處理收集系統日誌的程序,提供了高性能、安全功能和模塊化設計。

之前系統演進過程中使用過直接在宿主機上部署 Flume 的方式,由於 Flume 本身是 Java 開發的,會比較佔用機器資源而統一升級為使用 Rsyslog 服務。

為了防止本地部署與 Kafka 客戶端連接數過多,本機上的 Rsyslog 接收到數據後,不做過多的處理就直接將數據轉發到 Rsyslog-Hub 集群。

通過 LVS 做負載均衡,後端的 Rsyslog-Hub 會通過解析日誌的內容,提取出需要發往後端的 Kafka Topic。

日誌緩衝

Kafka 是一個高性能、高可用、易擴展的分佈式日誌系統,可以將整個數據處理流程解耦。

將 Kafka 集群作為日誌平臺的緩衝層,可以為後面的分佈式日誌消費服務提供異步解耦、削峰填谷的能力,也同時具備了海量數據堆積、高吞吐讀寫的特性。

日誌切分

日誌分析是重中之重,為了能夠更加快速、簡單、精確地處理數據。日誌平臺使用 Spark Streaming 流計算框架消費寫入 Kafka 的業務日誌。

Yarn 作為計算資源分配管理的容器,會跟不同業務的日誌量級,分配不同的資源處理不同日誌模型。

整個 Spark 任務正式運行起來後,單個批次的任務會將拉取到的所有的日誌分別異步的寫入到 ES 集群。

業務接入之前可以在管理臺對不同的日誌模型設置任意的過濾匹配的告警規則,Spark 任務每個 Excutor 會在本地內存裡保存一份這樣的規則。

在規則設定的時間內,計數達到告警規則所配置的閾值後,通過指定的渠道給指定用戶發送告警,以便及時發現問題。

當流量突然增加,ES 會有 bulk request rejected 的日誌重新寫入 Kakfa,等待補償。

日誌存儲

原先所有的日誌都會寫到 SSD 盤的 ES 集群,LogIndex 直接對應 ES 裡面的索引結構。

隨著業務增長,為了解決 ES 磁盤使用率單機最高達到 70%~80% 的問題,現有系統採用 Hbase 存儲原始日誌數據和 ElasticSearch 索引內容相結合的方式,完成存儲和索引。

Index 按天的維度創建,提前創建 Index 會根據歷史數據量,決定創建明日 Index 對應的 Shard 數量,也防止集中創建導致數據無法寫入。

現在日誌系統只存近 7 天的業務日誌,如果配置更久的保存時間的,會存到歸檔日誌中。

對於存儲來說,Hbase、ES 都是分佈式系統,可以做到線性擴展。

多租戶

隨著日誌系統不斷髮展,全網日誌的 QPS 越來越大,並且部分用戶對日誌的實時性、準確性、分詞、查詢等需求越來越多樣。


一個百億級日誌系統是怎麼設計出來的?


為了滿足這部分用戶的需求,日誌系統支持多租戶的的功能,根據用戶的需求,分配到不同的租戶中,以避免相互影響。


一個百億級日誌系統是怎麼設計出來的?


針對單個租戶的架構如下:

  • SDK:可以根據需求定製,或者採用天網的 TrackAppender 或 SkynetClient。
  • Kafka 集群:可以共用,也可以使用指定 Kafka 集群。
  • Spark 集群:目前的 Spark 集群是在 Yarn 集群上,資源是隔離的,一般情況下不需要特地做隔離。
  • 存儲:包含 ES 和 Hbase,可以根據需要共用或單獨部署 ES 和 Hbase。

現有問題和未來規劃

目前,有贊日誌系統作為集成在天網裡的功能模塊,提供簡單易用的搜索方式,包括時間範圍查詢、字段過濾、NOT/AND/OR、模糊匹配等方式。

並能對查詢字段高亮顯示,定位日誌上下文,基本能滿足大部分現有日誌檢索的場景。

但是日誌系統還存在很多不足的地方,主要有:

  • 缺乏部分鏈路監控:日誌從產生到可以檢索,經過多級模塊,現在採集,日誌緩衝層還未串聯,無法對丟失情況進行精準監控,並及時推送告警。
  • 現在一個日誌模型對應一個 Kafka Topic,Topic 默認分配三個 Partition。

由於日誌模型寫入日誌量上存在差異,導致有的 Topic 負載很高,有的 Topic 造成一定的資源浪費,且不便於資源動態伸縮。

Topic 數量過多,導致 Partition 數量過多,對 Kafka 也造成了一定資源浪費,也會增加延遲和 Broker 宕機恢復時間。

  • 目前 Elasticsearch 中文分詞我們採用 ikmaxword,分詞目標是中文,會將文本做最細粒度的拆分,但是日誌大部分都是英文,分詞效果並不是很好。

上述的不足之處也是我們以後努力改進的地方,除此之外,對於日誌更深層次的價值挖掘也是我們探索的方向,從而為業務的正常運行保駕護航。


分享到:


相關文章: