一个事件发生后,不是发布方自己挨个通知所有下游系统,而是把"消息"丢到 MQ,由 MQ 负责转发给需要的模块。
你这个场景特别典型:
文章发布后,要做 3 件事:
-
更新 ES 索引
-
清理缓存
-
发送通知
一、不用 MQ 时,为什么叫强耦合?
你现在的代码是这样:
java
publish() {
saveToDb();
esService.index();
cacheService.clear();
notifyService.send();
}
意思就是:
文章发布服务 不仅要负责"发布文章",
还要亲自去调用:
-
ES 模块
-
缓存模块
-
通知模块
这就像:
你开了一家店,每来一个新订单,你自己还要亲自打电话给仓库、快递、短信平台。
问题是:
1)耦合太重
发布文章本来只该关心"发布成功",
结果还依赖了 3 个别的模块。
2)扩展麻烦
以后如果再加一个"推荐系统更新",你还得改发布代码。
3)一个失败可能拖垮整体
比如通知服务挂了,可能导致整篇文章发布流程变慢,甚至失败。
二、用了 RabbitMQ 后,数据分发是怎么回事?
改成这样:
java
publish() {
saveToDb();
rabbitTemplate.send("article.published", articleId);
}
发布服务只做两件事:
-
保存文章
-
发一条"文章已发布"的消息
后面的事谁来做?
-
ES 模块自己监听消息,收到后更新索引
-
缓存模块自己监听消息,收到后清缓存
-
通知模块自己监听消息,收到后发通知
也就是说:
发布服务不再"点名通知每个人",而是"在群里发公告"。
谁关心这个事件,谁自己订阅。
三、什么叫"数据分发"?
所谓 数据分发,就是:
一份业务数据或一个业务事件,发送出去后,被多个下游系统分别消费,各自处理自己的逻辑。
在你的例子里:
-
一条
articleId -
被分发给多个消费者:
-
ES 消费者
-
缓存消费者
-
通知消费者
-
它们拿到的是同一个"文章发布事件",
但做的事情不同。
所以 RabbitMQ 在这里扮演的是:
事件中转站 / 分发中心
四、通俗比喻
你就把 RabbitMQ 想成一个广播站。
不用 MQ
你自己一个个打电话:
-
喂,ES 来更新一下
-
喂,缓存来删一下
-
喂,通知来发一下
用 MQ
你拿着喇叭喊一句:
"文章发布了,ID 是 1001!"
然后:
-
ES 部门听到了,去建索引
-
缓存部门听到了,去删缓存
-
通知部门听到了,去发消息
这就是数据分发。
五、它带来的核心好处
1)解耦
发布服务不需要知道 ES、缓存、通知的具体实现。
2)扩展方便
以后增加"积分发放""推荐系统更新",只要新增消费者,不用改发布代码。
3)异步提速
主流程只要把消息发出去就可以返回,不需要等所有下游执行完。
4)失败隔离
通知模块挂了,不一定影响文章发布主流程。
六、面试回答版
使用 RabbitMQ 做数据分发,核心思想是一个业务事件发生后,把事件消息交给 MQ,由多个下游系统各自订阅处理 。
比如文章发布后,主流程只负责保存文章并发送一条"文章发布成功"的消息,至于更新 ES、清理缓存、发送通知,都由各自的消费者独立完成。
这样相比同步调用,最大的好处是解耦、异步、易扩展:发布服务不需要依赖所有下游模块,后续新增业务也只需要新增消费者,不用修改核心发布逻辑;同时某个下游服务出问题,也不会直接拖慢主流程。
七、简短一句话
RabbitMQ 做数据分发,就是把"发布后要做的多个动作"从主业务里拆出来,通过消息广播给多个消费者分别处理。