如果你應聘微信產品經理,怎么回答這道面試題?
問題源自知乎問題,感興趣可以知乎搜索「關于微信的產品面試題,產品經理來答答?」,我從中選取了一個問題,加了一點自己的思考,發出來探討一下。
朋友圈的基本數據結構設計是怎么樣的?既能做到完美的閱讀權限設置,又能兼顧性能?
題目本身給出了兩個重點,「閱讀權限」和「性能」,考察產品經理思考問題的全面性和對技術的了解程度。
首先梳理一下朋友圈的幾個功能特點:
- (0)基礎存儲功能,可發布視頻、鏈接、純文本、圖文消息。
- (1)異步發布,即時用戶交互行為反饋。在網絡情況較差時可以先提交任務(如發布朋友圈、點贊、評論),無需等待任務完成。
- (2)可選擇部分用戶可見,也就是題目中說到的權限。
- (3)對某些用戶可見的權限,除了用戶主動選擇的,還有系統層面的過濾器,比如某些違反微信運營規定的活動鏈接可被系統限制在朋友圈中傳播(也就是你發了之后只有你自己能看到,別人看不到)
- (4)新消息通知主動push,無需刷新界面,新消息可自動push;新朋友圈需要刷新才能看到。
問題(0)和(1)與閱讀權限設置沒有多大關系,與性能有一點點關系,但并不是本文討論的重點。這個面試題我們可以圍繞「閱讀權限」和「性能」這兩個基本點,對(2)、(3)、(4)三個點進行探討。
回答問題(2)時,我們可以從微信提供的功能上找到一些設置閱讀權限的蛛絲馬跡。
1)互為好友關系,是好友關系才能看到對方朋友圈,這是第一前提。
微信的朋友與朋友之間的關系雖然是雙向的,如A和B要成為朋友,A需要給B發送好友申請,當B通過A的申請時A才能看到B的朋友圈。
此時,A與B雖然存在好友關系,但彼此有一份獨立的通訊錄,互不干擾。比如A把B從朋友圈刪除時,B會在A的通訊錄列表里消失,但A不會在B的通訊錄列表里消失,當B給A發信息時才能發現雙方已非友好關系。
2)不在黑名單內,才能給對方發送消息并且能看到對方的朋友圈。
黑名單是介于「關系正?!购汀竸h除」之間的一種關系,雙方的好友關系還被保留,比如A把B拉黑了,有如下表現:
B無法給A發送消息,也看不到對方朋友圈的任何內容。
因為A主動拉黑B,A可以看到B的歷史朋友圈,但看不到拉黑后更新的內容。
3)申請加為好友時,選擇「不讓他看我的朋友圈」開啟或關閉。
不讓看朋友圈是介于黑名單和正常關系之間的一個狀態,如果互相加為好友時,被選擇了「不讓看朋友圈」,你是不能看到對方朋友圈的更新的。
4)通訊錄朋友標簽化。
我們可以在微信提供的功能上找到「標簽」,這個標簽除了對朋友屬性進行標記(如你可以把某個微信聯系人標記為老板、同事)外,還可以在發布朋友圈時選擇帶某標簽的朋友可見或不可見。
微信基于此構建了朋友圈和通訊錄的權限體系,那在具體技術實現上是什么場景呢?
我認為,微信朋友圈的權限是在朋友關系和朋友圈內容有寫操作的時候進行下發的,也就是當用戶發布內容或對關系進行修改時,就會下發朋友圈的內容可見狀態,按照權限優先級分為三種下發情況:
- 非好友、黑名單關系是實時觸發的。一經修改,所有內容實時生效。
- 標簽關系也是實時觸發的,但不會因為修改標簽的動作而對已發布內容是否可見產生變化。比如你發了一條朋友圈,對打了標簽的A和B兩個好友可見,C當時還不在可見標簽內。發布完成之后修改C的標簽為可見,C仍然看不到這條朋友圈。除刪除狀態和取消點贊,朋友圈是不具備修改、編輯功能的。
- 對于違規的朋友圈內容,微信會限制內容在朋友圈傳播,這個限制是系統限制,是異步進行的。比如你發布了一個受限的鏈接,發布之后在很短的時間內(1-2分鐘內)朋友是可以看到這條鏈接的,但隨后這條鏈接馬上會被屏蔽,這樣異步處理的初衷大概是 “把部分復雜的但不是最高優先級的權限計算發送到閑散的客戶端或機器資源上去做”,保證核心的閱讀體驗不會受到影響。
以上便是一些權限處理上的策略,接下來我們來討論一下,用什么樣的技術手段或者存儲方式,來支持這些復雜的權限下發和閱讀權限控制。
在timeline(時間流)或feeds流的產品技術實現上常用到一個算法叫「混排算法」,顧名思義就是結合了一系列的影響因子,把用戶發布的狀態/信息 實時分發到好友關系鏈里,感興趣的朋友們可以使用谷歌學術搜索timelime cache等關鍵字自行檢索。
這些存儲計算使用的技術肯定不是我們平時說的數據庫,而多用一些分布式存儲、持久緩存技術作為工具,比如Memcached、Redis等。
我們大膽猜想微信朋友圈的實現也使用了Redis,或者類似Redis系統的Key-Value鍵值對存儲系統。
一條條的朋友圈狀態在用戶的權限列表里是以key-value的形式存在的,每個用戶的 timeline 是由一個 Redis list 來維護, Redis list 存放著經過上面權限策略過濾之后可見好友發布的朋友圈的 ID。每當一個用戶發布朋友圈時, 會把這條朋友圈的 ID 推到有權限閱讀的好友的timeline 中(也就是存儲到Redis list 里)。當用戶刷新自己的朋友圈時,只需要到自己的Redis list 里拉取到對應的朋友圈列表,然后再比對本地緩存,決定該朋友圈是否要顯示或重新請求。數據格式大概如下:#{user_id}/#{post_id}(發布朋友圈的用戶ID/該朋友圈的ID)”
Redis_List = [“10010/100111”, “10020/103111”, “10030/140111”, “100210/100786”, “100233/100444”]
同樣的,點贊數、評論數、自己是否點贊等與某條朋友圈的關系,也是存儲在Redis List里。
雖然朋友圈內容是不會變的,但是點贊數和評論數目可是實時變化的喲。每一條朋友圈都會要獲取這條動態獲得了多少贊、有多少條評論、自己是否點贊。而這三個屬性都是從 Redis 中讀取出來的。也就是說如果這個接口返回了 20 條動態的話, 我們需要調用20*3次= 60 次 Redis。這似乎也是不可以接受的,特別是有一些人好友比較多、互動比較頻繁的,有時候還需要主動給用戶推小紅點提醒有新消息更新,這些人所在的機器性能就會告急。
所以,微信的這道面試題提到了「性能」這個點。
這里,可以可以考慮使用時間戳來標記上一次動態更新的時間。比如,當用戶在發布新的朋友圈信息時,如果跟當前用戶有新的互動(比如回復了你的評論、給你點贊了),上一次更新的時間戳就會發生變化,并主動更新到用戶相關的各個Redis List里。當發現客戶端發現上次更新的時間戳和本地時間戳不一樣時,可以主動更新獲取信息,否則保持不動。
調整對象結構為 用戶ID=>[狀態,上次更新時間戳]
{ ‘10010’ => [‘200101′,’123453454’], ‘10011’ => [‘200102’, ‘12345345435’], ‘10021’ => [‘200103′,’12345345435’], ‘10031’ => [‘200104′,’12345345435’]}
額,講到這里,很多同學沒看懂?
看吧,產品經理懂一些技術還是好一點的吧。^_^
好了,以上是一位產品經理作為旁觀者對微信朋友圈數據結構設計的一些思考,希望對大家思考有所幫助。許久不寫技術文章,如有錯誤,歡迎留言指正。
本文系作者@歪 (微信公眾號:程序員和產品經理)授權發布,未經許可,不得轉載。
如果對方開了陌生人可以瀏覽10條朋友圈,有些內容還是可以看到的
后面基本上看不懂,尷尬
路過糾正一下:在微信平臺,非好友關系也能看到對方的朋友圈。這也是權限范圍的功能
發現看不懂,但學到了微信這種機制思想 ??
這是產品分享還是技術分享
沒看懂數據結構 講技術沒有多全面
你是開發轉產品吧,有點深奧。
果然任何一個牛逼的產品都不是簡單實現的??????
分析很深入很全面,微信的產品邏輯好深奧呀
1.
表示看不懂代碼,不明覺厲,厲害了,我的大神
贊一個,微信的產品邏輯恰到好處。不過后面的一部分有點炫技了
?? ?? ?? ??
留個腳印來看看
贊同,微信的緩存設計結構理念,有點類似新浪微博。嘗試一下看看,做個REDIS數據結構,來設計微信朋友圈。轉產品中,不過碼農的老本忘得快差不多了,哈哈
有點扯
1、這個點上怎么可能成為性能瓶頸?性能問題取決于實現模型,騰訊用的肯定是分布式計算,在服務端的鑒權如何會引起性能問題
2、這個點上關注的應該是權限的業務模型,不要零碎的場景化,而應該有一個貫穿始終的“權限主線”
我也覺得
厲害,數據結構都忘的差不多了
?? ?? ??