由于文章篇幅較長(zhǎng)趁俊,而作者精力有限脚作,不希望這么早就精盡人亡警没,故分成上下篇來(lái)寫消息系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)匈辱。上篇主要講的是一些概念,搞清楚我們要做的這個(gè)消息系統(tǒng)的主要內(nèi)容杀迹。而下篇主要講具體的實(shí)現(xiàn)亡脸,會(huì)包括架構(gòu)設(shè)計(jì),數(shù)據(jù)庫(kù)設(shè)計(jì),業(yè)務(wù)流程詳細(xì)的實(shí)現(xiàn)等浅碾。
整個(gè)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)大州,并非我一人之力就可以完成的。這其中是同事們大家一起討論與商討的結(jié)果垂谢,而我只是把它細(xì)化厦画,呈現(xiàn)出來(lái)。
我只是一個(gè)會(huì)思考的idea搬運(yùn)工滥朱。
產(chǎn)品分析
首先我們來(lái)看一下市場(chǎng)上關(guān)于消息的實(shí)現(xiàn)是怎么樣的根暑。
簡(jiǎn)書
簡(jiǎn)書的消息系統(tǒng)主要分了兩種
- 簡(jiǎn)信
- 提醒
簡(jiǎn)信
簡(jiǎn)信的性質(zhì)其實(shí)跟私信是一樣的,是用戶發(fā)送給用戶的一則消息徙邻,有具體的信息內(nèi)容排嫌。
提醒
而提醒,則是系統(tǒng)發(fā)送的一則消息鹃栽,其文案格式是固定的窘茁,并且對(duì)特殊對(duì)象一般擁有超鏈接瘫寝。
知乎
知乎跟簡(jiǎn)書一樣,主要分了兩種:
- 私信
- 消息
私信
跟簡(jiǎn)書一樣霹琼,使用戶發(fā)送給用戶的一則消息蓬抄,也可以是管理員發(fā)送給用戶的消息丰嘉。
消息
知乎的消息比簡(jiǎn)書的提醒有過(guò)之而無(wú)不及,知乎會(huì)對(duì)多條相似的消息進(jìn)行聚會(huì)嚷缭,以達(dá)到減輕用戶閱讀壓力的體驗(yàn)饮亏。
消息的三種分類
通過(guò)兩種產(chǎn)品的簡(jiǎn)單分析,得出他們的消息有兩種分類阅爽,在這基礎(chǔ)上路幸,我們?cè)偌由弦环N:公告。
公告的主要性質(zhì)是系統(tǒng)發(fā)送一則含有具體內(nèi)容的消息付翁,站內(nèi)所有用戶都能讀取到這條消息简肴。
所以,消息有三種分類:
- 公告 Announce
- 提醒 Remind
- 私信 Message
提醒的語(yǔ)言分析
我們從簡(jiǎn)書取一組提醒樣本:
- 3dbe1bd90774 關(guān)注了你
- magicdawn 喜歡了你的文章 《單點(diǎn)登錄的三種實(shí)現(xiàn)方式》
- 無(wú)良程序 喜歡了你的文章 《基于RESTful API 怎么設(shè)計(jì)用戶權(quán)限控制百侧?》
- alexcc4 喜歡了你的文章 《在Nodejs中貫徹單元測(cè)試》
- 你在《基于RESTful API 怎么設(shè)計(jì)用戶權(quán)限控制砰识?》中收到一條 cnlinjie 的評(píng)論
- 你的文章《Session原理》已被加入專題 《ios開發(fā)》
分析句子結(jié)構(gòu),提醒的內(nèi)容無(wú)非就是
「誰(shuí)對(duì)一樣屬于誰(shuí)的事物做了什么操作」
「someone do something in someone's something」
someone = 提醒的觸發(fā)者佣渴,或者發(fā)送者辫狼,標(biāo)記為sender
do something = 提醒的動(dòng)作,評(píng)論辛润、喜歡膨处、關(guān)注都屬于一個(gè)動(dòng)作,標(biāo)記為action
something = 提醒的動(dòng)作作用對(duì)象,這就具體到是哪一篇文章真椿,標(biāo)記為target
someone's = 提醒的動(dòng)作作用對(duì)象的所有者鹃答,標(biāo)記為targetOwner
這就清楚了,sender和targetOwner就是網(wǎng)站的用戶瀑粥,而target是具體到哪一篇文章挣跋,如果提醒的對(duì)象不僅僅局限于文章,還有其他的話狞换,就需要增加一項(xiàng)targetType避咆,來(lái)標(biāo)記目標(biāo)是文章還是其他的什么。而action修噪,則是固定的查库,整個(gè)網(wǎng)站會(huì)觸發(fā)提醒的動(dòng)作可能就只有那幾樣:評(píng)論、喜歡黄琼、關(guān)注.....(或者其他業(yè)務(wù)需要提醒的動(dòng)作)
消息的兩種獲取方式
- 推 Push
- 拉 Pull
以知乎為例
推的比較常見樊销,需要針對(duì)某一個(gè)問(wèn)題維護(hù)著一張關(guān)注者的列表,每當(dāng)觸發(fā)這個(gè)問(wèn)題推送的條件時(shí)(例如有人回答問(wèn)題)脏款,就把這個(gè)通知發(fā)送給每個(gè)關(guān)注者围苫。
拉的相對(duì)麻煩一點(diǎn),就是推的反向撤师,例如每個(gè)用戶都有一張關(guān)注問(wèn)題的列表剂府,每當(dāng)用戶上線的時(shí)候,對(duì)每個(gè)問(wèn)題進(jìn)行輪詢剃盾,當(dāng)問(wèn)題的事件列表出現(xiàn)了比我原本時(shí)間戳大的信息就進(jìn)行拉取腺占。
而我們則根據(jù)消息的不同分類采用不同的獲取方式:
通告和提醒,適合使用拉取的方式痒谴,消息產(chǎn)生之后衰伯,會(huì)存在消息表中,用戶在某一特定的時(shí)間根據(jù)自己關(guān)注問(wèn)題的表進(jìn)行消息的拉取积蔚,然后添加到自己的消息隊(duì)列中意鲸,
信息,適合使用推的方式库倘,在發(fā)送者建立一條信息之后临扮,同時(shí)指定接收者,把消息添加到接收者的消息隊(duì)列中教翩。
訂閱
根據(jù)提醒使用拉取的方式杆勇,需要維護(hù)一個(gè)關(guān)注某一事物的列表。
這種行為饱亿,我們稱之為:**「訂閱」Subscribe **
一則訂閱有以下三個(gè)核心屬性:
- 訂閱的目標(biāo) target
- 訂閱的目標(biāo)類型 targetType
- 訂閱的動(dòng)作 action
比如我發(fā)布了一篇文章蚜退,那么我會(huì)訂閱文章《XXX》的評(píng)論動(dòng)作闰靴,所以文章《XXX》每被人評(píng)論了,就需要發(fā)送一則提醒告知我钻注。
訂閱的規(guī)則還可以擴(kuò)展
我喜歡了一篇文章蚂且,和我發(fā)布了一篇文章,訂閱的動(dòng)作可能不一樣幅恋。
喜歡了一篇文章杏死,我希望我訂閱這篇文章更新、評(píng)論的動(dòng)作捆交。
而發(fā)布了一篇文章淑翼,我希望我只是訂閱這篇文章的評(píng)論動(dòng)作。
這時(shí)候就需要多一個(gè)參數(shù):subscribReason
不同的subscribReason品追,對(duì)應(yīng)著一個(gè)動(dòng)作數(shù)組玄括,
subscribReason = 喜歡,對(duì)應(yīng)著 actions = [更新肉瓦,評(píng)論]
subscribReason = 發(fā)布遭京,對(duì)應(yīng)著 actions = [評(píng)論]
訂閱的規(guī)則還還可以擴(kuò)展
用戶可能會(huì)有一個(gè)自己的訂閱設(shè)置,比如對(duì)于所有的喜歡的動(dòng)作泞莉,我都不希望接收哪雕。
比如Knewone的提醒設(shè)置
所以我們需要再維護(hù)一個(gè)表:SubscriptionConfig,來(lái)存放用戶的提醒設(shè)置鲫趁。
并且热监,當(dāng)用戶沒(méi)有提醒設(shè)置的時(shí)候,可以使用系統(tǒng)提供的一套默認(rèn)設(shè)置:defaultSubscriptionConfig
聚合
如果我發(fā)布了一篇文章《XXX》饮寞,在我不在線的時(shí)候,被評(píng)論了10遍列吼,當(dāng)我一上線的時(shí)候幽崩,應(yīng)該是收到十條信息類似于:「誰(shuí)誰(shuí)誰(shuí)評(píng)論了你的文章《XXX》」?
還是應(yīng)該收到一條信息:「甲、乙寞钥、丙慌申、丁...評(píng)論了你的文章《XXX》」?
知乎在聚合上做的很優(yōu)秀,要知道他們要實(shí)現(xiàn)這個(gè)還是挺有技術(shù)的:
知乎的消息機(jī)制理郑,在技術(shù)上如何設(shè)計(jì)與規(guī)劃蹄溉?
網(wǎng)站的消息(通知)系統(tǒng)一般是如何實(shí)現(xiàn)的?
關(guān)于這部分功能您炉,我們還沒(méi)有具體的實(shí)現(xiàn)方法柒爵,暫時(shí)也無(wú)法講得更加詳細(xì)∽簦⊙﹏⊙
五個(gè)實(shí)體
通過(guò)上面的分析棉胀,大概知道做這個(gè)消息系統(tǒng)法瑟,需要哪些實(shí)體類:
- 用戶消息隊(duì)列 UserNotify
- 用戶 User
- 訂閱 Subscription
- 訂閱設(shè)置 SubscriptionConfig
- 消息 Notify
- 通告 Announce
- 提醒 Remind
- 信息 Message
行為分解
說(shuō)了這么多,整理一下整個(gè)消息流程的一些行為:
- 系統(tǒng)或者管理員唁奢,創(chuàng)建消息
- createNotify (make announce | remind | message)
- 用戶霎挟,訂閱消息,取消訂閱
- subscribe, cancelSubscription
- 用戶管理訂閱設(shè)置
- getSubscriptionConfig, updateSubscriptionConfig
- 用戶麻掸,拉取消息
- pullNotify (pull announce | remind | message | all)
- 用戶酥夭,查詢消息隊(duì)列
- getUserNotify(get announce | remind | message | all)
- 用戶閱讀消息
- read
在本文的「下篇」我們來(lái)探討一下:模型怎么做、數(shù)據(jù)庫(kù)怎么設(shè)計(jì)脊奋、代碼結(jié)構(gòu)怎么來(lái)熬北、一些邏輯上的時(shí)序圖應(yīng)該是怎么樣的。
-------- 更新于 2015/11/15 ----------
關(guān)聯(lián)文章:消息系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)「下篇」
如果本文對(duì)您有用
請(qǐng)不要吝嗇你們的Follow與Start
這會(huì)大大支持我們繼續(xù)創(chuàng)作
「Github」
MZMonster :@MZMonster
JC_Huang :@JerryC8080