小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

日訪問(wèn)量百億級(jí)的應(yīng)用如何做緩存架構(gòu)設(shè)計(jì)

 xujin3 2018-06-17

中生代技術(shù)

全文:5588字28圖

閱讀時(shí)間:14分鐘

接力技術(shù),鏈接價(jià)值

-----------------------------------------------------

鏈接3000+技術(shù)總監(jiān)/CTO, 每天早上推送技術(shù)干貨文章

微博日活躍用戶1.6億+,每日訪問(wèn)量達(dá)百億級(jí),面對(duì)龐大用戶群的海量訪問(wèn),良好架構(gòu)且不斷改進(jìn)的緩存體系具有非常重要的支撐作用。

4月21日,中生代技術(shù)走進(jìn)盒子科技的現(xiàn)場(chǎng)技術(shù)交流活動(dòng)上,新浪微博技術(shù)專家陳波為大家講解了微博Cache架構(gòu)的設(shè)計(jì)實(shí)踐過(guò)程。

刷微博嗎?跟我們一起聽(tīng)聽(tīng)那些龐大的數(shù)據(jù)是如何呈現(xiàn)的吧!

陳波:大家好,今天的分享主要有以下內(nèi)容,首先是微博在運(yùn)行過(guò)程中的數(shù)據(jù)挑戰(zhàn),然后是Feed系統(tǒng)架構(gòu),接下來(lái)會(huì)著重分析Cache架構(gòu)及演進(jìn),最后是總結(jié)、展望。

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


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


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

1. Feed timeline

大家日常刷微博的時(shí)候,比如在主站或客戶端點(diǎn)一下刷新,最新獲得了十到十五條微博,它這個(gè)是怎么構(gòu)建出來(lái)的呢?刷新之后,首先會(huì)獲得用戶的關(guān)注關(guān)系,比如她有一千個(gè)關(guān)注,會(huì)把這一千個(gè)ID拿到,根據(jù)這一千個(gè)UID,拿到每個(gè)用戶發(fā)表的一些微博,同時(shí)會(huì)獲取這個(gè)用戶的Inbox,就是她收到的特殊的一些消息,比如分組的一些微博,群的微博,下面她的關(guān)注關(guān)系,她關(guān)注人的微博列表,拿到這一系列微博列表之后進(jìn)行集合、排序,拿到所需要的那些ID,再對(duì)這些ID去取每一條微博ID對(duì)應(yīng)的微博內(nèi)容,如果這些微博是轉(zhuǎn)發(fā)過(guò)來(lái)的,它還有一個(gè)原微博,會(huì)進(jìn)一步取原微博內(nèi)容,通過(guò)原微博取用戶信息,進(jìn)一步根據(jù)用戶的過(guò)濾詞,對(duì)這些微博進(jìn)行過(guò)濾,過(guò)濾掉用戶不想看到的微博,留下這些微博后,再進(jìn)一步來(lái)看,用戶對(duì)這些微博有沒(méi)有收藏、贊,做一些flag設(shè)置,最后還會(huì)對(duì)這些微博各種計(jì)數(shù),轉(zhuǎn)發(fā)、評(píng)論、贊數(shù)進(jìn)行組裝,最后才把這十幾條微博返回給用戶的各種端。這樣看,用戶一次請(qǐng)求,最終得到十幾條記錄,后端服務(wù)器大概要對(duì)幾百甚至幾千條數(shù)據(jù)進(jìn)行實(shí)時(shí)組裝,再返回給用戶,整個(gè)過(guò)程對(duì)Cache體系強(qiáng)度依賴。所以Cache架構(gòu)設(shè)計(jì)優(yōu)劣直接會(huì)影響到微博體系表現(xiàn)的好壞。

2. Feed Cache架構(gòu)

然后我們看一下Cache架構(gòu),它主要分為6層,首先是Inbox,主要是分組的一些微博,然后直接對(duì)群主的一些微博,Inbox比較少,主要是推的方式。然后對(duì)于Outbox,每個(gè)用戶都會(huì)發(fā)常規(guī)的微博,都會(huì)在它Outbox里面去,根據(jù)存的ID的數(shù)量,實(shí)際上分成多個(gè)Cache,普通的大概是200多,如果是長(zhǎng)的大概是2000條。第三組就是一些關(guān)系,它的關(guān)注、粉絲、用戶。第四個(gè)就是內(nèi)容,每一條微博一些內(nèi)容存在這里。下面就是一些存在性判斷,比如微博里面,這條微博有沒(méi)有贊過(guò),之前有一些明星就說(shuō)我沒(méi)有點(diǎn)贊這條微博怎么顯示我點(diǎn)贊了,引發(fā)一些新聞,這種就是記錄,實(shí)際上她在某個(gè)時(shí)候點(diǎn)贊忘記了。最下面還有比較大的一塊——計(jì)數(shù)。一條微博評(píng)論轉(zhuǎn)發(fā)等計(jì)數(shù),對(duì)用戶來(lái)說(shuō),她的關(guān)注數(shù)粉絲數(shù)這些數(shù)據(jù)。

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

1. 簡(jiǎn)單KV數(shù)據(jù)類型

接下來(lái)我們著重講一些微博Cache架構(gòu)演進(jìn)過(guò)程,最開(kāi)始微博上線的時(shí)候,都是把它作為一個(gè)簡(jiǎn)單的KV證人數(shù)據(jù)類型來(lái)存儲(chǔ),我們主要采取哈希分片存儲(chǔ)在MC池子里,上線幾個(gè)月之后發(fā)現(xiàn)一些問(wèn)題,有一些節(jié)點(diǎn)機(jī)器宕機(jī)或者其它方面原因,大量的請(qǐng)求會(huì)穿透Cache層達(dá)到DB上去,導(dǎo)致整個(gè)請(qǐng)求變慢,甚至DB僵死。于是我們很快給它改造增加一個(gè)HA層,這樣即便Main層出現(xiàn)某些節(jié)點(diǎn)宕機(jī)情況或者掛掉之后,這些請(qǐng)求會(huì)進(jìn)一步穿透到HA層,不會(huì)穿透DB層,這樣的話可以保證在任何情況下,整個(gè)系統(tǒng)命中率不會(huì)降低,系統(tǒng)服務(wù)穩(wěn)定性比較大提升。對(duì)于這種,現(xiàn)在業(yè)界用得比較多,然后很多人說(shuō)我直接用哈希,但這里面也有一些坑,比如我有一個(gè)節(jié)點(diǎn),節(jié)點(diǎn)3它宕機(jī)了,Main把它給摘掉了,節(jié)點(diǎn)3的一些QA分給其他幾個(gè)節(jié)點(diǎn),這個(gè)業(yè)務(wù)量還不是很大,穿透DB,DB可以抗住。如果后面這個(gè)節(jié)點(diǎn)3又恢復(fù)了,它又加進(jìn)來(lái),加進(jìn)來(lái)之后,節(jié)點(diǎn)3的訪問(wèn)又會(huì)回來(lái),如果節(jié)點(diǎn)3因?yàn)榫W(wǎng)絡(luò)原因或者機(jī)器本身的原因,它又宕機(jī)了,一些節(jié)點(diǎn)3的請(qǐng)求又會(huì)分給其他節(jié)點(diǎn),這個(gè)時(shí)候就會(huì)出現(xiàn)問(wèn)題,之前分散給其他節(jié)點(diǎn)寫回來(lái)的數(shù)據(jù)已經(jīng)沒(méi)有人更新了,如果它沒(méi)有被剔除掉就會(huì)出現(xiàn)混插數(shù)據(jù)。

微博和微信很大的區(qū)別,實(shí)際上微博是一個(gè)廣場(chǎng)型的業(yè)務(wù),比如突發(fā)事件,某明星找個(gè)女朋友,瞬間流量就30%,突發(fā)事件后,大量的請(qǐng)求會(huì)出現(xiàn)在某一些節(jié)點(diǎn),會(huì)導(dǎo)致這個(gè)節(jié)點(diǎn)非常熱,即便是MC也沒(méi)辦法滿足這么大的請(qǐng)求量。這時(shí)候整個(gè)MC就會(huì)變成瓶頸,導(dǎo)致整個(gè)系統(tǒng)變慢,基于這個(gè)原因我們引入L1層,還是一個(gè)Main關(guān)系池,每一個(gè)L1大概是Main層的N分之一,六分之一、八分之一、十分之一這樣一個(gè)內(nèi)存量,根據(jù)請(qǐng)求量我會(huì)增加4到8個(gè)L1,這樣所有的請(qǐng)求來(lái)了之后首先會(huì)訪問(wèn)L1,L1命中的話就會(huì)直接訪,如果沒(méi)有命中再來(lái)訪問(wèn)Main-HA層,這樣在一些突發(fā)流量的時(shí)候,可以由L1來(lái)抗住大部分熱的請(qǐng)求。對(duì)微博本身來(lái)說(shuō),新的數(shù)據(jù)就會(huì)越熱,只用增加很少一部分內(nèi)存就會(huì)抗住更大的量。

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

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

剛才講到簡(jiǎn)單的QA數(shù)據(jù),對(duì)于復(fù)雜的集合類數(shù)據(jù)怎么來(lái)處理,比如我關(guān)注了2000人,新增一個(gè)人,這就涉及到部分修改。有一種方式把2000個(gè)ID全部拿下來(lái)進(jìn)行修改,這種對(duì)帶寬、機(jī)器壓力會(huì)更大。還有一些分頁(yè)獲取,我存了2000個(gè),只需要取其中的第幾頁(yè),比如第二頁(yè),也就是第十到第二十個(gè),能不能不要全量把所有數(shù)據(jù)取回去。還有一些資源的聯(lián)動(dòng)計(jì)算,會(huì)計(jì)算到我關(guān)注的某些人里面ABC也關(guān)注了用戶D,這種涉及到部分?jǐn)?shù)據(jù)的修改、獲取,包括計(jì)算,對(duì)MC來(lái)說(shuō)它實(shí)際上是不太擅長(zhǎng)的。各種關(guān)注關(guān)系都存在Redis里面取,通過(guò)Hash分布、儲(chǔ)存,一組多存的方式來(lái)進(jìn)行讀寫分離。現(xiàn)在Redis的內(nèi)存大概有30個(gè)T,每天都有2-3萬(wàn)億的請(qǐng)求。

在使用Redis的過(guò)程中實(shí)際上還是遇到其他一些問(wèn)題,比如從關(guān)注關(guān)系,我關(guān)注了2000個(gè)UID,有一種方式是全量存儲(chǔ),但微博有大量的用戶,有些用戶登陸比較少,有些用戶特別活躍,這樣全部放在內(nèi)存里面成本開(kāi)銷是比較大的。所以我們就把Redis使用改成Cache,比如只存活躍的用戶,如果你最近一段時(shí)間沒(méi)有活躍之后,會(huì)把你從Redis里面踢掉,再次有訪問(wèn)到你的時(shí)候把你加進(jìn)來(lái)。這時(shí)候存在一個(gè)問(wèn)題,Redis工作機(jī)制是單線程模式,如果它加某一個(gè)UV,關(guān)注2000個(gè)用戶,可能擴(kuò)展到兩萬(wàn)個(gè)UID,兩萬(wàn)個(gè)UID塞回去基本上Redis就卡住了,沒(méi)辦法提供其他服務(wù)。所以我們擴(kuò)展一種新的數(shù)據(jù)結(jié)構(gòu),兩萬(wàn)個(gè)UID直接開(kāi)了端,寫的時(shí)候直接依次把它寫到Redis里面去,讀寫的整個(gè)效率就會(huì)非常高,它的實(shí)現(xiàn)是一個(gè)long型的開(kāi)放數(shù)組,通過(guò)Double Hash進(jìn)行尋址。

對(duì)Redis來(lái)說(shuō)我們進(jìn)行了一些其他的擴(kuò)展,之前的一些分享,大家在網(wǎng)上也會(huì)看到,把數(shù)據(jù)放到公共變量里面,整個(gè)升級(jí)過(guò)程,我們測(cè)試1G的話加載要10分鐘,10G大概要十幾分鐘以上,現(xiàn)在是毫秒級(jí)升級(jí)。對(duì)于AOF,我們采用滾動(dòng)的AOF,每個(gè)AOF是帶一個(gè)ID的,達(dá)到一定的量再滾動(dòng)到下一個(gè)AOF里面去。對(duì)RDB落地的時(shí)候,我們會(huì)記錄構(gòu)建這個(gè)RDB時(shí),AOF文件以及它所在的位置,通過(guò)新的RDB、AOF擴(kuò)展模式,實(shí)現(xiàn)全增量復(fù)制。

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

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

4. 計(jì)數(shù)器-Counter Service

最初是可以采取Memcached,但它有個(gè)問(wèn)題,如果計(jì)數(shù)超過(guò)它內(nèi)容容量的時(shí)候,它會(huì)導(dǎo)致一些計(jì)數(shù)的剔除,宕機(jī)或重啟后計(jì)數(shù)就沒(méi)有了。另外可能有很多計(jì)數(shù)它是為零,那這個(gè)時(shí)候怎么存,要不要存,存的話就占很多內(nèi)存。微博每天上十億的計(jì)數(shù),光存0都要占大量的內(nèi)存,如果不存又會(huì)導(dǎo)致穿透到DB里面去,對(duì)服務(wù)的可溶性就會(huì)存在影響。2010年之后我們又采用Redis訪問(wèn),隨著數(shù)據(jù)量越來(lái)越大之后,發(fā)現(xiàn)Redis內(nèi)存有效負(fù)荷還是比較低的,它一條KV大概需要至少65個(gè)字節(jié),但實(shí)際上我們一個(gè)計(jì)數(shù)需要8個(gè)字節(jié),然后Value大概4個(gè)字節(jié),實(shí)際上有效只有12個(gè)字節(jié),其他還有四十多個(gè)字節(jié)都是被浪費(fèi)掉的,這還只是單個(gè)KV,如果一條Key有多個(gè)計(jì)數(shù)的情況下,它就浪費(fèi)得更多了,比如說(shuō)四個(gè)計(jì)數(shù),一個(gè)Key8個(gè)字節(jié),四個(gè)計(jì)數(shù)每個(gè)計(jì)數(shù)是4個(gè)字節(jié),16個(gè)字節(jié)大概需要26個(gè)字節(jié)就行了。但是用Redis存大概需要200多個(gè)字節(jié)。后來(lái)通過(guò)自己研發(fā)Counter Service,內(nèi)存降至Redis的五分之一到十五分之一以下,而且進(jìn)行冷熱分離,熱數(shù)據(jù)存在內(nèi)存里面,冷數(shù)據(jù)如果重新變熱,就把它放到LRU里面去。落地RDB、AOF,實(shí)現(xiàn)全增量復(fù)制,通過(guò)這種方式,熱數(shù)據(jù)單機(jī)可以存百億級(jí),冷數(shù)據(jù)可以存千億級(jí)。

整個(gè)存儲(chǔ)架構(gòu)大概是這樣子,上面是內(nèi)存,下面是SSD,在內(nèi)存里面是預(yù)先把它分成N個(gè)Table,每個(gè)Table根據(jù)ID的指針序列,劃出一定范圍,任何一個(gè)ID過(guò)來(lái)先找到它所在的Table,如果有直接對(duì)它增增減減,有新的計(jì)數(shù)過(guò)來(lái),發(fā)現(xiàn)內(nèi)存不夠的時(shí)候,就會(huì)把一個(gè)小的Table Dump到SSD里面去,留著新的位置放在最上面供新的ID來(lái)使用。有些人疑問(wèn)說(shuō),如果在某個(gè)范圍內(nèi),我的ID本來(lái)設(shè)的計(jì)數(shù)是4個(gè)字節(jié),但是微博特別熱,超過(guò)了4個(gè)字節(jié),變成很大的一個(gè)計(jì)數(shù)怎么處理,對(duì)于超過(guò)限制的把它放在Aux dict進(jìn)行存放,對(duì)于落在SSD里面的Table,我們有專門的IndAux進(jìn)行訪問(wèn),通過(guò)RDB方式進(jìn)行復(fù)制。

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

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

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

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

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

6. 小結(jié)

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

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

8. 服務(wù)化

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

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

總結(jié)與展望


最后簡(jiǎn)單總結(jié)一下,對(duì)于微博Cache架構(gòu)來(lái)說(shuō),從它數(shù)據(jù)架構(gòu)、性能、儲(chǔ)存成本、服務(wù)化不同方面進(jìn)行優(yōu)化增強(qiáng)。

<全文完>

編輯/雪人

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多