微信產(chǎn)品經(jīng)理面試題:朋友圈是如何設(shè)置信息圍欄的?
而在權(quán)限管理上,微信采用了給用戶打「標(biāo)簽」來進(jìn)行分組,這個(gè)標(biāo)簽的分組與微信通訊錄一致。在數(shù)據(jù)上,就是給每個(gè)關(guān)系增加一個(gè)「標(biāo)簽」標(biāo)記。這里需要注意的是,雖然微信的關(guān)系在產(chǎn)品使用上給用戶是雙向的(即互相關(guān)注),但是在存儲(chǔ)的時(shí)候,是給互相關(guān)的兩個(gè)用戶分別建立了關(guān)系數(shù)據(jù),也就是每個(gè)人獨(dú)有自己的一份「通訊錄」。這通過刪除了自己的好友之后,自己并不從別人的通訊錄刪除就可以看得出來。標(biāo)簽分組的基礎(chǔ)數(shù)據(jù)就是這樣了,這也是后面朋友圈權(quán)限管理的基礎(chǔ)。
對(duì)于個(gè)人朋友圈 timeline 所能看到的消息,按照一般的邏輯是先獲取所有朋友的消息,然后剔除掉沒有授權(quán)給自己看的消息、剔除掉自己屏蔽的用戶消息,然后才得到自己當(dāng)前看到的 timeline。如果是這樣的邏輯的話,等于每次刷新朋友圈,都要跑到所有的消息池里面去找到上述通訊錄中朋友們的消息,還要對(duì)找到的每條消息去判斷用戶是否有權(quán)限閱讀。這顯然是效率低下的方式,更何況微信是這么大的一個(gè)訪問量和數(shù)據(jù)量。所以,這種數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)是行不通的了。
一般邏輯下朋友圈每次讀取的過程
利用零散時(shí)間進(jìn)行關(guān)系計(jì)算
解決這種性能問題一般的思路就是把需要大計(jì)算量的過程分散到平時(shí)零散的時(shí)間去做。在這里的思路就是:平時(shí)就把每個(gè)用戶需要的 timeline 數(shù)據(jù)按照權(quán)限設(shè)置準(zhǔn)備好,等到用的時(shí)候(刷新朋友圈)就直接讀取準(zhǔn)備好的內(nèi)容。那么答案就出來了:除了存儲(chǔ)一份上面講到的文字,圖片等基本信息外,還需要給每個(gè)用戶存儲(chǔ)一份 timeline 數(shù)據(jù),注意,是每個(gè)用戶一份。當(dāng)然,這里的「每份」不需要存儲(chǔ)完整信息,只需要存儲(chǔ)消息的 ID 和時(shí)間(可能需要)。每個(gè)人刷新自己的朋友圈時(shí),讀取自己的那份數(shù)據(jù)就行了,既不用去消息池子里面篩選,也不用判斷用戶權(quán)限。
那是怎么實(shí)現(xiàn)權(quán)限控制呢?
新消息產(chǎn)生新權(quán)限
當(dāng)一個(gè)用戶發(fā)布一條消息時(shí)會(huì)按照上面講的標(biāo)簽設(shè)置相關(guān)的權(quán)限,服務(wù)器就會(huì)給每個(gè)有權(quán)限接收這條消息的用戶的 timeline 中寫入這條消息。也就是在用戶發(fā)布的這一刻,就做好了權(quán)限安排,而不是等到讀取的時(shí)候。這樣就自然減少了讀取的時(shí)候的計(jì)算量,提高了效率。
發(fā)布時(shí)進(jìn)行權(quán)限控制(示意圖,實(shí)際比這復(fù)雜)
至于分庫(kù)分表這些就不展開了,知道有這么回事就行。有時(shí)候這種技術(shù)上的設(shè)計(jì)也是會(huì)限制產(chǎn)品的設(shè)計(jì)。
那怎么證明上面說的合理呢?
感興趣的同學(xué)可以去測(cè)試下:先發(fā)一條帶閱讀權(quán)限的消息,比如允許某個(gè)標(biāo)簽的人看。然后再給這個(gè)標(biāo)簽添加一個(gè)新人。結(jié)果是這個(gè)新人是看不到這條消息的,因?yàn)闄?quán)限劃分是在發(fā)布的時(shí)候就劃分好了,新人加入標(biāo)簽的時(shí)間是在發(fā)布之后,所以沒法獲得這條消息的權(quán)限分配機(jī)會(huì),雖然他后來在標(biāo)簽組中,但是仍然沒有辦法看到這條消息。
作為一個(gè)微信設(shè)計(jì)的旁觀者,以上答案是作為一個(gè)用戶從系統(tǒng)分析的角度去考慮的,并不代表微信確實(shí)是這樣的一個(gè)設(shè)計(jì)思路,但答案中的方案已經(jīng)盡可能做到了可以驗(yàn)證。答案中也沒有涉及到具體的技術(shù),僅僅是一個(gè)系統(tǒng)分析的思路。