消息系统设计与实现「上篇」

原文连接: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

相关文章
相关标签/搜索