七牛是如何搞定每天500億條日誌的

2021-08-17 13:52:32 字數 2949 閱讀 8083

資料平台在大部分公司都屬於支撐性平台,做的不好立刻會被吐槽,這點和運維部門很像。所以在技術選型上優先考慮現成的工具,快速出成果,沒必要去擔心有技術負擔。早期,我們走過彎路,認為沒多少工作量,收集儲存和計算都自己研發,發現是吃力不討好。去年上半年開始,我們全面擁抱開源工具,搭建自己的資料平台。

公司的主要資料**是散落在各個業務伺服器上的半結構化日誌,比如系統日誌、程式日誌、訪問日誌、審計日誌等。日誌是最原始的資料記錄,如果不是日誌,肯定會有資訊上的丟失。說個簡單的例子,需求是統計nginx上每個網域名稱的的流量,這個完全可以通過乙個簡單的nginx模組去完成,但是如果需要統計不同**的流量就無法做了,所以需要原始的完整的日誌。

有種手法是業務程式把日誌通過網路直接傳送出去,但是這並不可取,因為網路和接收端並不完全可靠,當出問題時會對業務造成影響或者日誌丟失。因此,對業務侵入最小最自然的方式是把日誌落到本地硬碟上。

agent設計需求

每台機器上會有乙個agent去同步這些日誌,這是個典型的佇列模型,業務程序在不斷的push,agent在不停地pop。agent需要有記憶功能,用來儲存同步的位置(offset),這樣才盡可能保證資料準確性,但不可能做到完全準確。由於傳送資料和儲存offset是兩個動作,不具有事務性,不可避免的會出現資料不一致性情況,通常是傳送成功後儲存offset,那麼在agent異常退出或機器斷電時可能會造成多餘的資料。 agent需要足夠輕,這主要體現在運維和邏輯兩個方面。agent在每台機器上都會部署,運維成本、接入成本是需要考慮的。agent不應該有解析日誌、過濾、統計等動作,這些邏輯應該給資料消費者。倘若agent有較多的邏輯,那它是不可完成的,不可避免的經常會有公升級變更動作。

資料收集流程

資料收集這塊的技術選擇,agent是用go自己研發的,訊息中介軟體kafka,資料傳輸工具flume。說到資料收集經常有人拿flume和kafka做比較,我看來這兩者定位是不同的,flume更傾向於資料傳輸本身,kakfa是典型的訊息中介軟體用於解耦生產者消費者。

具體架構上,agent並沒把資料直接傳送到kafka,在kafka前面有層由flume構成的forward。這樣做有兩個原因:

forward層不含狀態,完全可以做到水平擴充套件,不用擔心成為瓶頸。出於高可用考慮,forward通常不止乙個例項,這會帶來日誌順序問題,agent按一定規則(round-robin、failover等)來選擇forward例項,即使kafka partition key一樣,由於forward層的存在,最終落入kafka的資料順序和agent傳送的順序可能會不一樣。我們對亂序是容忍的,因為產生日誌的業務基本是分布式的,保證單台機器的日誌順序意義不大。如果業務對順序性有要求,那得把資料直接發到kafka,並選擇好partition key,kafka只能保證partition級的順序性。

多機房的情形,通過上述流程,先把資料匯到本地機房kafka集群,然後匯聚到核心機房的kafka,最終供消費者使用。由於kafka的mirror對網路不友好,這裡我們選擇更加的簡單的flume去完成跨機房的資料傳送。

flume使用要點

flume在不同的資料來源傳輸資料還是比較靈活的,但有以下幾個點需要注意。

kafka使用要點

kafka在效能和擴充套件性很不錯,以下幾個點需要注意下。

資料離線和實時計算

資料到kafka後,一路資料同步到hdfs,用於離線統計,另一路用於實時計算。由於今天時間有限,接下來只能和大家分享下實時計算的一些經驗。

實時計算選擇的是spark streaming。目前只有統計需求,沒迭代計算的需求,spark streaming使用比較保守。從kakfa讀資料統計完存入mongodb中,中間狀態資料很少,好處是系統吞吐量很大,但沒遇到記憶體相關問題。

spark streaming對儲存計算結果的資料庫tps要求較高。假如有10w個網域名稱需要統計流量,batch interval為10s,每個網域名稱有4個相關統計項,算下來平均是4w tps,這只是平均值,實際峰值更高,固態硬碟上的mongodb也只能抗1w tps,後續我們會考慮用redis來抗這麼高的tps。

當開啟speculation引數或**層面沒處理好異常時,task可能會被重放。但是有外部狀態的task是不可重入的,否則會造成計算結果的不準確。說個簡單的例子,如下:

這個任務,如果被重放了,會造成落入mongodb的結果比實際多。

有些物件會包含狀態,這些狀態的生成需要較大的代價,不能做到在每次使用時都去new乙個。我們對這種物件的處理策略是jvm內乙個物件,同時在**層面做好併發控制。類似下面:

如果這種使用形式有效能問題,可以考慮實現乙個pool來管理。

在spark1.3的後版本,streaming為kafka引入了新的direct api試**決資料準確性問題。direct api把kafka consumer offset的管理暴露出來(舊版本是非同步存入zookeeper),讓使用者透明的管理consumer offset,這在一定程度上能緩解準確性問題,但不可避免還會有一致性問題。為什麼這樣說呢?只有計算結果和offset兩者的儲存具有事務性,才能完全準確。這個事務有兩種手段做到,一種是用mysql這種支援事務的資料庫,把計算結果和offset的儲存放在乙個事務裡,另一種是自己實現兩階段提交。direct api 還會有效能問題,因為它到計算的時候才實際從kafka讀資料,這對整體吞吐有很大影響。

七牛資料平台規模

要分享的就這些了,最後秀下實時計算這邊規模:flume+kafka+spark 混部在8台高配機器,日均500億條資料,峰值80w tps。

我是如何搞定複雜水晶報表的(2)

要想獲取圖6 14中某門課程某個班級的成績表,除了必須獲取課程號和班級號這兩個主鍵以外,還必須獲取的資訊包括 某門課程某個班級教師閱卷時候設定的考試成績百分比值,以及參加該門課程考試的學生各個考試型別具體的成績,同時也必須獲取相應的學期資訊 課程名 專業名 班級名,而且在系統執行最後應當將考試成績的...

揭秘 500粉絲10萬 的閱讀量是如何煉成的?

在微信朋友圈看別人分享的鏈結,開啟一看,竟然有10萬 的閱讀量。每每看到這種情況,都讓本尊十分羨慕。可是,那些微信閱讀量10萬 的文章是如何做到的呢?是內容直接造成的?還是微信 粉絲的基數高呢?之前在微信朋友圈曾經有過這樣一篇火爆的文章,名字叫 幫你是情分,不幫你是本分 這篇文章曾經被朋友圈刷屏了,...

乙個全國500強企業的老闆是如何關愛員工的

每當我想起這些工人在艱苦的環境裡工作,不免都熱淚盈眶。我熱愛這些工人,我熱愛這些工人如同兄弟姐妹子女,他們的這種精神 即艱苦奮鬥的創業精神 是敬業的創業之本。這是敬業集團李趕坡董事長在敬業愛廠工程技術人員表彰會上的肺腑之言。其言感人,其行動人!多年來,敬業集團李趕坡董事長始終心揣員工,大到公寓建設 ...