業務中很多需求都會用到類似feed流的架構。
例如
- 微信朋友圈
- 微博
- 動態
- 1對N消息。
一般feed流的架構實現有下面幾種。
假如現在的業務場景是微博,然后當前的數據情況是:
用戶A關注了用戶B和C,用戶D關注了用戶B
用戶B發了微博A,B,用戶C發了微博C,D
1. 拉
數據表
- 微博表(字段有:微博ID,微博內容,發布人)
代碼邏輯:
- 用戶 B發布微博接口,插入記錄到微博表,只有一行記錄
- 用戶A獲取我關注的用戶的微博接口:
- 獲取當前登錄用戶關注的用戶,例如A關注的用戶B和C
- 獲取B和C發布的所有微博,
- 按時間倒序排列,分頁,返回
優缺點:
- 實現簡單
- 空間占用較少,一條微博只用一條數據庫記錄
- 數據量大的情況下, 第2個接口查詢較慢(需要用臨時表,而且查詢數據較多)
2.推
數據表
- 微博表(字段有:微博ID,微博內容,發布人)
- feed流表(字段有:微博ID,發布時間,接收人)
代碼邏輯:
- 發布微博接口
- 插入記錄到微博表
- 獲取當前用戶粉絲用戶列表,假如當前用戶是B,那就是獲取A和D
- 插入2行記錄到feed流表
- 接收人=A,微博ID=剛才的微博表ID
- 接收人=B,微博ID=剛才的微博表ID
- 用戶A獲取我關注的用戶的微博接口:
- 查詢feed流表,找到接收人=A的記錄,按發布時間倒序排,分頁,返回
優缺點:
- 實現較復雜
- 空間占用較多,一條微博需要插入1+N條記錄(N是粉絲用戶數)。如果N是幾十w或者幾百w,對數據庫壓力非常大,包括空間占用,插入或刪除耗時,索引建立等。
- 第2個接口可以用索引,所以查詢很快,。
3.推+拉
上面兩種方案都有優缺點,當對讀的要求很高,同時用戶粉絲數很大,就要想辦法優化,推+拉是其中一種方案。
具體方法是區分用戶:
- 對於經常讀取的用戶,采用推方案,保證讀取的性能
- 對於不常讀取的用戶,采用拉方案,降低存儲壓力
從產品的角度看,有很多種方法可以區分用戶是否屬於經常讀,這里提供其中一個可行的方案:
4. 區分活躍用戶的推+拉
數據表
- 微博表(字段有:微博ID,微博內容,發布人)
- feed流表(字段有:微博ID,發布時間,接收人)
- 活躍用戶表(字段有:用戶ID,是否活躍,最新登錄時間)
代碼邏輯:
-
發布微博接口
- 插入記錄到微博表
- 獲取當前用戶活躍粉絲用戶列表,假如當前用戶是B,那就是獲取A和D,其中A是活躍用戶,D是非活躍,那就只獲取A。SQL可以用exists,例如:
select * from fans where exists (select * from 活躍表 where 是否活躍=1)
- 插入1行記錄到feed流表(D不是活躍用戶,就不插入了)
- 接收人=A,微博ID=剛才的微博表ID
-
用戶A獲取我關注的用戶的微博接口:
- 查詢feed流表,找到接收人=A的記錄,按發布時間倒序排,分頁,返回
-
APP啟動接口(每次APP啟動,發送一個請求到后端)
- 如果用戶是活躍用戶,更新用戶最新登錄時間
- 如果不是,通過拉方式為用戶補發feed流:
- 獲取用戶所有關注的用戶
- 獲取這些用戶發的微博
- 把這些微博ID插入到用戶的feed流表(要避免重復插入)
-
定時任務
- 每天把最新登錄時間小於1天前的用戶,設置為非活躍
優缺點:
- 第2個接口可以用索引,所以查詢很快。
- 數據庫壓力降低。因為一般粉絲中活躍用戶只有小部分,同時補發的時候,可以只補發最新的N條微博,進一步節省空間,當然這些要和產品經理制定好規則。
- 邏輯較復雜
- 因為補發feed流需要一定時間,所以這期間用戶只能拉到舊的微博
5.總結
- 如果想簡單做,而且對讀取要求不高,用拉方式就可以了
- 如果對讀取要求高,同時粉絲數不多,例如朋友圈,最多就幾千個朋友,建議用推方式
- 如果粉絲數很多,例如微博,動輒幾十萬到幾千萬粉絲的,建議用推+拉方式
未經允許,請不要轉載