自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

微博應(yīng)對日訪問量百億級的緩存架構(gòu)設(shè)計

開發(fā) 架構(gòu)
微博日活躍用戶1.6億+,每日訪問量達(dá)百億級,面對龐大用戶群的海量訪問,良好的架構(gòu)且不斷改進(jìn)的緩存體系具有非常重要的支撐作用。本文將由新浪微博技術(shù)專家陳波老師,跟大家詳細(xì)講解那些龐大的數(shù)據(jù)都是如何呈現(xiàn)的。

微博日活躍用戶1.6億+,每日訪問量達(dá)百億級,面對龐大用戶群的海量訪問,良好的架構(gòu)且不斷改進(jìn)的緩存體系具有非常重要的支撐作用。本文將由新浪微博技術(shù)專家陳波老師,跟大家詳細(xì)講解那些龐大的數(shù)據(jù)都是如何呈現(xiàn)的。

本文大綱

1、微博在運(yùn)行過程中的數(shù)據(jù)挑戰(zhàn)

2、Feed平臺系統(tǒng)架構(gòu)

3、Cache架構(gòu)及演進(jìn)

4、總結(jié)與展望

數(shù)據(jù)挑戰(zhàn)

Feed平臺系統(tǒng)架構(gòu)

Feed平臺系統(tǒng)架構(gòu)總共分為五層,最上面是端層,比如web端、客戶端、大家用的IOS或安卓的一些客戶端,還有一些開放平臺、第三方接入的一些接口;下一層是平臺接入層,不同的池子,主要是為了把好的資源集中調(diào)配給重要的核心接口,這樣遇到突發(fā)流量的時候,就有更好的彈性來服務(wù),提高服務(wù)穩(wěn)定性。再下面是平臺服務(wù)層,主要是Feed算法、關(guān)系等等。接下來是中間層,通過各種中間介質(zhì)提供一些服務(wù)。最下面一層就是存儲層。

1、Feed Timeline

大家日常刷微博的時候,比如在主站或客戶端點一下刷新,***獲得了十到十五條微博,這是怎么構(gòu)建出來的呢?

刷新之后,首先會獲得用戶的關(guān)注關(guān)系。比如他有一千個關(guān)注,會把這一千個ID拿到,再根據(jù)這一千個UID,拿到每個用戶發(fā)表的一些微博。同時會獲取這個用戶的Inbox,就是他收到的特殊的一些消息,比如分組的一些微博、群的微博、下面的關(guān)注關(guān)系、關(guān)注人的微博列表。

拿到這一系列微博列表之后進(jìn)行集合、排序,拿到所需要的那些ID,再對這些ID去取每一條微博ID對應(yīng)的微博內(nèi)容。如果這些微博是轉(zhuǎn)發(fā)過來的,它還有一個原微博,會進(jìn)一步取原微博內(nèi)容。通過原微博取用戶信息,進(jìn)一步根據(jù)用戶的過濾詞對這些微博進(jìn)行過濾,過濾掉用戶不想看到的微博。

根據(jù)以上步驟留下的微博,會再進(jìn)一步來看,用戶對這些微博有沒有收藏、點贊,做一些flag設(shè)置,還會對這些微博各種計數(shù),轉(zhuǎn)發(fā)、評論、贊數(shù)進(jìn)行組裝,***才把這十幾條微博返回給用戶的各種端。

這樣看來,用戶一次請求得到的十幾條記錄,后端服務(wù)器大概要對幾百甚至幾千條數(shù)據(jù)進(jìn)行實時組裝,再返回給用戶,整個過程對Cache體系強(qiáng)度依賴,所以Cache架構(gòu)設(shè)計優(yōu)劣會直接影響到微博體系表現(xiàn)的好壞。

2、Feed Cache架構(gòu)

接下來我們看一下Cache架構(gòu),它主要分為六層。首先***層是Inbox,主要是分組的一些微博,然后直接對群主的一些微博。Inbox比較少,主要是推的方式。

然后對于第二層的Outbox,每個用戶都會發(fā)常規(guī)的微博,都會在它的Outbox里面去。根據(jù)存的ID數(shù)量,實際上分成多個Cache,普通的大概是200多條,如果長的大概是2000條。

第三層是一些關(guān)系,它的關(guān)注、粉絲、用戶。

第四層是內(nèi)容,每一條微博一些內(nèi)容存在這里。

第五層就是一些存在性判斷,比如某條微博我有沒有贊過。之前有一些明星就說我沒有點贊這條微博怎么顯示我點贊了,引發(fā)了一些新聞。而這種就是記錄,實際上她有在某個時候點贊過但可能忘記了。

最下面還有比較大的一層——計數(shù),每條微博的評論、轉(zhuǎn)發(fā)等計數(shù),還有用戶的關(guān)注數(shù)、粉絲數(shù)這些數(shù)據(jù)。

Cache架構(gòu)及演進(jìn)

1、簡單KV數(shù)據(jù)類型

接下來我們著重講一下微博的Cache架構(gòu)演進(jìn)過程。最開始微博上線時,我們是把它作為一個簡單的KV數(shù)據(jù)類型來存儲。我們主要采取哈希分片存儲在MC池子里,上線幾個月之后發(fā)現(xiàn)一些問題:有一些節(jié)點機(jī)器宕機(jī)或是其它原因,大量的請求會穿透Cache層達(dá)到DB上去,導(dǎo)致整個請求變慢,甚至DB僵死。

于是我們很快進(jìn)行了改造,增加了一個HA層,這樣即便Main層出現(xiàn)某些節(jié)點宕機(jī)情況或者掛掉之后,這些請求會進(jìn)一步穿透到HA層,不會穿透到DB層。這樣可以保證在任何情況下,整個系統(tǒng)***率不會降低,系統(tǒng)服務(wù)穩(wěn)定性有了比較大的提升。

對于這種做法,現(xiàn)在業(yè)界用得比較多,然后很多人說我直接用哈希,但這里面也有一些坑。比如我有一個節(jié)點,節(jié)點3宕機(jī)了,Main把它給摘掉,節(jié)點3的一些QA分給其他幾個節(jié)點,這個業(yè)務(wù)量還不是很大,穿透DB,DB還可以抗住。但如果這個節(jié)點3恢復(fù)了,它又加進(jìn)來之后,節(jié)點3的訪問就會回來,稍后節(jié)點3因為網(wǎng)絡(luò)原因或者機(jī)器本身的原因,它又宕機(jī)了,一些節(jié)點3的請求又會分給其他節(jié)點。這個時候就會出現(xiàn)問題,之前分散給其他節(jié)點寫回來的數(shù)據(jù)已經(jīng)沒有人更新了,如果它沒有被剔除掉就會出現(xiàn)混插數(shù)據(jù)。

實際上微博是一個廣場型的業(yè)務(wù),比如突發(fā)事件,某明星找個女朋友,瞬間流量就30%了。突發(fā)事件后,大量的請求會出現(xiàn)在某一些節(jié)點,會導(dǎo)致這些節(jié)點非常熱,即便是MC也沒辦法滿足這么大的請求量。這時MC就會變成瓶頸,導(dǎo)致整個系統(tǒng)變慢。

基于這個原因,我們引入了L1層,還是一個Main關(guān)系池,每一個L1大概是Main層的N分之一,六分之一、八分之一、十分之一這樣一個內(nèi)存量,根據(jù)請求量我會增加4到8個L1,這樣所有請求來了之后首先會訪問L1。L1***的話就會直接訪問,如果沒有***再來訪問Main-HA層,這樣在一些突發(fā)流量的時候,可以由L1來抗住大部分熱的請求。對微博本身來說,新的數(shù)據(jù)就會越熱,只要增加很少一部分內(nèi)存就會抗住更大的量。

簡單總結(jié)一下,通過簡單KV數(shù)據(jù)類型的存儲,我們實際上以MC為主的,層內(nèi)HASH節(jié)點不漂移,Miss穿透到下一層去讀取。通過多組L1讀取性能提升,能夠抗住峰值、突發(fā)流量,而且成本會大大降低。對讀寫策略,采取多寫,讀的話采用逐層穿透,如果Miss的話就進(jìn)行回寫。對存在里面的數(shù)據(jù),我們最初采用Json/xml,2012年之后就直接采用Protocol Buffer格式,對一些比較大的用QuickL進(jìn)行壓縮。

2、集合類數(shù)據(jù)

剛才講到簡單的QA數(shù)據(jù),那對于復(fù)雜的集合類數(shù)據(jù)怎么來處理?

比如我關(guān)注了2000人,新增一個人,就涉及到部分修改。有一種方式是把2000個ID全部拿下來進(jìn)行修改,但這種對帶寬、機(jī)器壓力會很大。還有一些分頁獲取,我存了2000個,只需要取其中的第幾頁,比如第二頁,也就是第十到第二十個,能不能不要全量把所有數(shù)據(jù)取回去。還有一些資源的聯(lián)動計算,會計算到我關(guān)注的某些人里面ABC也關(guān)注了用戶D。這種涉及到部分?jǐn)?shù)據(jù)的修改、獲取,包括計算,對MC來說實際上是不太擅長的。

各種關(guān)注關(guān)系都存在Redis里面取,通過Hash分布、儲存,一組多存的方式來進(jìn)行讀寫分離。現(xiàn)在Redis的內(nèi)存大概有30個T,每天都有2-3萬億的請求。

在使用Redis的過程中,實際上還是遇到其他一些問題。比如從關(guān)注關(guān)系,我關(guān)注了2000個UID,有一種方式是全量存儲,但微博有大量的用戶,有些用戶登陸得比較少,有些用戶特別活躍,這樣全部放在內(nèi)存里成本開銷是比較大的。所以我們就把Redis使用改成Cache,比如只存活躍的用戶,如果你最近一段時間沒有活躍,會把你從Redis里踢掉,再次有訪問的時候再把你加進(jìn)來。

這時存在一個問題,因為Redis工作機(jī)制是單線程模式,如果它加某一個UV,關(guān)注2000個用戶,可能擴(kuò)展到兩萬個UID,兩萬個UID塞回去基本上Redis就卡住了,沒辦法提供其他服務(wù)。所以我們擴(kuò)展一種新的數(shù)據(jù)結(jié)構(gòu),兩萬個UID直接開了端,寫的時候直接依次把它寫到Redis里面去,讀寫的整個效率就會非常高。它的實現(xiàn)是一個long型的開放數(shù)組,通過Double Hash進(jìn)行尋址。

我們對Redis進(jìn)行了一些其他的擴(kuò)展,大家可能也在網(wǎng)上看到過我們之前的一些分享,把數(shù)據(jù)放到公共變量里面,整個升級過程,我們測試1G的話加載要10分鐘,10G大概要十幾分鐘以上,現(xiàn)在是毫秒級升級。

對于AOF,我們采用滾動的AOF,每個AOF是帶一個ID的,達(dá)到一定的量再滾動到下一個AOF里去。對RDB落地的時候,我們會記錄構(gòu)建這個RDB時,AOF文件以及它所在的位置,通過新的RDB、AOF擴(kuò)展模式,實現(xiàn)全增量復(fù)制。

3、其他數(shù)據(jù)類型-計數(shù)

接下來還有一些其他的數(shù)據(jù)類型,比如一個計數(shù),實際上計數(shù)在每個互聯(lián)網(wǎng)公司都可能會遇到,對一些中小型的業(yè)務(wù)來說,實際上MC和Redis足夠用的,但在微博里計數(shù)出現(xiàn)了一些特點:單條Key有多條計數(shù),比如一條微博,有轉(zhuǎn)發(fā)數(shù)、評論數(shù),還有點贊;一個用戶有粉絲數(shù)、關(guān)注數(shù)等各種各樣的數(shù)字。因為是計數(shù),它的Value size是比較小的,根據(jù)它的各種業(yè)務(wù)場景,大概就是2-8個字節(jié),一般4個字節(jié)為多,然后每日新增的微博大概十億條記錄,總記錄就更可觀了,然后一次請求,可能幾百條計數(shù)要返回去。

4、計數(shù)器-Counter Service

最初是可以采取Memcached,但它有個問題,如果計數(shù)超過它內(nèi)容容量時,會導(dǎo)致一些計數(shù)的剔除,宕機(jī)或重啟后計數(shù)就沒有了。另外可能有很多計數(shù)它為零,那這個時候怎么存,要不要存,存的話就占很多內(nèi)存。微博每天上十億的計數(shù),光存0都要占大量的內(nèi)存,如果不存又會導(dǎo)致穿透到DB里去,對服務(wù)的可溶性會存在影響。

2010年之后我們又采用Redis訪問,隨著數(shù)據(jù)量越來越大之后,發(fā)現(xiàn)Redis內(nèi)存有效負(fù)荷還是比較低的,它一條KV大概需要至少65個字節(jié),但實際上我們一個計數(shù)需要8個字節(jié),然后Value大概4個字節(jié),所以有效只有12個字節(jié),還有四十多個字節(jié)都是被浪費掉的。這還只是單個KV,如果在一條Key有多個計數(shù)的情況下,它就浪費得更多了。比如說四個計數(shù),一個Key 8個字節(jié),四個計數(shù)每個計數(shù)是4個字節(jié),16個字節(jié)大概需要26個字節(jié)就行了,但是用Redis存大概需要200多個字節(jié)。

后來我們通過自己研發(fā)的Counter Service,內(nèi)存降至Redis的五分之一到十五分之一以下,而且進(jìn)行冷熱分離,熱數(shù)據(jù)存在內(nèi)存里,冷數(shù)據(jù)如果重新變熱,就把它放到LRU里去。落地RDB、AOF,實現(xiàn)全增量復(fù)制,通過這種方式,熱數(shù)據(jù)單機(jī)可以存百億級,冷數(shù)據(jù)可以存千億級。

整個存儲架構(gòu)大概是上圖這樣,上面是內(nèi)存,下面是SSD,在內(nèi)存里是預(yù)先把它分成N個Table,每個Table根據(jù)ID的指針序列,劃出一定范圍。任何一個ID過來先找到它所在的Table,如果有直接對它增增減減,有新的計數(shù)過來,發(fā)現(xiàn)內(nèi)存不夠的時候,就會把一個小的Table Dump到SSD里去,留著新的位置放在最上面供新的ID來使用。

有些人疑問說,如果在某個范圍內(nèi),我的ID本來設(shè)的計數(shù)是4個字節(jié),但是微博特別熱,超過了4個字節(jié),變成很大的一個計數(shù)怎么處理?對于超過限制的,我們把它放在Aux dict進(jìn)行存放,對于落在SSD里的Table,我們有專門的IndAux進(jìn)行訪問,通過RDB方式進(jìn)行復(fù)制。

5、其他數(shù)據(jù)類型-存在性判斷

除了計數(shù),微博還有一些業(yè)務(wù),一些存在性判斷。比如一條微博展現(xiàn)的,有沒有點贊、閱讀、推薦,如果這個用戶已經(jīng)讀過這個微博了,就不要再顯示給他。這種有一個很大的特點,它檢查是否存在,每條記錄非常小,比如Value1個bit就可以了,但總數(shù)據(jù)量巨大。比如微博每天新發(fā)表微博1億左右,讀的可能有上百億、上千億這種總的數(shù)據(jù)需要判斷。怎么來存儲是個很大的問題,而且這里面很多存在性就是0。還是前面說的,0要不要存?如果存了,每天就存上千億的記錄;如果不存,那大量的請求最終會穿透Cache層到DB層,任何DB都沒辦法抗住那么大的流量。

我們也進(jìn)行了一些選型,首先直接考慮能不能用Redis。單條KV 65個字節(jié),一個KV可以8個字節(jié)的話,Value只有1個bit,這樣算下來每日新增內(nèi)存有效率是非常低的。第二種我們新開發(fā)的Counter Service,單條KV Value1個bit,我就存1個byt,總共9個byt就可以了。這樣每日新增內(nèi)存900G,存的話可能就只能存***若干天的,存?zhèn)€三天差不多快3個T了,壓力也挺大,但比Redis已經(jīng)好很多。

我們最終方案是自己開發(fā)Phantom,先采用把共享內(nèi)存分段分配,最終使用的內(nèi)存只用120G就可以。算法很簡單,對每個Key可以進(jìn)行N次哈希,如果哈希的某一個位它是1,那么進(jìn)行3次哈希,三個數(shù)字把它設(shè)為1。把X2也進(jìn)行三次哈希,后面來判斷X1是否存在的時候,從進(jìn)行三次哈希來看,如果都為1就認(rèn)為它是存在的,如果某一個哈希X3,它的位算出來是0,那就***肯定是不存在的。

它的實現(xiàn)架構(gòu)比較簡單,把共享內(nèi)存預(yù)先拆分到不同Table里,在里面進(jìn)行開方式計算,然后讀寫,落地的話采用AOF+RDB的方式進(jìn)行處理。整個過程因為放在共享內(nèi)存里面,進(jìn)程要升級重啟數(shù)據(jù)也不會丟失。對外訪問的時候,建Redis協(xié)議,它直接擴(kuò)展新的協(xié)議就可以訪問我們這個服務(wù)了。

6、小結(jié)

[[231695]]

小結(jié)一下,到目前為止,我們關(guān)注了Cache集群內(nèi)的高可用、擴(kuò)展性、組件高性能,還有一個特別重要就是存儲成本,還有一些我們沒有關(guān)注到的,比如運(yùn)維性如何,微博現(xiàn)在已經(jīng)有幾千差不多上萬臺服務(wù)器等。

7、進(jìn)一步優(yōu)化

8、服務(wù)化

采取的方案首先就是對整個Cache進(jìn)行服務(wù)化管理,對配置進(jìn)行服務(wù)化管理,避免頻繁重啟,另外如果配置發(fā)生變更,直接用一個腳本修改一下。

 

 

服務(wù)化還引入Cluster Manager,實現(xiàn)對外部的管理,通過一個界面來進(jìn)行管理,可以進(jìn)行服務(wù)校驗。服務(wù)治理方面,可以做到擴(kuò)容、縮容,SLA也可以得到很好的保障。另外,對于開發(fā)來說,現(xiàn)在就可以屏蔽Cache資源。

總結(jié)與展望

 

***簡單總結(jié)一下,對于微博Cache架構(gòu)來說,我們從它的數(shù)據(jù)架構(gòu)、性能、儲存成本、服務(wù)化等不同方面進(jìn)行了優(yōu)化增強(qiáng)。歡迎對此有研究或有疑問的同行們留言,跟我們一起探討。 

責(zé)任編輯:龐桂玉 來源: DBAplus社群
相關(guān)推薦

2018-06-08 09:48:52

緩存架構(gòu)設(shè)計

2019-10-28 11:00:37

RedisMySQL數(shù)據(jù)庫

2017-04-01 09:04:54

docker自動化

2019-10-31 09:32:58

Redis微博緩存

2018-05-21 09:15:06

Redis美團(tuán)點評數(shù)據(jù)庫運(yùn)維

2018-01-30 14:26:49

監(jiān)控應(yīng)用性能管理運(yùn)維管理

2018-05-17 10:10:17

架構(gòu)設(shè)計優(yōu)化

2018-05-28 08:20:12

服務(wù)器Redis優(yōu)化

2022-07-17 06:54:51

Eureka架構(gòu)

2024-05-06 08:43:00

2025-02-26 07:20:07

2017-11-25 19:11:45

微服務(wù)架構(gòu)設(shè)計

2011-06-19 12:12:12

網(wǎng)站瀏覽量訪問量

2023-06-05 08:17:03

2012-06-07 10:53:08

架構(gòu)設(shè)計數(shù)據(jù)訪問層設(shè)計原則

2016-12-05 08:46:07

緩存架構(gòu)設(shè)計

2012-09-19 13:46:37

存儲存儲設(shè)計快速表態(tài)

2013-12-30 10:33:43

訪問量12306癱瘓

2018-05-06 16:33:52

微信朋友圈實踐

2019-02-12 09:34:00

微博短視頻架構(gòu)
點贊
收藏

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