微博feed系統(tǒng)的push和pull模式和時(shí)間分區(qū)拉模式架構(gòu)探討
sns系統(tǒng),微博系統(tǒng)都應(yīng)用到了feed(每條微博或者sns里的新鮮事等我們稱作feed)系統(tǒng),不管是twitter.com或者國(guó)內(nèi)的新浪微博,人人網(wǎng)等,在各種技術(shù)社區(qū),技術(shù)大會(huì)上都在分享自己的feed架構(gòu),也就是推拉模式(timyang上次也分享了新浪微薄的模式)。下面我們就微博的feed推拉(push,pull)模式做一下探討,并提出新的時(shí)間分區(qū)拉模式。
眾所周知,在微博中,當(dāng)你發(fā)表一篇微博,那么所有關(guān)注你的followers(粉絲)都會(huì)在一定的時(shí)間內(nèi)收到你的微薄,這有點(diǎn)像群發(fā)一封郵件,所有的抄送者都會(huì)在一定的時(shí)間內(nèi)收到。到這里,你可能覺得沒有什么難度。我們看下下面的截圖:
圖一:新浪微博姚晨
圖二:twitter上馮大輝
新浪微博的姚晨粉絲有2594751,她發(fā)表任何一篇微博,都需要2594751個(gè)粉絲在一定的時(shí)間內(nèi)收到,twitter的馮大輝發(fā)表一篇的話,需要19868個(gè)followers收到。
相反,姚晨需要收到他關(guān)注的545個(gè)人的所有更新,馮大輝需要收到他關(guān)注的2525個(gè)人的所有更新。到這里,你是不是感覺到有那么一點(diǎn)點(diǎn)小挑戰(zhàn)呢?
下面我們看下微博一般的整體結(jié)構(gòu)圖:
圖三:微博整體結(jié)構(gòu)
圖中展示了微博的整體數(shù)據(jù)流程,先了解下整體的數(shù)據(jù)結(jié)構(gòu),沒有涉及到followers等的推拉模式處理。下面我們?cè)倏聪峦颇J剑╬ush):
圖四:推模式結(jié)構(gòu)
推模式需要把一篇微博推送給所有關(guān)注他的人(推給所有的粉絲),比如姚晨,我們就需要推送給2594751個(gè)用戶的feeds表中。當(dāng)然,feeds表可以很好的進(jìn)行sharding,存儲(chǔ)也都是一些數(shù)字型的字段,存儲(chǔ)空間可能不是很大,用戶在查詢自己關(guān)注的所有人的feed時(shí),速度快,性能非常高,但是推送量會(huì)非常大,姚晨發(fā)表一篇,就會(huì)產(chǎn)生200多萬條數(shù)據(jù)。試想,一個(gè)大量用戶的微薄系統(tǒng)通過使用推模式,是不是會(huì)產(chǎn)生非常驚人的數(shù)據(jù)呢?
下面看下拉模式(pull)
圖五:拉模式
拉模式只需要用戶發(fā)表微博時(shí),存儲(chǔ)一條微博數(shù)據(jù)到feeds表中(feeds表可以是一個(gè)臨時(shí)表,只保存近期可接受范圍的數(shù)據(jù)).用戶每次查詢feed時(shí)都會(huì)去查詢feeds表。比如姚晨打開自己的微薄首頁(yè),就產(chǎn)生:SELECT id FROM feeds where uid in(following uid list) ORDER BY id DESC LIMIT n(查詢最新的n條),緩存到memcached
uidlist=>{data:id list,timeline:上次查詢出來的最新的一條數(shù)據(jù)的時(shí)間}
再次刷新:SELECT id FROM feeds where uid in(following uid list) AND timeline>(memcached存儲(chǔ)的上次的timeline) ORDER BY id DESC LIMIT n
這種模式實(shí)現(xiàn)起來也是比較簡(jiǎn)單和容易的,只是在查詢的時(shí)候需要多考慮下緩存的結(jié)構(gòu)。但是feeds表會(huì)產(chǎn)生很大的壓力,怎么說feeds表也要保存最近十天半個(gè)月的數(shù)據(jù)吧,對(duì)于一個(gè)大點(diǎn)的系統(tǒng),這會(huì)產(chǎn)生比較大的數(shù)據(jù),如果following的人數(shù)比較多,數(shù)據(jù)庫(kù)的壓力就會(huì)非常大。而且一般在線的用戶,客戶端都會(huì)定期掃描,又會(huì)增加很大的壓力,這在查詢性能上沒有推模式的效率高。
下面我們?cè)趯?duì)拉模式做一下改進(jìn)優(yōu)化
圖五:拉模式(pull)-改進(jìn)(時(shí)間分區(qū)拉模式)
拉模式的改進(jìn)主要是在feeds的存儲(chǔ)上,使用按照時(shí)間進(jìn)行分區(qū)存儲(chǔ)。分為最近時(shí)間段(比如最近一個(gè)小時(shí)),近期的,比較長(zhǎng)時(shí)期等等。我們?cè)賮砜聪虏樵兊牧鞒?,比如姚晨登陸微博首?yè),假設(shè)緩存中沒有任何數(shù)據(jù),那么我們可以查詢比較長(zhǎng)時(shí)期的feeds表,然后進(jìn)入緩存。下一次查詢,通過查詢緩存中的數(shù)據(jù)的timeline,如果timeline還在最近一個(gè)小時(shí)內(nèi),那么只需要查詢最近一個(gè)小時(shí)的數(shù)據(jù)的feed表,最近一個(gè)小時(shí)的feeds表比圖四的feeds表可要小很多,查詢起來速度肯定快幾個(gè)數(shù)量級(jí)了。
改進(jìn)模式的重點(diǎn)在于feeds的時(shí)間分區(qū)存儲(chǔ),根據(jù)上次查詢的timeline來決定查詢應(yīng)該落在那個(gè)表。一般情況下,經(jīng)常在線的用戶,頻繁使用的客戶端掃描操作,經(jīng)常登錄的用戶,都會(huì)落在最近的feeds表區(qū)間,查詢都是比較高效的。只有那些十天,半個(gè)月才登錄一次的用戶需要去查詢比較長(zhǎng)時(shí)間的feeds大表,一旦查詢過了,就又會(huì)落在最近時(shí)間區(qū)域,所以效率也是非常高的。
關(guān)于時(shí)間的分區(qū),需要根據(jù)數(shù)據(jù)量,用戶訪問特點(diǎn)進(jìn)行一個(gè)合理的切分。如果數(shù)據(jù)發(fā)表量非常大,可以進(jìn)行更多的分區(qū)。
上面介紹的推模式和拉模式都有各自的特點(diǎn),個(gè)人覺得時(shí)間分區(qū)拉模式彌補(bǔ)了圖四的拉模式的很大的不足,是一個(gè)成本比較低廉的解決方案。當(dāng)然,時(shí)間分區(qū)拉模式也可以結(jié)合推模式,根據(jù)某些特點(diǎn)來增加系統(tǒng)的性能。
后記:本文的目的是介紹時(shí)間分區(qū)拉模式,本人對(duì)新浪微博和twitter等的推拉模式的細(xì)節(jié)并不清楚。
[文章作者:孫立 鏈接:http://www.cnblogs.com/sunli/
- 目前還沒評(píng)論,等你發(fā)揮!