作者:麥克周?
寫在前面
做過分布式系統(tǒng)的人都知道,想要在大規(guī)模集群下處理高并發(fā)事務(wù)時同時滿足CAP(一致性、可用性、分區(qū)容錯),從理論上來說不可能,當然聽說最近谷歌已經(jīng)實現(xiàn)了這樣的分布式系統(tǒng),但是總的來說確實非常難。對于社交媒體的海量日志文件,如果我們也提出了需要確保高可用、持續(xù)寫入數(shù)據(jù)、按照記錄順序返回數(shù)據(jù)等三條要求,你覺得是否可以實現(xiàn)?FaceBook的LogDevice實現(xiàn)了。
什么是日志
日志是記錄一系列序列化的系統(tǒng)行為的信息,我們需要確保它們能夠被保存在可靠的地方。對于應(yīng)用程序來說,日志的作用一般有兩個,即Troubleshooting和顯示程序運行狀態(tài)。好的日志記錄方式可以提供我們足夠多定位問題的依據(jù)。對于一些復(fù)雜系統(tǒng),例如數(shù)據(jù)庫,日志可以承擔(dān)數(shù)據(jù)備份、同步作用,很多分布式數(shù)據(jù)庫都采用“write-ahead”方案,在節(jié)點數(shù)據(jù)同步時通過日志文件恢復(fù)數(shù)據(jù)。
日志一般具有三個特性:
面向記錄:寫入日志的一定是孤立的行,而不是一個字節(jié)。日志實質(zhì)上是問題的最小單元,用戶也一定是讀取整行日志。日志的存儲原則上按照順序,即按照LSN(日志順序數(shù)字)存放,但是也不完全這么要求,所以日志系統(tǒng)可以優(yōu)先高寫入需求,對寫入失敗容錯。日志天生就是遞增的:也就是說,日志是不會修改的,那么也就意味著,日志系統(tǒng)的設(shè)計應(yīng)該是以高寫入、高讀取為目標,不需要擔(dān)心更新操作的數(shù)據(jù)一致性問題。日志存儲周期長:可能是一天,也可能是一個月,甚至于一年。這也就意味著,日志的刪除規(guī)則一般都是按照時間或者空間進行設(shè)定的,具有固定的規(guī)則。來個假如
假如我們要設(shè)計一個分布式日志存儲系統(tǒng),你會怎么設(shè)計?
日志信息需要傳輸、存儲,為了實現(xiàn)穩(wěn)定的數(shù)據(jù)交換,我們可以采用Kafka作為消息中間件。
Kafka實際上是一個消息發(fā)布訂閱系統(tǒng)。Producer向某個Topic發(fā)布消息,而Consumer訂閱某個Topic的消息,進而一旦有新的關(guān)于某個Topic的消息,Broker會傳遞給訂閱它的所有Consumer。在Kafka中,消息是按Topic組織的,而每個Topic又會分為多個Partition,這樣便于管理數(shù)據(jù)和進行負載均衡。同時,它也使用了Zookeeper進行負載均衡。
Kafka在磁盤上的存取代價為O(1),即便是普通服務(wù)器,每秒也能處理幾十萬條消息,并且它本身就是分布式架構(gòu),也支持將數(shù)據(jù)并行加載到Hadoop。
上面這張圖是一個典型的采用消息中間件進行日志數(shù)據(jù)交換的系統(tǒng)設(shè)計架構(gòu),但是沒有實現(xiàn)數(shù)據(jù)存儲,也沒有描述數(shù)據(jù)是如何被抽取并發(fā)送到Kafka的。
如果想要實現(xiàn)數(shù)據(jù)存儲,并描述清楚內(nèi)部處理流程,我們可以采用怎么樣的日志處理系統(tǒng)架構(gòu)呢?這里推薦你FaceBook的Scribe,它是一款開源的日志收集系統(tǒng),在Facebook內(nèi)部已經(jīng)得到大量的應(yīng)用。它能夠從各種日志源上收集日志,存儲到一個中央存儲系統(tǒng) (可以是NFS,分布式文件系統(tǒng)等)上,以便于進行集中統(tǒng)計分析處理。
Scribe最重要的特點是容錯性好。當后端的存儲系統(tǒng)奔潰時,Scribe會將數(shù)據(jù)寫到本地磁盤上,當存儲系統(tǒng)恢復(fù)正常后,Scribe將日志重新加載到存儲系統(tǒng)中。
Scribe的架構(gòu)比較簡單,主要包括三部分,分別為Scribe Agent, Scribe和存儲系統(tǒng)。Scribe Agent實際上是一個Thrift Client。Scribe接收到Thrift Client發(fā)送過來的數(shù)據(jù),根據(jù)配置文件,將不同topic的數(shù)據(jù)發(fā)送給不同的對象。存儲系統(tǒng)實際上就是Scribe中的Store,當前Scribe支持非常多的Store。
貌似市面上已經(jīng)有很多分布式日志收集系統(tǒng)了,為什么FaceBook還需要推出LogDevice呢?而且FaceBook自己已經(jīng)有了Scribe,為什么還要繼續(xù)設(shè)計LogDevice?因為Scribe更多實現(xiàn)了日志數(shù)據(jù)的收集,它不是一個完整的日志處理、存儲、讀取服務(wù),系統(tǒng)設(shè)計也較為死板,存儲更多依賴HDFS,使用過程中一定出現(xiàn)了不能滿足自身需求的情況。而對于開源的哪些分布式日志收集系統(tǒng),更多的是集成各個開源組件,共同完成日志存儲系統(tǒng)設(shè)計需求。對于FaceBook的工程師來說,他們一貫秉承著用于創(chuàng)新的精神,想想Apache Cassandra,其實當時已經(jīng)有HBase等成熟的NoSQL數(shù)據(jù)庫,但是由于存在中心節(jié)點等諸多設(shè)計上的限制,F(xiàn)aceBook自己搞了一個全新的無中心化設(shè)計的架構(gòu),即便在初期飽受質(zhì)疑,后續(xù)也在不斷地改進,到目前為止,Cassandra真正進入到了它的黃金時代。
LogDevice
設(shè)計背景FaceBook擁有大量的分布式服務(wù)用于保存和處理數(shù)據(jù),如果想要構(gòu)建高可用的數(shù)據(jù)密集型分布式服務(wù),F(xiàn)aceBook認為,一定需要保存日志。為了處理FaceBook內(nèi)部日志的高強度負載、性能需求,F(xiàn)aceBook把LogDevice設(shè)計成了可以調(diào)節(jié)的系統(tǒng),而不是一套方案應(yīng)對所有需求。
需求整理對于日志服務(wù)的需求,也就是對于LogDevice的需求,第一條就是服務(wù)必須永遠在線,不允許出現(xiàn)離線狀態(tài),因為FaceBook內(nèi)部各個系統(tǒng)都需要保存日志,也就是說高可用。第二條是持久性,也就是說不允許丟數(shù)據(jù),特別是返回客戶端寫入成功之后,絕對不能丟失數(shù)據(jù)。第三條是存在一定程度的數(shù)據(jù)讀取,并且通常是讀取最近寫入的日志數(shù)據(jù),這一條實質(zhì)上是要求寫入響應(yīng)快。
設(shè)計思路對于整個日志系統(tǒng)來說,整個設(shè)計應(yīng)該更加關(guān)注數(shù)據(jù)的寫入速度,怎么樣設(shè)計才能具有更快的寫入速度,并能支撐一定的讀取速度,所以需要看看數(shù)據(jù)是如何被寫入到LogDevice的。
如果需要提升日志文件的寫入速率,或者更高一點要求,希望沒有寫入速率限制,你該怎么實現(xiàn)?我們可以模仿分布式文件系統(tǒng)或者分布式數(shù)據(jù)庫的設(shè)計方式,采用多處副本方式,即一個文件有多個副本,那么每次日志寫入請求就有了幾處寫入地址選擇,而不是單一一個節(jié)點,或者幾個特定的節(jié)點。這樣做的好處是,當集群中的一部分節(jié)點宕機或者失去聯(lián)系時,日志寫入請求不會受到大規(guī)模的干擾,并且寫入負載能夠做到相對均衡。
數(shù)據(jù)副本設(shè)計,有沒有其他系統(tǒng)實現(xiàn)?
有,非常多,例如HDFS、Cassandra。我們這里還是以FaceBook自己出品的Cassandra為例。
Cassandra在多個節(jié)點上存儲副本以確??捎眯院蛿?shù)據(jù)容錯。副本策略決定了副本的放置方法。集群中的副本數(shù)量被稱為復(fù)制因子,復(fù)制因子為1表示每行只有一個副本,復(fù)制因子為2表示每行有兩個副本,每個副本不在同一個節(jié)點。所有副本同等重要,沒有主次之分。作為一般規(guī)則,副本因子不應(yīng)超過在集群中的節(jié)點的樹木。當副本因子超過節(jié)點數(shù)時,寫入不會成功,但讀取只要提供所期望的一致性級別即可滿足。目前Cassandra中實現(xiàn)了不同的副本策略,包括:
SimpleStrategy:復(fù)制數(shù)據(jù)副本到協(xié)調(diào)者節(jié)點的N-1個后繼節(jié)點上;NetworkTopologyStrategy:用于多數(shù)據(jù)中心部署。這種策略可以指定每個數(shù)據(jù)中心的副本數(shù)。在同數(shù)據(jù)中心中,它按順時針方向直到另一個機架放置副本。它嘗試著將副本放置在不同的機架上,因為同一機架經(jīng)常因為電源、制冷和網(wǎng)絡(luò)問題導(dǎo)致不可用。多數(shù)據(jù)中心集群最常見的兩種配置方式是:
每個數(shù)據(jù)中心2個副本:此配置容忍每個副本組單節(jié)點的失敗,并且仍滿足一致性級別為ONE的讀操作。每個數(shù)據(jù)中心3個副本:此配置可以容忍在強一致性級別LOCAL_QUORUM基礎(chǔ)上的每個副本組1個節(jié)點的失敗,或者容忍一致性級別ONE的每個數(shù)據(jù)中心多個節(jié)點的失敗。LogDevice將日志里的記錄順序和實際存儲的順序區(qū)分開來,通過序列器產(chǎn)生一個學(xué)號,對每一行存儲的日志進行重新序列標定。一旦一行記錄被標定了這個序列號,接下來該條記錄(數(shù)據(jù))就會被保存在集群中任一位置。注意,這里提到的序列號不是一個數(shù)字,而是一對數(shù)字,第一個數(shù)字叫做“ epoch number”,第二個是相對于第一個的偏移量。序列號生成器本身也是需要做好容災(zāi)的,也就是說,一旦一個序列號生成器服務(wù)不在線,另一個一定要被立即啟用,而它生成的序列號要比當前已經(jīng)存在的序列號大。FaceBook使用ZooKeeper保存序列號(Epoch Number)。
這里為什么要選擇ZooKeeper存儲序列號?
ZooKeeper作為Hadoop
項目中的一個子項目,是Hadoop集群管理的一個必不可少的模塊,它主要用來控制集群中的數(shù)據(jù),如它管理Hadoop集群中的NameNode,還有HBase中Master節(jié)點的選舉機制、服務(wù)器之間的狀態(tài)同步等。除此之外,ZooKeeper還可以被用在構(gòu)建高可用性集群、統(tǒng)一命名服務(wù)管理、分布式緩存機制設(shè)計、配置文件管理、集群管理、分布式鎖機制設(shè)計、隊列管理等等。
存儲序列號的思路配置文件管理類似。
配置文件的管理在分布式應(yīng)用環(huán)境中很常見,例如同一個應(yīng)用系統(tǒng)需要多臺PC Server運行,但是它們運行的應(yīng)用系統(tǒng)的某些配置項是相同的,如果要修改這些相同的配置項,那么就必須同時修改每臺運行這個應(yīng)用系統(tǒng)的PC Server,這樣非常麻煩而且容易出錯。諸如這樣的配置信息完全可以交給ZooKeeper來管理,將配置信息保存在ZooKeeper的某個目錄節(jié)點中,然后將所有需要修改的應(yīng)用機器監(jiān)控配置信息的狀態(tài),一旦配置信息發(fā)生變化,每臺應(yīng)用機器就會收到ZooKeeper的通知,然后從ZooKeeper獲取新的配置信息應(yīng)用到系統(tǒng)中。
如上圖所示,實際應(yīng)用時我們可以通過自動監(jiān)測Master節(jié)點內(nèi)是否形成了新的配置文件,并在檢測到形成了新的配置文件后主動上傳到ZooKeeper,并下發(fā)到各Slave節(jié)點加載到內(nèi)存中用于搜索任務(wù)的處理,無需管理人員在發(fā)現(xiàn)Master節(jié)點形成了新的配置文件之后,重啟Master節(jié)點才將新的配置文件上傳,顯然降低了Master節(jié)點與Slave節(jié)點間配置文件同步的繁瑣性,提高了設(shè)備的智能性,降低了同步成本。
根據(jù)FaceBook的設(shè)計思路,由于日志文件本身是可以隨機讀的,并且很多節(jié)點上都存在數(shù)據(jù),這有點像小文件存儲方式,每個節(jié)點上的數(shù)據(jù)都可以被讀取,因此不會造成IO和網(wǎng)絡(luò)資源的浪費。
數(shù)據(jù)是怎么做到負載均衡的?
FaceBook沒有在文章中描述實現(xiàn)原理。我們可以看看HDFS是怎么實現(xiàn)的。
數(shù)據(jù)平衡過程由于平衡算法的原因造成它是一個迭代的、周而復(fù)始的過程。每一次迭代的最終目的是讓高負載的機器能夠降低數(shù)據(jù)負載,所以數(shù)據(jù)平衡會最大程度上地使用網(wǎng)絡(luò)帶寬。下圖1數(shù)據(jù)平衡流程交互圖顯示了數(shù)據(jù)平衡服務(wù)內(nèi)部的交互情況,
包括NameNode和DataNode。
步驟分析如下:
數(shù)據(jù)平衡服務(wù)首先要求NameNode生成DataNode數(shù)據(jù)分布分析報告。選擇所有的DataNode機器后,要求NameNode匯總數(shù)據(jù)分布的具體情況。確定具體數(shù)據(jù)塊遷移路線圖,保證網(wǎng)絡(luò)內(nèi)最短路徑,并且確保原始數(shù)據(jù)塊被刪除。實際開始數(shù)據(jù)塊遷移任務(wù)。數(shù)據(jù)遷移任務(wù)完成后,通過NameNode可以刪除原始數(shù)據(jù)塊。NameNode在確保滿足數(shù)據(jù)塊最低副本條件下選擇一塊數(shù)據(jù)塊刪除。NameNode通知數(shù)據(jù)平衡服務(wù)任務(wù)全部完成。HDFS數(shù)據(jù)在各個數(shù)據(jù)節(jié)點間可能保存的格式不一致。當存放新的數(shù)據(jù)塊(一個文件包含多個數(shù)據(jù)塊)時,NameNode在選擇數(shù)據(jù)節(jié)點作為其存儲地點前需要考慮以下幾點因素:
當數(shù)據(jù)節(jié)點正在寫入一個數(shù)據(jù)塊時,會自動在本節(jié)點內(nèi)保存一個副本??绻?jié)點備份數(shù)據(jù)塊。相同節(jié)點內(nèi)的備份數(shù)據(jù)塊可以節(jié)約網(wǎng)絡(luò)消耗。HDFS數(shù)據(jù)均勻分布在整個集群的數(shù)據(jù)節(jié)點上。FaceBook采用內(nèi)存+磁盤的方式存儲日志,HDD硬盤可以達到100-200MBps每秒的順序讀寫速度,隨機讀寫速度頂峰可以達到100-140MBps每秒。用來存儲日志的服務(wù)被稱為LogsDB,它是針對寫入性能進行特殊優(yōu)化過的。LogsDB本身又是構(gòu)建于RocksDB之上的,RocksDB是基于LSM樹的有序Key-Value存儲層。RocksDB的每一個實例對應(yīng)LogsDB的分區(qū),當寫入日志文件時,會寫入到最新的分區(qū),也就是最近訪問過的RocksDB實例(以log id、LSN排序),然后以順序方式保存到磁盤(稱為SST文件)。這種方式確保了寫入的方式是順序方式,但是需要合并文件(當達到LogsDB分區(qū)的最大文件數(shù)量時)。
總結(jié)
就在我寫文章的時候,微博因為“鹿晗介紹女朋友”事件奔潰了,系統(tǒng)啟動之后的數(shù)據(jù)同步、驗證過程,日志的作用非常重要。目前LogDevice還沒有開源,但是從它的介紹來看,它應(yīng)該是結(jié)合了FaceBook內(nèi)部的多個開源項目的精髓,例如Cassandra,它的無中心化存儲、碎片化存儲(SSTable)、SSTable文件合并等等優(yōu)秀的特性,為確保日志文件的高速寫入、快速讀取提供技術(shù)支撐。FaceBook已經(jīng)明確今年年底會開源LogDevice,喜歡分布式實時處理、存儲系統(tǒng)的同學(xué)們,就等著它了。
- 蜜度索驥:以跨模態(tài)檢索技術(shù)助力“企宣”向上生長
- 央國企采購管理升級,合合信息旗下啟信慧眼以科技破局難點
- Apache Struts重大漏洞被黑客利用,遠程代碼執(zhí)行風(fēng)險加劇
- Crunchbase:2024年AI網(wǎng)絡(luò)安全行業(yè)風(fēng)險投資超過26億美元
- 調(diào)查報告:AI與云重塑IT格局,77%的IT領(lǐng)導(dǎo)者視網(wǎng)絡(luò)安全為首要挑戰(zhàn)
- 長江存儲發(fā)布聲明:從無“借殼上市”意愿
- 泛微·數(shù)智大腦Xiaoe.AI正式發(fā)布,千人現(xiàn)場體驗數(shù)智化運營場景
- IDC:2024年第三季度北美IT分銷商收入增長至202億美元
- AI成為雙刃劍!凱捷調(diào)查:97%組織遭遇過GenAI漏洞攻擊
- openEuler開源五年樹立新里程碑,累計裝機量突破1000萬
- 創(chuàng)想 華彩新程!2024柯尼卡美能達媒體溝通會煥新增長之道
免責(zé)聲明:本網(wǎng)站內(nèi)容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準確性及可靠性,但不保證有關(guān)資料的準確性及可靠性,讀者在使用前請進一步核實,并對任何自主決定的行為負責(zé)。本網(wǎng)站對有關(guān)資料所引致的錯誤、不確或遺漏,概不負任何法律責(zé)任。任何單位或個人認為本網(wǎng)站中的網(wǎng)頁或鏈接內(nèi)容可能涉嫌侵犯其知識產(chǎn)權(quán)或存在不實內(nèi)容時,應(yīng)及時向本網(wǎng)站提出書面權(quán)利通知或不實情況說明,并提供身份證明、權(quán)屬證明及詳細侵權(quán)或不實情況證明。本網(wǎng)站在收到上述法律文件后,將會依法盡快聯(lián)系相關(guān)文章源頭核實,溝通刪除相關(guān)內(nèi)容或斷開相關(guān)鏈接。