得物技术从0到1构建一个完整的消息系统

得物技术
English

背景

随着公司的快速发展,每天推送的消息量不断增加。之前的旧消息系统已经日益不能满足现阶段推送场景的功能要求,我们就开始从0到1构建一个完整的消息系统。

消息平台的过去

640.png
原始架构中存在各种各样的痛点与挑战:

  • 接入慢,发送慢

业务接入比较慢,发送不同类型的消息需要接入不同的api. 消息消费处理都很慢,影响活动运营体验。

  • 流量分析没有,各个业务直接调用互相影响

业务调用量统计不清楚,无法针对不同业务进行关闭/限流。

  • 缺乏特殊消息优先推送

缺乏优先级消息,在营销类消息大批量推送时,正常的订单相关的消息就会堆积,阻塞会被延时。

通过下列4个方面进行优化:

  • 接入接口统一,业务身份识别
  • 发送加快,单一消费转多条同时消费
  • 支持消息优先级处理
  • 切换数据源存储,选择写比es相对高一点和读相对es少一点的mongodb
    640 (1).png

    消息平台的现在

    消息平台目前整体架构*
    640 (2).png

    在上述过程中优先级队列如何实现?

    目前消息平台的优先级采用2种发送实现的,首先使用传统的消息队列kafka进行一次优先级发送和消费,后面采用优先线程池任务进行优先消息发送。

    队列优先级

    kafka本身并不支持优先级,我们通过下列2个方案进行处理,人为的对kafka不同队列发送不同优先级消息。

采用创建不同的topic,不同优先级消息发送到不同的topic中,同时在消息消费的时候,按照不同的比例获取不同topic的数据进行消费。

目前的顺序是优先级最高的是第二高的2倍,依次进行下去。最后剩余的拉取消息值加入到优先级最高的里面 比如一次拉取50条,3个topic 那么我们就是按照 (25 +5/ 13 / 7) 进行拉取。

高优先级消息没有了如何让低优先级的消息满负载拉取,即按照上述优先级最低的消息一次性拉取50条消息呢?

引入消息拉取状态机,优先级消息比较低的时候,加大低优先级的消费。目前消息服务状态机,有初始化、低负载、高负载等几个状态,通过判断上一次处理的消息条数来确定消息消费者当前的状态并进行拉取参数的修改,目前采用反射的方式修改kafka的拉取数量。

为了加快速度发送我们也采用了本地线程池,本地线程任务,我们采用任务优先级队列。下面是提交一个线程任务的流程。
640 (3).png
在上图中,我们通过给一个线程任务一个自增的序列号以及之前定义的优先级值进行比较,唯一确定一条任务的执行优先级。

在整体流程图中的延时队列我们是如何实现的呢?

首先我们定义延时/定时策略有一下几个策略:

  • 大于30分钟消息推送
  • 小于30分钟消息推送
  • 低于15s的消息推送

我们将延时定时的消息区分上述3种类型之后,分别有不同的实现方式。在低于15s的时候我们直接采用了java自带的delayTask进行消息判断&推送。而高于15s低于30分的,我们自己创建了一个秒基本级别的单时间轮,进行消息推送,下述是时间轮的执行。
640 (4).png
但是我们在这个基础上进行了部分优化,参考了kafka的延时队列,当时间轮中没有需要执行的任务之后,我们直接对执行的线程进行wait等待,直到下个任务提交notify唤醒。对于高于30分钟的延时任务,我们一般先进行消息任务的存储,在任务快要执行的30分钟之前,我们将任务数据加入到秒级别的时间轮中,参考第二种进行消息发送。(为啥不用天/小时级别时间轮,纯粹是不想浪费内存)

我们在消息推送过程中,用户的防疲劳是必要的,目前消息中心的防疲劳场景主要有以下几种类型:

  • 用户N天不能收到M条消息
  • 某个具体的场景N天内不能收到M条消息
  • 某个具体的业务1天内只能收到1条消息

我们在上述几种场景,主要采用的是mongo进行数据的存储和聚合查询,因为如果使用redis场景在多用户的时候,会频繁的操作redis,并不是很好。且大部分防疲劳的数据我们也仅仅最多保留1周,mongo的集合,很容易把我们这些功能满足。当然在某个具体的业务1天内只能收到1条消息这个场景中,我们采用了redis的helperLogLog进行防疲劳,减少查询和内存消耗。虽然有一点的误差,但是我们的使用场景上影响不是很高。

最后我们从自己的实战总结下来构建一个消息平台需要思考的点:

  • 简单易接入
  • 响应快,不影响业务
  • 紧急消息第一时间送达用户,消息可分级
  • 消息可回溯,可撤回
  • 效果可视化
  • 内容安全

关注得物技术,携手走向技术的云端

阅读 873
328 声望
1.2k 粉丝
0 条评论
你知道吗?

328 声望
1.2k 粉丝
文章目录
宣传栏