産品分析【轉載】
首先我們來看一下市場上關于消息的實作是怎麼樣的。
簡書
簡書的消息系統主要分了兩種
- 簡信
- 提醒
簡信簡信的性質其實跟私信是一樣的,是使用者發送給使用者的一則消息,有具體的資訊内容。

提醒而提醒,則是系統發送的一則消息,其文案格式是固定的,并且對特殊對象一般擁有超連結。
知乎
知乎跟簡書一樣,主要分了兩種:
- 私信
- 消息
私信跟簡書一樣,使使用者發送給使用者的一則消息,也可以是管理者發送給使用者的消息。
消息知乎的消息比簡書的提醒有過之而無不及,知乎會對多條相似的消息進行聚會,以達到減輕使用者閱讀壓力的體驗。
消息的三種分類
通過兩種産品的簡單分析,得出他們的消息有兩種分類,在這基礎上,我們再加上一種:公告。公告的主要性質是系統發送一則含有具體内容的消息,站内所有使用者都能讀取到這條消息。是以,消息有三種分類:
- 公告 Announce
- 提醒 Remind
- 私信 Message
提醒的語言分析
我們從簡書取一組提醒樣本:
- 3dbe1bd90774 關注了你
- magicdawn 喜歡了你的文章 《單點登入的三種實作方式》
- 無良程式 喜歡了你的文章 《基于RESTful API 怎麼設計使用者權限控制?》
- alexcc4 喜歡了你的文章 《在Nodejs中貫徹單元測試》
- 你在《基于RESTful API 怎麼設計使用者權限控制?》中收到一條 cnlinjie 的評論
- 你的文章《Session原理》已被加入專題 《ios開發》
分析句子結構,提醒的内容無非就是
「誰對一樣屬于誰的事物做了什麼操作」「someone do something in someone’s something」
someone = 提醒的觸發者,或者發送者,标記為senderdo something = 提醒的動作,評論、喜歡、關注都屬于一個動作,标記為actionsomething = 提醒的動作作用對象,這就具體到是哪一篇文章,标記為targetsomeone’s = 提醒的動作作用對象的所有者,标記為targetOwner
這就清楚了,sender和targetOwner就是網站的使用者,而target是具體到哪一篇文章,如果提醒的對象不僅僅局限于文章,還有其他的話,就需要增加一項targetType,來标記目标是文章還是其他的什麼。而action,則是固定的,整個網站會觸發提醒的動作可能就隻有那幾樣:評論、喜歡、關注…(或者其他業務需要提醒的動作)
消息的兩種擷取方式
- 推 Push
- 拉 Pull
以知乎為例推的比較常見,需要針對某一個問題維護着一張關注者的清單,每當觸發這個問題推送的條件時(例如有人回答問題),就把這個通知發送給每個關注者。
拉的相對麻煩一點,就是推的反向,例如每個使用者都有一張關注問題的清單,每當使用者上線的時候,對每個問題進行輪詢,當問題的事件清單出現了比我原本時間戳大的資訊就進行拉取。
而我們則根據消息的不同分類采用不同的擷取方式:通告和提醒,适合使用拉取的方式,消息産生之後,會存在消息表中,使用者在某一特定的時間根據自己關注問題的表進行消息的拉取,然後添加到自己的消息隊列中,
資訊,适合使用推的方式,在發送者建立一條資訊之後,同時指定接收者,把消息添加到接收者的消息隊列中。
訂閱
根據提醒使用拉取的方式,需要維護一個關注某一事物的清單。這種行為,我們稱之為:**「訂閱」Subscribe **
一則訂閱有以下三個核心屬性:
- 訂閱的目标 target
- 訂閱的目标類型 targetType
- 訂閱的動作 action
比如我釋出了一篇文章,那麼我會訂閱文章《XXX》的評論動作,是以文章《XXX》每被人評論了,就需要發送一則提醒告知我。
訂閱的規則還可以擴充我喜歡了一篇文章,和我釋出了一篇文章,訂閱的動作可能不一樣。喜歡了一篇文章,我希望我訂閱這篇文章更新、評論的動作。而釋出了一篇文章,我希望我隻是訂閱這篇文章的評論動作。
這時候就需要多一個參數:subscribReason不同的subscribReason,對應着一個動作數組,subscribReason = 喜歡,對應着 actions = [更新,評論]subscribReason = 釋出,對應着 actions = [評論]
訂閱的規則還還可以擴充使用者可能會有一個自己的訂閱設定,比如對于所有的喜歡的動作,我都不希望接收。比如Knewone的提醒設定<img src=“http://xia-dev.b0.upaiyun.com/80cc4aaf-0568-478c-8513-b8821e57520f.jpg” alt=“Knewone提醒設定” width=“500”>
是以我們需要再維護一個表:SubscriptionConfig,來存放使用者的提醒設定。并且,當使用者沒有提醒設定的時候,可以使用系統提供的一套預設設定:defaultSubscriptionConfig
聚合
如果我釋出了一篇文章《XXX》,在我不線上的時候,被評論了10遍,當我一上線的時候,應該是收到十條資訊類似于:「誰誰誰評論了你的文章《XXX》」?還是應該收到一條資訊:「甲、乙、丙、丁…評論了你的文章《XXX》」?
知乎在聚合上做的很優秀,要知道他們要實作這個還是挺有技術的:知乎的消息機制,在技術上如何設計與規劃?網站的消息(通知)系統一般是如何實作的?
關于這部分功能,我們還沒有具體的實作方法,暫時也無法講得更加詳細。⊙﹏⊙
五個實體
通過上面的分析,大概知道做這個消息系統,需要哪些實體類:
- 使用者消息隊列 UserNotify
- 使用者 User
- 訂閱 Subscription
- 訂閱設定 SubscriptionConfig
- 消息 Notify
- 通告 Announce
- 提醒 Remind
- 資訊 Message
行為分解
說了這麼多,整理一下整個消息流程的一些行為:
- 系統或者管理者,建立消息
- createNotify (make announce | remind | message)
- 使用者,訂閱消息,取消訂閱
- subscribe, cancelSubscription
- 使用者管理訂閱設定
- getSubscriptionConfig, updateSubscriptionConfig
- 使用者,拉取消息
- pullNotify (pull announce | remind | message | all)
- 使用者,查詢消息隊列
- getUserNotify(get announce | remind | message | all)
- 使用者閱讀消息
- read
在本文的「下篇」我們來探讨一下:模型怎麼做、資料庫怎麼設計、代碼結構怎麼來、一些邏輯上的時序圖應該是怎麼樣的。
---------------------- 更新于 2015/11/15 -----------------------
關聯文章:消息系統設計與實作「下篇」