跳到主要内容

设计一个消息中心

需求汇总

  • 消息已读\未读
  • 消息投递
  • 展示消息数量
  • 一键已读
  • 多用户
  • 推送的渠道

消息的分类

系统通知

系统通知一般是由后台管理员发出,然后指定某一类(全体,个人等)用户接收。 基于此设想,可以把系统通知大致分为两张表:

  • 一张记录管理员发出的通知,称之为 t_manager_system_notice 管理员系统通知表;
  • 一张存储用户接受的通知,称之为 t_user_system_notice 用户系统通知表。

这个 t_manager_system_notice 结构如下:

字段名类型描述
system_notice_idLONG系统通知ID
titleVARCHAR标题
contentTEXT内容
typeVARCHAR发给哪些用户:单用户single;全体用户all,vip用户,具体类型各位同学可以根据自己的需求选择
stateBOOLEAN是否已被拉取过,如果已经拉取过,就无需再次拉取
recipient_idLONG接受通知的用户的ID,如果type为单用户,那么recipient为该用户的ID;否则recipient为0
manager_idLONG发布通知的管理员ID
publish_timeTIMESTAMP发布时间

这个 t_user_system_notice 结构如下:

字段名类型描述
user_notice_idLONG主键ID
stateBOOLEAN是否已读
system_notice_idLONG系统通知的ID
recipient_idLONG接受通知的用户的ID
pull_timeTIMESTAMP拉取通知的时间

当管理员发布一条通知后,将通知插入 t_manager_system_notice 表中,然后系统定时的从 t_manager_system_notice 表中拉取通知,然后根据通知的 type 将通知插入 t_user_system_notice 表中。

如果通知的 type 是 single 的,那就只需要插入一条记录到 t_user_system_notice 中。如果是全体用户,那么就需要将一个通知批量根据不同的用户 ID 插入到 t_user_system_notice 中, 这个数据量就需要根据平台的用户量来计算。

举个例子: 管理员A 发布了一个活动的通知,他需要将这个通知发布给全体用户, 当拉取时间到来时,系统会将这一条通知取出。随后系统到用户表中查询选取所有用户的 ID, 然后将这一条通知的信息根据所有用户的 ID,批量插入 t_user_system_notice 中。 用户需要查看系统通知时,从 t_user_system_notice 表中查询就行了。

个人消息

TODO: 遇到再设计

设计方案

方案1:提供 sdk 没有 MQ

优点:

  • 降低了系统的复杂度;

缺点:

  • 需要保证消息中心的并发、高可用等各种复杂场景;

方案2:提供sdk,借助 MQ

优点:

  • 集成成本低,只要按照 sdk 接口封装消息调用即可,便于新手集成以及调试;
  • 业务系统无需关注消息处理方式,不需要引入 mq 组件;
  • 消息中心统一选择 mq 组件,方便后期升级改造;
  • 处理延迟消息时无需借助其他方案,比如定时器或者轮询;
  • 削峰,有效保证消息中心能够始终稳定处理消息;
  • 有效保证处理的顺序性;

缺点:

  • 业务方需要集成 sdk,跟消息中心耦合在一起;
  • 业务系统需要维护 sdk 的版本;
  • 消息中心服务不可用时,消息无法正常发送,造成消息丢失;
  • 引入 mq 后,增加了复杂度;
  • 需要保证 mq 的可用性;

方案3:不提供sdk,借助 MQ

优点:

  • 业务系统无需集成 sdk,跟消息中心完全解耦;
  • 无需关注后续 sdk 升级等问题;
  • 消息中心不可用时,不影响业务系统正常消息发送;

缺点:

  • 使用成本高,新业务集成无法知道消息体包装是否正确,中间的调试排查成本高;
  • 业务系统需要引入 mq 等配置信息和组件,增加了业务系统的复杂度;
  • 不利于后期对 mq 的升级改造;

SDK 方法设计

发送方式

  • 单个发送消息(可以考虑去掉)
  • 批量发送消息

撤回方式

  • 单个消息撤回(可以考虑去掉)
  • 批量消息撤回

发送形式

  • 短信
  • 站内信
  • 邮件

消息管理

消息类型列表接口

根据端标识来展示消息类型列表

列表中要包含:类型信息+最新消息+未读数量

消息类型下消息列表分页接口

查询消息类型下的所有消息,需要分页展示、排序

未读数量接口-总合计

查询用户所有未读的消息合计

已读接口

修改消息阅读状态

删除接口

消息逻辑删除

References