偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

分布式存儲(chǔ)在B站的應(yīng)用實(shí)踐

存儲(chǔ) 新聞
如何設(shè)計(jì)一套穩(wěn)定可靠易拓展的系統(tǒng),來(lái)滿足未來(lái)進(jìn)一步增長(zhǎng)的業(yè)務(wù)訴求?

業(yè)務(wù)高速發(fā)展,B站的存儲(chǔ)系統(tǒng)如何演進(jìn)以支撐指數(shù)增長(zhǎng)的流量洪峰?隨著流量進(jìn)一步暴增,如何設(shè)計(jì)一套穩(wěn)定可靠易拓展的系統(tǒng),來(lái)滿足未來(lái)進(jìn)一步增長(zhǎng)的業(yè)務(wù)訴求?同時(shí),面對(duì)更高的可用性訴求,KV 是如何通過(guò)異地多活為應(yīng)用提供更高的可用性保障?文章的最后,會(huì)介紹一些典型業(yè)務(wù)在KV存儲(chǔ)的應(yīng)用實(shí)踐。

全文將圍繞下面4點(diǎn)展開:

  • 存儲(chǔ)演進(jìn)
  • 設(shè)計(jì)實(shí)現(xiàn)
  • 場(chǎng)景&問(wèn)題
  • 總結(jié)思考

01 存儲(chǔ)演進(jìn)

首先介紹一下B站早期的存儲(chǔ)演進(jìn)。

圖片?

針對(duì)不同的場(chǎng)景,早期的KV存儲(chǔ)包括Redix/Memcache,Redis+MySQL,HBASE。

圖片

但是隨著B站數(shù)據(jù)量的高速增長(zhǎng),這種存儲(chǔ)選型會(huì)面臨一些問(wèn)題

  • 首先,MySQL是單機(jī)存儲(chǔ),一些場(chǎng)景數(shù)據(jù)量已經(jīng)超過(guò) 10 T,單機(jī)無(wú)法放下。當(dāng)時(shí)也考慮了使用TiDB,TiDB是一種關(guān)系型數(shù)據(jù)庫(kù),對(duì)于播放歷史這種沒(méi)有強(qiáng)關(guān)系的數(shù)據(jù)并不適合。
  • 其次,是Redis Cluster的規(guī)模瓶頸,因?yàn)閞edis采用的是Gossip協(xié)議來(lái)通信傳遞信息,集群規(guī)模越大,節(jié)點(diǎn)間的通信開銷越大,并且節(jié)點(diǎn)之間狀態(tài)不一致的存留時(shí)間也會(huì)越長(zhǎng),很難再進(jìn)行橫向擴(kuò)展。
  • 另外,HBase存在嚴(yán)重長(zhǎng)尾和緩存內(nèi)存成本高的問(wèn)題。

基于這些問(wèn)題,我們對(duì)KV存儲(chǔ)提出了如下要求:

  • 易拓展:100x橫向擴(kuò)容;
  • 高性能:低延時(shí),高QPS;
  • 高可用:長(zhǎng)尾穩(wěn)定,故障自愈;
  • 低成本:對(duì)比緩存;
  • 高可靠:數(shù)據(jù)不丟。

02 設(shè)計(jì)實(shí)現(xiàn)

接下來(lái)介紹我們是如何基于上述要求進(jìn)行具體實(shí)現(xiàn)的。

1. 總體架構(gòu)

圖片

總體架構(gòu)共分為三個(gè)部分Client,Node,Metaserver。Client是用戶接入端,確定了用戶的接入方式,用戶可以采用SDK的方式進(jìn)行接入。Metaserver主要是存儲(chǔ)表的元數(shù)據(jù)信息,表分為了哪些分片,這些分片位于哪些node之上。用戶在讀寫操作的時(shí)候,只需要put、get方法,無(wú)需關(guān)注分布式實(shí)現(xiàn)的技術(shù)細(xì)節(jié)。Node的核心點(diǎn)就是Replica,每一張表會(huì)有多個(gè)分片,而每個(gè)分片會(huì)有多個(gè)Replica副本,通過(guò)Raft實(shí)現(xiàn)副本之間的同步復(fù)制,保證高可用。

2. 集群拓?fù)?/span>

圖片?

Pool:資源池。根據(jù)不同的業(yè)務(wù)劃分,分為在線資源池和離線資源池。

Zone:可用區(qū)。主要用于故障隔離,保證每個(gè)切片的副本分布在不同的zone。

Node:存儲(chǔ)節(jié)點(diǎn),可包含多個(gè)磁盤,存儲(chǔ)著Replica。

Shard:一張表數(shù)據(jù)量過(guò)大的時(shí)候可以拆分為多個(gè)Shard。拆分策略有Range,Hash。

3. Metaserver

資源管理:主要記錄集群的資源信息,包括有哪些資源池,可用區(qū),多少個(gè)節(jié)點(diǎn)。當(dāng)創(chuàng)建表的時(shí)候,每個(gè)分片都會(huì)記錄這樣的映射關(guān)系。

元數(shù)據(jù)分布:記錄分片位于哪臺(tái)節(jié)點(diǎn)之上。

健康檢查:注冊(cè)所有的node信息,檢查當(dāng)前node是否正常,是否有磁盤損壞?;谶@些信息可以做到故障自愈。

負(fù)載檢測(cè):記錄磁盤使用率,CPU使用率,內(nèi)存使用率。

負(fù)載均衡:設(shè)置閾值,當(dāng)達(dá)到閾值時(shí)會(huì)進(jìn)行數(shù)據(jù)的重新分配。

分裂管理:數(shù)據(jù)量增大時(shí),進(jìn)行橫向擴(kuò)展。

Raft選主:當(dāng)有一個(gè)Metaserver掛掉的時(shí)候,可進(jìn)行故障自愈。

Rocksdb:元數(shù)據(jù)信息持久化存儲(chǔ)。

4. Node

做為存儲(chǔ)模塊,主要包含后臺(tái)線程,RPC接入,抽象引擎層三個(gè)部分

圖片?

① 后臺(tái)線程

Binlog管理,當(dāng)用戶進(jìn)行寫操作的時(shí)候,會(huì)記錄一條binlog日志,當(dāng)發(fā)生故障的時(shí)候可以對(duì)數(shù)據(jù)進(jìn)行恢復(fù)。因?yàn)楸镜氐拇鎯?chǔ)空間有限,所以Binlog管理會(huì)將一些冷數(shù)據(jù)存放在S3,熱門的數(shù)據(jù)存放在本地。數(shù)據(jù)回收功能主要是用來(lái)防止誤刪數(shù)據(jù)。當(dāng)用戶進(jìn)行刪除操作,并不會(huì)真正的把數(shù)據(jù)刪除,通常是設(shè)置一個(gè)時(shí)間,比如一天,一天之后數(shù)據(jù)才會(huì)被回收。如果是誤刪數(shù)據(jù),就可以使用數(shù)據(jù)回收模塊對(duì)數(shù)據(jù)進(jìn)行恢復(fù)。健康檢查會(huì)檢查節(jié)點(diǎn)的健康狀態(tài),比如磁盤信息,內(nèi)存是否異常,再上報(bào)給Metaserver。Compaction模塊主要是用來(lái)數(shù)據(jù)回收管理。存儲(chǔ)引擎Rocksdb,以LSM實(shí)現(xiàn),其特點(diǎn)在于寫入時(shí)是append only的形式。

RPC接入:

當(dāng)集群達(dá)到一定規(guī)模后,如果沒(méi)有自動(dòng)化運(yùn)維,那么人工運(yùn)維的成本是很高的。所以在RPC模塊加入了指標(biāo)監(jiān)控,包括QPS、吞吐量、延時(shí)時(shí)間等,當(dāng)出現(xiàn)問(wèn)題時(shí),會(huì)很方便排查。不同的業(yè)務(wù)的吞吐量是不同的,如何做到多用戶隔離?通過(guò)Quota管理,在業(yè)務(wù)接入的時(shí)候會(huì)申請(qǐng)配額,比如一張表申請(qǐng)了10K的QPS,當(dāng)超過(guò)這個(gè)值得時(shí)候,會(huì)對(duì)用戶進(jìn)行限流。不同的業(yè)務(wù)等級(jí),會(huì)進(jìn)行不同的Quota管理。

② 抽象引擎層

主要是為了應(yīng)對(duì)不同的業(yè)務(wù)場(chǎng)景。比如大value引擎,因?yàn)長(zhǎng)SM存在寫放大的問(wèn)題,如果數(shù)據(jù)的value特別大,頻繁的寫入會(huì)導(dǎo)致數(shù)據(jù)的有效寫入非常低。這些不同的引擎對(duì)于上層來(lái)說(shuō)是透明的,在運(yùn)行時(shí)通過(guò)選擇不同的參數(shù)就可以了。

5. 分裂-元數(shù)據(jù)更新

圖片?

在KV存儲(chǔ)的時(shí)候,剛開始會(huì)根據(jù)業(yè)務(wù)規(guī)模劃分不同的分片,默認(rèn)情況下單個(gè)分片是24G的大小。隨著業(yè)務(wù)數(shù)據(jù)量的增長(zhǎng),單個(gè)分片的數(shù)據(jù)放不下,就會(huì)對(duì)數(shù)據(jù)進(jìn)行分裂。分裂的方式有兩種,rang和hash。這里我們以hash為例展開介紹:

假設(shè)一張表最開始設(shè)計(jì)了3個(gè)分片,當(dāng)數(shù)據(jù)4到來(lái),根據(jù)hash取余,應(yīng)該保存在分片1中。隨著數(shù)據(jù)的增長(zhǎng),3個(gè)分片放不下,則需要進(jìn)行分裂,3個(gè)分片會(huì)分裂成6個(gè)分片。這個(gè)時(shí)候數(shù)據(jù)4來(lái)訪問(wèn),根據(jù)Hash會(huì)分配到分片4,如果分片4正處于分裂狀態(tài),Metaserver會(huì)對(duì)訪問(wèn)進(jìn)行重定向,還是訪問(wèn)到原來(lái)的分片1。當(dāng)分片完成,狀態(tài)變?yōu)閚ormal,就可以正常接收訪問(wèn),這一過(guò)程,用戶是無(wú)感知的。

6. 分裂-數(shù)據(jù)均衡回收

圖片?

首先需要先將數(shù)據(jù)分裂,可以理解為本地做一個(gè)checkpoint,Rocksdb的checkpoint相當(dāng)于是做了一個(gè)硬鏈接,通常1ms就可以完成數(shù)據(jù)的分裂。分裂完成后,Metaserver會(huì)同步更新元數(shù)據(jù)信息,比如0-100的數(shù)據(jù),分裂之后,分片1的50-100的數(shù)據(jù)其實(shí)是不需要的,就可以通過(guò)Compaction Filter對(duì)數(shù)據(jù)進(jìn)行回收。最后將分裂后的數(shù)據(jù)分配到不同的節(jié)點(diǎn)上。因?yàn)檎麄€(gè)過(guò)程都是對(duì)一批數(shù)據(jù)進(jìn)行操作,而不是像redis那樣主從復(fù)制的時(shí)候一條一條復(fù)制,得益于這樣的實(shí)現(xiàn),整個(gè)分裂過(guò)程都在毫秒級(jí)別。

7. 多活容災(zāi)

圖片?

前面提到的分裂和Metaserver來(lái)保證高可用,對(duì)某些場(chǎng)景仍不能滿足需求。比如整個(gè)機(jī)房的集群掛掉,這在業(yè)界多是采用多活來(lái)解決。我們KV存儲(chǔ)的多活也是基于Binlog來(lái)實(shí)現(xiàn),比如在云立方的機(jī)房寫入一條數(shù)據(jù),會(huì)通過(guò)Binlog同步到嘉定的機(jī)房。假如位于嘉定的機(jī)房的存儲(chǔ)部分掛了以后,proxy模塊會(huì)自動(dòng)將流量切到云立方的機(jī)房進(jìn)行讀寫操作。最極端的情況,整個(gè)機(jī)房掛掉了,就會(huì)將所有的用戶訪問(wèn)集中到里一個(gè)機(jī)房,保證可用性。

03 場(chǎng)景&問(wèn)題

接下來(lái)介紹KV在B站應(yīng)用的典型場(chǎng)景以及遇到的問(wèn)題。

圖片?

最典型的場(chǎng)景就是用戶畫像,比如推薦,就是通過(guò)用戶畫像來(lái)完成的。其他還有動(dòng)態(tài)、追番、對(duì)象存儲(chǔ)、彈幕等都是通過(guò)KV來(lái)存儲(chǔ)。

1. 定制優(yōu)化

圖片?

基于抽象實(shí)現(xiàn),可以很方便地支持不同的業(yè)務(wù)場(chǎng)景,并對(duì)一些特定的業(yè)務(wù)場(chǎng)景進(jìn)行優(yōu)化。

Bulkload全量導(dǎo)入的場(chǎng)景主要是用于動(dòng)態(tài)推薦以及用戶畫像。用戶畫像主要是T+1的數(shù)據(jù),在沒(méi)有使用Bulkload以前,主要是通過(guò)Hive來(lái)逐條寫入,數(shù)據(jù)鏈路很長(zhǎng),每天全量導(dǎo)入10億條數(shù)據(jù)大概需要6、7個(gè)小時(shí)。使用Bulkload之后,只需要在hive離線平臺(tái)把數(shù)據(jù)構(gòu)建成一個(gè)rocksdb引擎,hive離線平臺(tái)再把數(shù)據(jù)上傳到對(duì)象存儲(chǔ)。上傳完成之后通知KV來(lái)進(jìn)行拉取,拉取完成后就可以進(jìn)行本地的Bulkload,時(shí)間可以縮短到10分鐘以內(nèi)。

另一個(gè)場(chǎng)景就是定長(zhǎng)list。大家可能發(fā)現(xiàn)你的播放歷史只有3000條,動(dòng)態(tài)也只有3000條。因?yàn)闅v史記錄是非常大的,不能無(wú)限存儲(chǔ)。最早是通過(guò)一個(gè)腳本,對(duì)歷史數(shù)據(jù)進(jìn)行刪除,為了解決這個(gè)問(wèn)題,我們開發(fā)了一個(gè)定制化引擎,保存一個(gè)定長(zhǎng)的list,用戶只需要往里面寫入,當(dāng)超過(guò)定長(zhǎng)的長(zhǎng)度時(shí),引擎會(huì)自動(dòng)刪除。

2. 面臨問(wèn)題——存儲(chǔ)引擎

前面提到的compaction,在實(shí)際使用的過(guò)程中,也碰到了一些問(wèn)題,主要是存儲(chǔ)引擎和raft方面的問(wèn)題。存儲(chǔ)引擎方面主要是Rocksdb的問(wèn)題。第一個(gè)就是數(shù)據(jù)淘汰,在數(shù)據(jù)寫入的時(shí)候,會(huì)通過(guò)不同的Compaction往下推。我們的播放歷史,會(huì)設(shè)置一個(gè)過(guò)期時(shí)間。超過(guò)了過(guò)期時(shí)間之后,假設(shè)數(shù)據(jù)現(xiàn)在位于L3層,在L3層沒(méi)滿的時(shí)候是不會(huì)觸發(fā)Compaction的,數(shù)據(jù)也不會(huì)被刪除。為了解決這個(gè)問(wèn)題,我們就設(shè)置了一個(gè)定期的Compaction,在Compaction的時(shí)候回去檢查這個(gè)Key是否過(guò)期,過(guò)期的話就會(huì)把這條數(shù)據(jù)刪除。

另一個(gè)問(wèn)題就是DEL導(dǎo)致SCAN慢查詢的問(wèn)題。因?yàn)長(zhǎng)SM進(jìn)行delete的時(shí)候要一條一條地掃,有很多key。比如20-40之間的key被刪掉了,但是LSM刪除數(shù)據(jù)的時(shí)候不會(huì)真正地進(jìn)行物理刪除,而是做一個(gè)delete的標(biāo)識(shí)。刪除之后做SCAN,會(huì)讀到很多的臟數(shù)據(jù),要把這些臟數(shù)據(jù)過(guò)濾掉,當(dāng)delete非常多的時(shí)候,會(huì)導(dǎo)致SCAN非常慢。為了解決這個(gè)問(wèn)題,主要用了兩個(gè)方案。第一個(gè)就是設(shè)置刪除閾值,超過(guò)閾值的時(shí)候,會(huì)強(qiáng)制觸發(fā)Compaction,把這些delete標(biāo)識(shí)的數(shù)據(jù)刪除掉。但是這樣也會(huì)產(chǎn)生寫放大的問(wèn)題,比如有L1層的數(shù)據(jù)進(jìn)行了刪除,刪除的時(shí)候會(huì)觸發(fā)一個(gè)Compaction,L1的文件會(huì)帶上一整層的L2文件進(jìn)行Compaction,這樣會(huì)帶來(lái)非常大的寫放大的問(wèn)題。為了解決寫放大,我們加入了一個(gè)延時(shí)刪除,在SCAN的時(shí)候,會(huì)統(tǒng)計(jì)一個(gè)指標(biāo),記錄當(dāng)前刪除的數(shù)據(jù)占所有數(shù)據(jù)的比例,根據(jù)這個(gè)反饋值去觸發(fā)Compaction。

第三個(gè)是大Value寫入放大的問(wèn)題,目前業(yè)內(nèi)的解決辦法都是通過(guò)KV存儲(chǔ)分離來(lái)實(shí)現(xiàn)的。我們也是這樣解決的。

3. 面臨問(wèn)題——Raft

圖片?

Raft層面的問(wèn)題有兩個(gè):

首先,我們的Raft是三副本,在一個(gè)副本掛掉的情況下,另外兩個(gè)副本可以提供服務(wù)。但是在極端情況下,超過(guò)半數(shù)的副本掛掉,雖然概率很低,但是我們還是做了一些操作,在故障發(fā)生的時(shí)候,縮短系統(tǒng)恢復(fù)的時(shí)間。我們采用的方法就是降副本,比如三個(gè)副本掛了兩個(gè),會(huì)通過(guò)后臺(tái)的一個(gè)腳本將集群自動(dòng)降為單副本模式,這樣依然可以正常提供服務(wù)。同時(shí)會(huì)在后臺(tái)啟動(dòng)一個(gè)進(jìn)程對(duì)副本進(jìn)行恢復(fù),恢復(fù)完成后重新設(shè)置為多副本模式,大大縮短了故障恢復(fù)時(shí)間。

另一個(gè)是日志刷盤問(wèn)題。比如點(diǎn)贊、動(dòng)態(tài)的場(chǎng)景,value其實(shí)非常小,但是吞吐量非常高,這種場(chǎng)景會(huì)帶來(lái)很嚴(yán)重的寫放大問(wèn)題。我們用磁盤,默認(rèn)都是4k寫盤,如果每次的value都是幾十個(gè)字節(jié),這樣會(huì)造成很大的磁盤浪費(fèi)?;谶@樣的問(wèn)題,我們會(huì)做一個(gè)聚合刷盤,首先會(huì)設(shè)置一個(gè)閾值,當(dāng)寫入多少條,或者寫入量超過(guò)多少k,進(jìn)行批量刷盤,這個(gè)批量刷盤可以使吞吐量提升2~3倍。

04 總結(jié)思考

圖片?

1. 應(yīng)用

應(yīng)用方面,我們會(huì)做KV與緩存的融合。因?yàn)闃I(yè)務(wù)開發(fā)不太了解KV與緩存資源的情況,融合之后就不需要再去考慮是使用KV還是緩存。

另一個(gè)應(yīng)用方面的改進(jìn)是支持Sentinel模式,進(jìn)一步降低副本成本。

2. 運(yùn)維

運(yùn)維方面,一個(gè)問(wèn)題就是慢節(jié)點(diǎn)檢測(cè),我們可以檢測(cè)到故障節(jié)點(diǎn),但是慢節(jié)點(diǎn)怎么檢測(cè)呢,目前在業(yè)界也是一個(gè)難題,也是我們今后要努力的方向。

另一個(gè)問(wèn)題就是自動(dòng)剔盤均衡,磁盤發(fā)生故障后,目前的方法是第二天看一些報(bào)警事項(xiàng),再人工操作一下。我們希望做成一個(gè)自動(dòng)化機(jī)制。

3. 系統(tǒng)

系統(tǒng)層面就是SPDK、DPDK方面的性能優(yōu)化,通過(guò)這些優(yōu)化,進(jìn)一步提升KV進(jìn)程的吞吐。

責(zé)任編輯:張燕妮 來(lái)源: DataFunTalk
相關(guān)推薦

2016-01-12 14:59:40

分布式存儲(chǔ)分布式存儲(chǔ)架構(gòu)

2022-07-18 10:29:33

數(shù)據(jù)分布式系統(tǒng)

2022-07-15 09:41:09

分布式系統(tǒng)技術(shù)棧

2017-10-27 08:40:44

分布式存儲(chǔ)剪枝系統(tǒng)

2018-08-08 10:32:55

分布式集群存儲(chǔ)

2018-06-08 08:46:14

RaftPaxos系統(tǒng)

2018-10-24 11:01:53

分布式存儲(chǔ)系統(tǒng)

2024-08-12 16:20:27

2015-05-12 13:03:54

開源分布式存儲(chǔ)HDFS

2022-03-15 09:10:00

分布式訓(xùn)練實(shí)踐

2023-02-28 12:12:21

語(yǔ)音識(shí)別技術(shù)解碼器

2021-10-30 19:30:23

分布式Celery隊(duì)列

2022-04-12 15:53:24

存儲(chǔ)緩存分布式

2023-02-28 07:01:11

分布式緩存平臺(tái)

2018-02-22 08:42:04

分布式存儲(chǔ)安全

2021-10-22 05:42:38

分布式存儲(chǔ)三副本系統(tǒng)

2018-10-29 12:51:35

分布式存儲(chǔ)元數(shù)據(jù)

2022-03-21 19:44:30

CitusPostgreSQ執(zhí)行器

2015-07-02 13:26:35

分布式存儲(chǔ)云存儲(chǔ)云平臺(tái)

2024-09-27 09:19:30

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)