内容简介:消息系统的设计与实现
消息系统的设计与实现
在开发 Web 应用的时候,消息系统是一个绕不过的话题,特别是在社交类的应用中。用户的点赞、评论、关注、回复等等,对于电商类的应用,还需要有公告等消息,而这些都需要把操作详情通知到对应的人,而且还要满足个性化的定制。
需求梳理
我们首先来看看关于消息这一块具体的业务形态是怎么样的:
1.对于知乎的消息聚合
2.对于简书的消息聚合
通过对这些的分析,我们可以得出对于消息一般是分为三类:公告、提醒、私信,这里着重讲一下提醒类的消息。
- 公告就是针对全部用户的消息推送(比如停机维护、业务升级)
- 提醒是指在特定环境下的通知(比如点赞、评论)
- 私信就类似点对点聊天
再来看看一组具体提醒类消息的样本:
- 张三三 关注了你
- 李思思 喜欢了你的文章 《消息系统的设计与实现》
- 赵武武 收藏了你的文章 《消息系统的设计与实现》
- 周正正 评论了你的文章 《消息系统的设计与实现》
可以看到消息都是有一个统一的范本:
- sender: 提醒的触发者(比如上文中的张三三)
- action: 提醒的动作(评论、喜欢、关注)
- target: 提醒的作用对象(具体的某一篇文章)
- user: 提醒动作作用对象的所有者(比如文章的作者)
通过这样的分析,就可以明白其中sender
和user
是网站的用户,而target
是具体的作用对象,比如文章(article)、商品(product)、订单(order),action
动作对于每个应用来说都是固定的,比如点赞(like)、收藏(collection)、评论(comment)等等。
个性化配置
对于消息系统来说,个性化配置是不可或缺的需求。我们来看看知乎上面的配置:
对于这样的个性化配置,我们还需要维护一个用户对于某个对象可能产生的动作的关注。对于文章,他可能存在的通知范畴有:点赞、收藏、评论。作者只有去订阅了该文章的这些动作,才能在特定的事件产生的时候给作者推送提醒。比如我发布了一篇文章,那么我会根据自己的配置(比如配置中打开了只接收评论)订阅该文章的动作(那么只订阅评论动作),所以文章每被人评论了,就需要发送一则提醒告知我。
对于订阅的规则,不拘泥于这一些,可以根据不同的业务与通知对象进行拓展,而且假如用户没有配置的话,我们还要提供默认的配置。通过上面的分析,我们可以抽象出三个实体,其中通知(Notify)包括三类(公告、提醒、私信)
- 通知(Notify)
- 订阅(Subscription)
- 配置(SubscriptionConfig)
数据结构
- Notify
id : {type: 'integer'} // 主键 content : {type: 'text'} // 消息的内容 type : {type: 'string'} // 消息类型(公告announce、提醒remind、私信message) target_id : {type: 'integer'} // 目标的ID(比如文章ID) target_type : {type: 'string'} // 目标的类型(比如文章article) action : {type: 'string'} // 动作类型(比如点赞like) sender_id : {type: 'integer'} // 发送者ID sender_type : {type: 'string'} // 发送者类型(前台用户user,管理员admin) is_read : {type: 'integer'} // 阅读状态 user_id : {type: 'integer'} // 消息的所属者(比如文章的作者) created_at : {type: 'datetime'} // 时间
对于
target
和sender
这两个可能不是很理解,对于提醒类的消息我们需要标记作用对象(target)与触发者(sender),举一个简单的例子: 「张三三喜欢了你的文章《我的家乡》」,那么:target_id: 123 // 文章ID target_type: 'article', // 指明target所属类型是文章 sender_id: 123456 // 张三三 sender_type: 'user' // 张三三的用户类型(普通用户or管理员)
上面
sender_type
区分的目的就是为了在发送公告类的时候保存发送者。而且对于公告和私信类的消息还会用到content
字段,而不会用到target
、action
字段
2.Subscription
target_id : {type: 'integer'} // 目标的ID(比如文章ID)
target_type : {type: 'string'} // 目标的类型(比如文章article)
action : {type: 'string'} // 动作类型(比如点赞like)
user_id : {type: 'integer'} // 订阅用户
订阅表的设定是为了个性化配置铺路,当用户发表一篇文章的时候,我们会把文章可能产生的动作都保存到订阅表中,在此之后这个目标触发该动作产生的消息,都会被通知到该用户。比如用户想要接收一篇文章的评论消息,那么订阅的数据表现为:
target_id : 123 // 目标的ID(文章ID)
target_type : 'article' // 目标的类型
action : 'comment' // 动作类型
user_id : 1 // 订阅用户
而且有订阅的情况下,还可以实现特定文章才接收通告的需求,同学们可以自行发挥想象。
3.SubscriptionConfig
对于每个订阅动作来说,用户可能并不想要都通知到自己。比如文章的动作有点赞、评论、收藏,但是用户只想接收评论的消息,那么配置就派上用场了。他的数据结构很简单:
config : {type: 'json'} // 具体配置
user_id : {type: 'integer'} // 订阅用户
其中config
是一个特定的 json
对象,根据不同的业务配置有所不同,比如对于文章和用户可能有:
{
comment : true,
like : false,
collection : false,
follow : true //关注用户
}
当然了并不是每个用户都会去配置,所以我们要提供一组默认的配置,而且配置还可以根据业务进行拓展:
defaultConfig: {
comment : true,
like : true,
collection : true,
follow : true //关注用户
}
业务逻辑
通过上面的分析整个需求已经很明朗了,再详细说下每个功能点的实现过程中,具体的业务逻辑。
- 创建提醒
创建提醒主要的参数是用户、动作、目标,然后到订阅表中查询该用户是否有订阅该目标的该动作,然后再去配置表中查询是否开启了该项配置,进而就可以进行入库处理了。
2.创建订阅
一般情况下,我们都会在创建特定实体的时候同步创建订阅记录。比如用户写了一篇文章,然后文章有评论、点赞、收藏事件,那么我们就要在新建文章后这个节点入库三条记录:
{
target_id : 111,
target_type : 'article',
action : 'comment'
user_id : 10
}
{
target_id : 111,
target_type : 'article',
action : 'like'
user_id : 10
}
{
target_id : 111,
target_type : 'article',
action : 'collection'
user_id : 10
}
然后在文章收到评论(comment)等的时候,就可以去查询并且判定是否通知用户了。
3.针对特定实体设定配置
我们还会有这样的需求,用户发表完文章后不想接收该文章的所有或者特定提醒,那么就可以在订阅表中把不想要的那个订阅动作删除了即可
4.设定已读
对于提醒和私信类的消息,设定已读只要在 notify
表里面设定 is_read
字段即可,但是对于公告类的消息,并没有存储user_id
字段,这样如果直接设置的话所有用户拉取到的公告都会被设定为已读。这里提供一个解决方案就是通过 Redis
的 Bitmap
来存储每个用户每条公告的阅读状态。
论坛传图片太难受,具体可以查看:https://mp.weixin.qq.com/s/JVvyFu_K0CdJwWbGDEkxAw
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何优雅的实现消息通信?
- Go实现Websocket消息推送
- Golang,kafka实现消息推拉
- 基于RabbitMQ实现异步消息通知处理
- 去哪儿网消息队列设计与实现
- QMQ 顺序消息设计与实现(上)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数值方法和MATLAB实现与应用
拉克唐瓦尔德 / 机械工业出版社 / 2004-9 / 59.00元
本书是关于数值方法和MATLAB的介绍,是针对高等院校理工科专业学生编写的教材。数值方法可以用来生成其他方法无法求解的问题的近似解。本书的主要目的是为应用计算打下坚实的基础,由简单到复杂讲述了标准数值方法在实际问题中的实现和应用。本书通篇使用良好的编程习惯向读者展示了如何清楚地表达计算思想及编制文档。书中通过给读者提供大量的可直接运行的代码库以及讲解MARLAB工具箱中内置函数使用的数量方法,帮助......一起来看看 《数值方法和MATLAB实现与应用》 这本书的介绍吧!