Table of Contents
Message system design and implementation, message system design and implementation
Product Analysis
Brief Book
Zhihu
Three categories of messages
Language analysis of reminders
Two ways to get messages
订阅
聚合
五个实体
行为分解
模型设计
Notify
UserNotify
Subscription
SubscriptionConfig
配置文件 NotifyConfig
服务层 NotifyService
NotifyService拥有以下方法:
各方法的处理逻辑如下:
时序图
提醒的订阅、创建、拉取
公告的创建、拉取
信息的创建
Home Backend Development PHP Tutorial Message system design and implementation, message system design and implementation_PHP tutorial

Message system design and implementation, message system design and implementation_PHP tutorial

Jul 12, 2016 am 08:55 AM

Message system design and implementation, message system design and implementation

Text/JC_Huang (author of the short book)
Original link: http://www.jianshu.com/p/f4d7827821f1
The copyright belongs to the author. Please contact the author for authorization to reprint, and mark the "author of the brief book".

Product Analysis

First, let’s take a look at how messages are implemented in the market.

Brief Book

Jianshu’s messaging system is mainly divided into two types

  • Short message
  • Reminder

Short message
The nature of a short message is actually the same as a private message. It is a message sent from a user to a user with specific information content.


Simple letters

Reminder
A reminder is a message sent by the system, its copy format is fixed, and it usually has a hyperlink to a special object.


Brief reminder

Zhihu

Zhihu is the same as Jianshu, there are two main types:

  • Private message
  • Message

Private message
Similar to Jianshu, it can be a message sent by users to users, or it can also be a message sent by administrators to users.


Zhihu private message

Messages
Zhihu’s messages are even better than Jianshu’s reminders. Zhihu will gather multiple similar messages to reduce users’ reading pressure.


Zhihu news

Three categories of messages

Through a simple analysis of the two products, we can conclude that their messages have two categories. On this basis, we add another one: announcement.
The main nature of the announcement is that the system sends a message with specific content, which can be read by all users on the site.
So, there are three categories of messages:

Language analysis of reminders

We take a set of reminder samples from the short book:

  • 3dbe1bd90774 followed you
  • magicdawn liked your article "Three ways to implement single sign-on"
  • Unscrupulous program likes your article "How to design user permission control based on RESTful API?" 》
  • alexcc4 liked your article "Implementing Unit Testing in Nodejs"
  • You wrote in "How to design user permission control based on RESTful API?" 》Received a comment from cnlinjie
  • Your article "Session Principle" has been added to the topic "ios Development"

Analyze the sentence structure and the content of the reminder is nothing more than

<p>「谁对一样属于谁的事物做了什么操作」<br />「someone do something in someone's something」</p>

Copy after login

someone = the triggerer of the reminder, or the sender, marked as sender
do something = the action of the reminder, comments, likes, and attention all belong to one action, marked as action
something = the action object of the reminder , this is specific to which article it is, marked as target
someone's = the owner of the reminder action object, marked as targetOwner

This is clear. The sender and targetOwner are the users of the website, and the target is the specific article. If the reminder object is not limited to the article, but there are others, you need to add a targetType to mark it. Is the goal an article or something else? The action is fixed. There may be only a few actions that will trigger reminders on the entire website: comment, like, follow... (or other actions that the business needs to remind)

Two ways to get messages

  • Push
  • Pull

Take Zhihu as an example
Pushing is more common. It is necessary to maintain a list of followers for a certain question. Whenever the conditions for pushing this question are triggered (for example, someone answers the question ), send this notification to each follower.

Pulling is a bit more troublesome, which is the reverse of pushing. For example, each user has a list of concerns. Whenever the user goes online, each issue is polled. When the event list of the issue appears, I originally pulled the information with a large timestamp.

而我们则根据消息的不同分类采用不同的获取方式
通告和提醒,适合使用拉取的方式,消息产生之后,会存在消息表中,用户在某一特定的时间根据自己关注问题的表进行消息的拉取,然后添加到自己的消息队列中,

信息,适合使用推的方式,在发送者建立一条信息之后,同时指定接收者,把消息添加到接收者的消息队列中。

订阅

根据提醒使用拉取的方式,需要维护一个关注某一事物的列表。
这种行为,我们称之为:「订阅」Subscribe

一则订阅有以下三个核心属性

  • 订阅的目标 target
  • 订阅的目标类型 targetType
  • 订阅的动作 action

比如我发布了一篇文章,那么我会订阅文章《XXX》的评论动作,所以文章《XXX》每被人评论了,就需要发送一则提醒告知我。

订阅的规则还可以扩展
我喜欢了一篇文章,和我发布了一篇文章,订阅的动作可能不一样。
喜欢了一篇文章,我希望我订阅这篇文章更新、评论的动作。
而发布了一篇文章,我希望我只是订阅这篇文章的评论动作。

这时候就需要多一个参数:subscribReason
不同的subscribReason,对应着一个动作数组,
subscribReason = 喜欢,对应着 actions = [更新,评论]
subscribReason = 发布,对应着 actions = [评论]

订阅的规则还还可以扩展
用户可能会有一个自己的订阅设置,比如对于所有的喜欢的动作,我都不希望接收。
比如Knewone的提醒设置


Knewone提醒设置

所以我们需要再维护一个表:SubscriptionConfig,来存放用户的提醒设置。
并且,当用户没有提醒设置的时候,可以使用系统提供的一套默认设置:defaultSubscriptionConfig

聚合

如果我发布了一篇文章《XXX》,在我不在线的时候,被评论了10遍,当我一上线的时候,应该是收到十条信息类似于:「谁谁谁评论了你的文章《XXX》」?
还是应该收到一条信息:「甲、乙、丙、丁...评论了你的文章《XXX》」?

知乎在聚合上做的很优秀,要知道他们要实现这个还是挺有技术的:
知乎的消息机制,在技术上如何设计与规划?
网站的消息(通知)系统一般是如何实现的?

关于这部分功能,我们还没有具体的实现方法,暂时也无法讲得更加详细。⊙﹏⊙

五个实体

通过上面的分析,大概知道做这个消息系统,需要哪些实体类:

行为分解

说了这么多,整理一下整个消息流程的一些行为:

  • 系统或者管理员,创建消息
    • createNotify (make announce | remind | message)
  • 用户,订阅消息,取消订阅
    • subscribe, cancelSubscription
  • 用户管理订阅设置
    • getSubscriptionConfig, updateSubscriptionConfig
  • 用户,拉取消息
    • pullNotify (pull announce | remind | message | all)
  • 用户,查询消息队列
    • getUserNotify(get announce | remind | message | all)
  • 用户阅读消息
    • read
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

模型设计

Notify

<code class="javascript">id            : {type: <span class="hljs-string">'integer', primaryKey: <span class="hljs-literal">true},        <span class="hljs-comment">// 主键
content     : {type: <span class="hljs-string">'text'},    <span class="hljs-comment">// 消息的内容
type        : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true, enum: [<span class="hljs-number">1, <span class="hljs-number">2, <span class="hljs-number">3]},  <span class="hljs-comment">// 消息的类型,1: 公告 Announce,2: 提醒 Remind,3:信息 Message
target      : {type: <span class="hljs-string">'integer'},    <span class="hljs-comment">// 目标的ID
targetType  : {type: <span class="hljs-string">'string'},    <span class="hljs-comment">// 目标的类型
action      : {type: <span class="hljs-string">'string'},    <span class="hljs-comment">// 提醒信息的动作类型
sender      : {type: <span class="hljs-string">'integer'},    <span class="hljs-comment">// 发送者的ID
createdAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
Copy after login

Save Remind
消息表,我们需要targettargetType字段,来记录该条提醒所关联的对象。而action字段,则记录该条提醒所关联的动作。
比如消息:「小明喜欢了文章」
则:

<code class="javascript">target = <span class="hljs-number">123,  <span class="hljs-comment">// 文章ID
targetType = <span class="hljs-string">'post',  <span class="hljs-comment">// 指明target所属类型是文章
sender = <span class="hljs-number">123456  <span class="hljs-comment">// 小明ID</span></span></span></span></span></span></code>
Copy after login

Save Announce and Message
当然,Notify还支持存储公告和信息。它们会用到content字段,而不会用到targettargetTypeaction字段。

UserNotify

<code class="javascript">id            : {type: <span class="hljs-string">'integer', primaryKey: <span class="hljs-literal">true},        <span class="hljs-comment">// 主键
isRead      : {type: <span class="hljs-string">'boolean', required: <span class="hljs-literal">true},   
user        : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true},  <span class="hljs-comment">// 用户消息所属者
notify      : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true}   <span class="hljs-comment">// 关联的Notify
createdAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></span></span></code>
Copy after login

我们用UserNotify来存储用户的消息队列,它关联一则提醒(Notify)的具体内容。
UserNotify的创建,主要通过两个途径:

Subscription

<code class="javascript">target      : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true},    <span class="hljs-comment">// 目标的ID
targetType  : {type: <span class="hljs-string">'string', required: <span class="hljs-literal">true},    <span class="hljs-comment">// 目标的类型
action      : {type: <span class="hljs-string">'string'},   <span class="hljs-comment">// 订阅动作,如: comment/like/post/update etc.
user        : {type: <span class="hljs-string">'integer'},
createdAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></code>
Copy after login

订阅,是从Notify表拉取消息到UserNotify的前提,用户首先订阅了某一个目标的某一个动作,在此之后产生这个目标的这个动作的消息,才会被通知到该用户。
如:「小明关注了产品A的评论」,数据表现为:

<code class="javascript">target: <span class="hljs-number">123,  <span class="hljs-comment">// 产品A的ID
targetType: <span class="hljs-string">'product',
action: <span class="hljs-string">'comment',
user: <span class="hljs-number">123  <span class="hljs-comment">// 小明的ID</span></span></span></span></span></span></code>
Copy after login

这样,产品A下产生的每一条评论,都会产生通知给小明了。

SubscriptionConfig

<code class="javascript">action: {type: <span class="hljs-string">'json', required: <span class="hljs-literal">true},   <span class="hljs-comment">// 用户的设置
user: {type: <span class="hljs-string">'integer'}</span></span></span></span></code>
Copy after login

不同用户可能会有不一样的订阅习惯,在这个表中,用户可以统一针对某种动作进行是否订阅的设置。而默认是使用系统提供的默认配置:

<code class="javascript">defaultSubscriptionConfig: {
  <span class="hljs-string">'comment'   : <span class="hljs-literal">true,    <span class="hljs-comment">// 评论
  <span class="hljs-string">'like'      : <span class="hljs-literal">true,    <span class="hljs-comment">// 喜欢
}</span></span></span></span></span></span></code>
Copy after login
<p>在这套模型中,<code>targetType</code>、<code>action</code>是可以根据需求来扩展的,例如我们还可以增加多几个动作的提醒:<code>hate</code>被踩、<code>update</code>被更新....诸如此类。</p>
Copy after login

配置文件 NotifyConfig

<code class="javascript"><span class="hljs-comment">// 提醒关联的目标类型
targetType: {
  PRODUCT : <span class="hljs-string">'product',    <span class="hljs-comment">// 产品
  POST    : <span class="hljs-string">'post'    <span class="hljs-comment">// 文章
},

<span class="hljs-comment">// 提醒关联的动作
action: {
  COMMENT   : <span class="hljs-string">'comment',  <span class="hljs-comment">// 评论
  LIKE      : <span class="hljs-string">'like',     <span class="hljs-comment">// 喜欢
},

<span class="hljs-comment">// 订阅原因对应订阅事件
reasonAction: {
  <span class="hljs-string">'create_product'  : [<span class="hljs-string">'comment', <span class="hljs-string">'like']
  <span class="hljs-string">'like_product'    : [<span class="hljs-string">'comment'],
  <span class="hljs-string">'like_post'       : [<span class="hljs-string">'comment'],
},

<span class="hljs-comment">// 默认订阅配置
defaultSubscriptionConfig: {
  <span class="hljs-string">'comment'   : <span class="hljs-literal">true,    <span class="hljs-comment">// 评论
  <span class="hljs-string">'like'      : <span class="hljs-literal">true,    <span class="hljs-comment">// 喜欢
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
Copy after login

服务层 NotifyService

NotifyService拥有以下方法:

  • createAnnounce(content, sender)
  • createRemind(target, targetType, action, sender, content)
  • createMessage(content, sender, receiver)
  • pullAnnounce(user)
  • pullRemind(user)
  • subscribe(user, target, targetType, reason)
  • cancelSubscription(user, target ,targetType)
  • getSubscriptionConfig(userID)
  • updateSubscriptionConfig(userID)
  • getUserNotify(userID)
  • read(user, notifyIDs)

各方法的处理逻辑如下:

createAnnounce(content, sender)

createRemind(target, targetType, action, sender, content)

createMessage(content, sender, receiver)

pullAnnounce(user)

pullRemind(user)

subscribe(user, target, targetType, reason)

cancelSubscription(user, target ,targetType)

getSubscriptionConfig(userID)

updateSubscriptionConfig(userID)

getUserNotify(userID)

read(user, notifyIDs)

时序图

提醒的订阅、创建、拉取


提醒的订阅、创建、拉取


我们可以在产品创建之后,调用NotifyService.subscribe方法,
然后在产品被评论之后调用NotifyService.createRemind方法,
再就是用户登录系统或者其他的某一个时刻调用NotifyService.pullRemind方法,
最后在用户查询消息队列的时候调用NotifyService.getUserNotify方法。

公告的创建、拉取


公告的创建、拉取


在管理员发送了一则公告的时候,调用NotifyService.createAnnounce方法,
然后在用户登录系统或者其他的某一个时刻调用NotifyService.pullAnnounce方法,
最后在用户查询消息队列的时候调用NotifyService.getUserNotify方法。

信息的创建


信息的创建


信息的创建,只需要直接调用NotifyService.createMessage方法就可以了,
在下一次用户查询消息队列的时候,就会查询这条信息。


 

   

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/1114983.htmlTechArticleMessage system design and implementation, message system design and implementation article/JC_Huang (author of the short book) Original link: http:/ /www.jianshu.com/p/f4d7827821f1 The copyright belongs to the author, please contact...
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1669
14
PHP Tutorial
1273
29
C# Tutorial
1256
24
Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1? Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1? Apr 17, 2025 am 12:06 AM

In PHP, password_hash and password_verify functions should be used to implement secure password hashing, and MD5 or SHA1 should not be used. 1) password_hash generates a hash containing salt values ​​to enhance security. 2) Password_verify verify password and ensure security by comparing hash values. 3) MD5 and SHA1 are vulnerable and lack salt values, and are not suitable for modern password security.

PHP and Python: Comparing Two Popular Programming Languages PHP and Python: Comparing Two Popular Programming Languages Apr 14, 2025 am 12:13 AM

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP in Action: Real-World Examples and Applications PHP in Action: Real-World Examples and Applications Apr 14, 2025 am 12:19 AM

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

How does PHP type hinting work, including scalar types, return types, union types, and nullable types? How does PHP type hinting work, including scalar types, return types, union types, and nullable types? Apr 17, 2025 am 12:25 AM

PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

The Enduring Relevance of PHP: Is It Still Alive? The Enduring Relevance of PHP: Is It Still Alive? Apr 14, 2025 am 12:12 AM

PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.

PHP and Python: Different Paradigms Explained PHP and Python: Different Paradigms Explained Apr 18, 2025 am 12:26 AM

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

How do you prevent SQL Injection in PHP? (Prepared statements, PDO) How do you prevent SQL Injection in PHP? (Prepared statements, PDO) Apr 15, 2025 am 12:15 AM

Using preprocessing statements and PDO in PHP can effectively prevent SQL injection attacks. 1) Use PDO to connect to the database and set the error mode. 2) Create preprocessing statements through the prepare method and pass data using placeholders and execute methods. 3) Process query results and ensure the security and performance of the code.

PHP and Python: Code Examples and Comparison PHP and Python: Code Examples and Comparison Apr 15, 2025 am 12:07 AM

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

See all articles