業務中不少需求都會用到相似feed流的架構。
例如數據庫
通常feed流的架構實現有下面幾種。
假如如今的業務場景是微博,而後當前的數據狀況是:後端
用戶A關注了用戶B和C,用戶D關注了用戶B
用戶B發了微博A,B,用戶C發了微博C,D微信
1. 拉
數據表架構
代碼邏輯:性能
- 用戶 B發佈微博接口,插入記錄到微博表,只有一行記錄
- 用戶A獲取我關注的用戶的微博接口:
- 獲取當前登陸用戶關注的用戶,例如A關注的用戶B和C
- 獲取B和C發佈的全部微博,
- 按時間倒序排列,分頁,返回
優缺點:優化
- 實現簡單
- 空間佔用較少,一條微博只用一條數據庫記錄
- 數據量大的狀況下, 第2個接口查詢較慢(須要用臨時表,並且查詢數據較多)
2.推
數據表code
- 微博表(字段有:微博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.總結
- 若是想簡單作,並且對讀取要求不高,用拉方式就能夠了
- 若是對讀取要求高,同時粉絲數很少,例如朋友圈,最多就幾千個朋友,建議用推方式
- 若是粉絲數不少,例如微博,動輒幾十萬到幾千萬粉絲的,建議用推+拉方式
未經容許,請不要轉載