消息系統設計與實現「上篇」

原文連接:Bluesun | 消息系統設計與實現「上篇」ios

因爲文章篇幅較長,而做者精力有限,不但願這麼早就精盡人亡,故分紅上下篇來寫消息系統的設計與實現。上篇主要講的是一些概念,搞清楚咱們要作的這個消息系統的主要內容。而下篇主要講具體的實現,會包括架構設計,數據庫設計,業務流程詳細的實現等。git

整個系統的設計與實現,並不是我一人之力就能夠完成的。這其中是同事們你們一塊兒討論與商討的結果,而我只是把它細化,呈現出來。github

我只是一個會思考的idea搬運工。數據庫

產品分析

首先咱們來看一下市場上關於消息的實現是怎麼樣的。segmentfault

簡書

簡書的消息系統主要分了兩種數組

  • 簡信架構

  • 提醒數據庫設計

簡信
簡信的性質其實跟私信是同樣的,是用戶發送給用戶的一則消息,有具體的信息內容。ide

簡書簡信

提醒
而提醒,則是系統發送的一則消息,其文案格式是固定的,而且對特殊對象通常擁有超連接。
簡書提醒單元測試

知乎

知乎跟簡書同樣,主要分了兩種:

  • 私信

  • 消息

私信
跟簡書同樣,使用戶發送給用戶的一則消息,也能夠是管理員發送給用戶的消息。

消息
知乎的消息比簡書的提醒有過之而無不及,知乎會對多條類似的消息進行聚會,以達到減輕用戶閱讀壓力的體驗。

消息的三種分類

經過兩種產品的簡單分析,得出他們的消息有兩種分類,在這基礎上,咱們再加上一種:公告。
公告的主要性質是系統發送一則含有具體內容的消息,站內全部用戶都能讀取到這條消息。
因此,消息有三種分類:

  1. 公告 Announce

  2. 提醒 Remind

  3. 私信 Message

提醒的語言分析

咱們從簡書取一組提醒樣本:

  • 3dbe1bd90774 關注了你

  • magicdawn 喜歡了你的文章 《單點登陸的三種實現方式》

  • 無良程序 喜歡了你的文章 《基於RESTful API 怎麼設計用戶權限控制?》

  • alexcc4 喜歡了你的文章 《在Nodejs中貫徹單元測試》

  • 你在《基於RESTful API 怎麼設計用戶權限控制?》中收到一條 cnlinjie 的評論

  • 你的文章《Session原理》已被加入專題 《ios開發》

分析句子結構,提醒的內容無非就是

「誰對同樣屬於誰的事物作了什麼操做」

「someone do something in someone's something」

someone = 提醒的觸發者,或者發送者,標記爲sender
do something = 提醒的動做,評論、喜歡、關注都屬於一個動做,標記爲action
something = 提醒的動做做用對象,這就具體到是哪一篇文章,標記爲target
someone's = 提醒的動做做用對象的全部者,標記爲targetOwner

這就清楚了,sender和targetOwner就是網站的用戶,而target是具體到哪一篇文章,若是提醒的對象不只僅侷限於文章,還有其餘的話,就須要增長一項targetType,來標記目標是文章仍是其餘的什麼。而action,則是固定的,整個網站會觸發提醒的動做可能就只有那幾樣:評論、喜歡、關注.....(或者其餘業務須要提醒的動做)

消息的兩種獲取方式

  • 推 Push

  • 拉 Pull

以知乎爲例
推的比較常見,須要針對某一個問題維護着一張關注者的列表,每當觸發這個問題推送的條件時(例若有人回答問題),就把這個通知發送給每一個關注者。

拉的相對麻煩一點,就是推的反向,例如每一個用戶都有一張關注問題的列表,每當用戶上線的時候,對每一個問題進行輪詢,當問題的事件列表出現了比我本來時間戳大的信息就進行拉取。

而咱們則根據消息的不一樣分類採用不一樣的獲取方式
通告和提醒,適合使用拉取的方式,消息產生以後,會存在消息表中,用戶在某一特定的時間根據本身關注問題的表進行消息的拉取,而後添加到本身的消息隊列中,

信息,適合使用推的方式,在發送者創建一條信息以後,同時指定接收者,把消息添加到接收者的消息隊列中。

訂閱

根據提醒使用拉取的方式,須要維護一個關注某一事物的列表。
這種行爲,咱們稱之爲:「訂閱」Subscribe

一則訂閱有如下三個核心屬性

  • 訂閱的目標 target

  • 訂閱的目標類型 targetType

  • 訂閱的動做 action

好比我發佈了一篇文章,那麼我會訂閱文章《XXX》的評論動做,因此文章《XXX》每被人評論了,就須要發送一則提醒告知我。

訂閱的規則還能夠擴展
我喜歡了一篇文章,和我發佈了一篇文章,訂閱的動做可能不同。
喜歡了一篇文章,我但願我訂閱這篇文章更新、評論的動做。
而發佈了一篇文章,我但願我只是訂閱這篇文章的評論動做。

這時候就須要多一個參數:subscribReason
不一樣的subscribReason,對應着一個動做數組,
subscribReason = 喜歡,對應着 actions = [更新,評論]
subscribReason = 發佈,對應着 actions = [評論]

訂閱的規則還還能夠擴展
用戶可能會有一個本身的訂閱設置,好比對於全部的喜歡的動做,我都不但願接收。
好比Knewone的提醒設置

因此咱們須要再維護一個表:SubscriptionConfig,來存放用戶的提醒設置。
而且,當用戶沒有提醒設置的時候,可使用系統提供的一套默認設置:defaultSubscriptionConfig

聚合

若是我發佈了一篇文章《XXX》,在我不在線的時候,被評論了10遍,當我一上線的時候,應該是收到十條信息相似於:「誰誰誰評論了你的文章《XXX》」?
仍是應該收到一條信息:「甲、乙、丙、丁...評論了你的文章《XXX》」?

知乎在聚合上作的很優秀,要知道他們要實現這個仍是挺有技術的:
知乎的消息機制,在技術上如何設計與規劃?
網站的消息(通知)系統通常是如何實現的?

關於這部分功能,咱們尚未具體的實現方法,暫時也沒法講得更加詳細。⊙﹏⊙

五個實體

經過上面的分析,大概知道作這個消息系統,須要哪些實體類:

  1. 用戶消息隊列 UserNotify

  2. 用戶 User

  3. 訂閱 Subscription

  4. 訂閱設置 SubscriptionConfig

  5. 消息 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 -----------------------

關聯文章:消息系統設計與實現「下篇」


若是本文對您有用
請不要吝嗇大家的Follow與Start
這會大大支持咱們繼續創做

「Github」
MZMonster :@MZMonster
JC_Huang :@JerryC8080

相關文章
相關標籤/搜索