經常使用Feed流架構實現

業務中不少需求都會用到相似feed流的架構。
例如數據庫

  • 微信朋友圈
  • 微博
  • 動態
  • 1對N消息。

通常feed流的架構實現有下面幾種。
假如如今的業務場景是微博,而後當前的數據狀況是:後端

用戶A關注了用戶B和C,用戶D關注了用戶B
用戶B發了微博A,B,用戶C發了微博C,D微信

1. 拉

數據表架構

  • 微博表(字段有:微博ID,微博內容,發佈人)

代碼邏輯:性能

  1. 用戶 B發佈微博接口,插入記錄到微博表,只有一行記錄
  2. 用戶A獲取我關注的用戶的微博接口:
    1. 獲取當前登陸用戶關注的用戶,例如A關注的用戶B和C
    2. 獲取B和C發佈的全部微博,
    3. 按時間倒序排列,分頁,返回

優缺點:優化

  • 實現簡單
  • 空間佔用較少,一條微博只用一條數據庫記錄
  • 數據量大的狀況下, 第2個接口查詢較慢(須要用臨時表,並且查詢數據較多)

2.推

數據表code

  • 微博表(字段有:微博ID,微博內容,發佈人)
  • feed流表(字段有:微博ID,發佈時間,接收人)

代碼邏輯:索引

  1. 發佈微博接口
    1. 插入記錄到微博表
    2. 獲取當前用戶粉絲用戶列表,假如當前用戶是B,那就是獲取A和D
    3. 插入2行記錄到feed流表
      1. 接收人=A,微博ID=剛纔的微博表ID
      2. 接收人=B,微博ID=剛纔的微博表ID
  2. 用戶A獲取我關注的用戶的微博接口:
    1. 查詢feed流表,找到接收人=A的記錄,按發佈時間倒序排,分頁,返回

優缺點:接口

  • 實現較複雜
  • 空間佔用較多,一條微博須要插入1+N條記錄(N是粉絲用戶數)。若是N是幾十w或者幾百w,對數據庫壓力很是大,包括空間佔用,插入或刪除耗時,索引創建等。
  • 第2個接口能夠用索引,因此查詢很快,。

3.推+拉

上面兩種方案都有優缺點,當對讀的要求很高,同時用戶粉絲數很大,就要想辦法優化,推+拉是其中一種方案。
具體方法是區分用戶:產品

  • 對於常常讀取的用戶,採用推方案,保證讀取的性能
  • 對於不常讀取的用戶,採用拉方案,下降存儲壓力

從產品的角度看,有不少種方法能夠區分用戶是否屬於常常讀,這裏提供其中一個可行的方案:

4. 區分活躍用戶的推+拉

數據表

  • 微博表(字段有:微博ID,微博內容,發佈人)
  • feed流表(字段有:微博ID,發佈時間,接收人)
  • 活躍用戶表(字段有:用戶ID,是否活躍,最新登陸時間)

代碼邏輯:

  1. 發佈微博接口
    1. 插入記錄到微博表
    2. 獲取當前用戶活躍粉絲用戶列表,假如當前用戶是B,那就是獲取A和D,其中A是活躍用戶,D是非活躍,那就只獲取A。SQL能夠用exists,例如:select * from fans where exists (select * from 活躍表 where 是否活躍=1)
    3. 插入1行記錄到feed流表(D不是活躍用戶,就不插入了)
      1. 接收人=A,微博ID=剛纔的微博表ID
  2. 用戶A獲取我關注的用戶的微博接口:
    1. 查詢feed流表,找到接收人=A的記錄,按發佈時間倒序排,分頁,返回
  3. APP啓動接口(每次APP啓動,發送一個請求到後端)
    1. 若是用戶是活躍用戶,更新用戶最新登陸時間
    2. 若是不是,經過拉方式爲用戶補發feed流:
      1. 獲取用戶全部關注的用戶
      2. 獲取這些用戶發的微博
      3. 把這些微博ID插入到用戶的feed流表(要避免重複插入)
  4. 定時任務
    1. 天天把最新登陸時間小於1天前的用戶,設置爲非活躍

優缺點:

  • 第2個接口能夠用索引,因此查詢很快。
  • 數據庫壓力下降。由於通常粉絲中活躍用戶只有小部分,同時補發的時候,能夠只補發最新的N條微博,進一步節省空間,固然這些要和產品經理制定好規則。
  • 邏輯較複雜
  • 由於補發feed流須要必定時間,因此這期間用戶只能拉到舊的微博

5.總結

  • 若是想簡單作,並且對讀取要求不高,用拉方式就能夠了
  • 若是對讀取要求高,同時粉絲數很少,例如朋友圈,最多就幾千個朋友,建議用推方式
  • 若是粉絲數不少,例如微博,動輒幾十萬到幾千萬粉絲的,建議用推+拉方式

未經容許,請不要轉載

相關文章
相關標籤/搜索