主题
面试速答(先看这里)
**一句话结论:**生产者消费者模式 ,这个就不用说了,通过这种方式可以实现解耦,即生产者只负责发送事件,消费者负责监听处理,二者之间的耦合相比于直接调用是比较弱的,中间的联系只是一个事件的定义而已。
60秒标准回答:
我们都知道,Spring是提供了Event机制的,可以在发送一个事件,然后再基于这个事件做监听处理,这个流程好像和MQ有点像。都是典型的生产者-消费者的模式
有很多事情,我们用这两者都能实现,主要是因为他们有很多共同点
生产者消费者模式 ,这个就不用说了,通过这种方式可以实现解耦,即生产者只负责发送事件,消费者负责监听处理,二者之间的耦合相比于直接调用是比较弱的,中间的联系只是一个事件的定义而已
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**我们都知道,Spring是提供了Event机制的,可以在发送一个事件,然后再基于这个事件做监听处理,这个流程好像和MQ有点像。
- **要点2:**有很多事情,我们用这两者都能实现,主要是因为他们有很多共同点:
- **要点3:**异步处理 ,MQ是异步的这个没啥好说的了,大家都很容易理解。
- **要点4:**事件/消息的持久化 ,MQ的事件是可以在磁盘上进行持久化存储的。
- **要点5:**失败重试 ,基于MQ,可以做失败重试,MQ自己会针对失败的消息进行重新投递,但是Spring的Event失败了没办法重试,需要自己进行异常的处理。
**记忆锚点:**Spring → Event → 生产者消费者模式 → 一对多的模式 → 失败重试 → JVM
易错提醒:
- 异步处理 ,MQ是异步的这个没啥好说的了,大家都很容易理解。
- 失败重试 ,基于MQ,可以做失败重试,MQ自己会针对失败的消息进行重新投递,但是Spring的Event失败了没办法重试,需要自己进行异常的处理。
加分表达:
- 有很多事情,我们用这两者都能实现,主要是因为他们有很多共同点: 生产者消费者模式 ,这个就不用说了,通过这种方式可以实现解耦,即生产者只负责发送事件,消费者负责监听处理,二者之间的耦合相比于直接调用是比较弱的,中间的联系只是一个事件的定义而已。
- 都是典型的生产者-消费者的模式。
- 所以, 在实际的业务中,如果是在自己的业务中需要做一些解耦或者一发多收的操作,比如订单创建后,异步创建一条订单流水。
追问准备:
- 围绕「Spring」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「Event」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「生产者消费者模式」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
我们都知道,Spring是提供了Event机制的,可以在发送一个事件,然后再基于这个事件做监听处理,这个流程好像和MQ有点像。都是典型的生产者-消费者的模式。
有很多事情,我们用这两者都能实现,主要是因为他们有很多共同点:
生产者消费者模式,这个就不用说了,通过这种方式可以实现解耦,即生产者只负责发送事件,消费者负责监听处理,二者之间的耦合相比于直接调用是比较弱的,中间的联系只是一个事件的定义而已。
一对多的模式,无论是Spring的事件还是MQ,都支持一发多收,一个发送者发送消息,其他的多个消费者一起监听这个消息做自己的业务逻辑。
异步处理,MQ是异步的这个没啥好说的了,大家都很容易理解。Spring Event默认是同步的,但是他也支持异步,能基于线程池实现一个异步的事件消费。
但是,他们之间还有很多不同:
事件/消息的持久化,MQ的事件是可以在磁盘上进行持久化存储的。但是Spring的事件机制的话,是没有持久化的,它是基于JVM内存的,一旦应用重启或者崩溃,未处理完的事件也会随时消失
削峰填谷,MQ天然提供了削峰填谷的能力,因为MQ自己会通过队列做存储,这个队列可以起到一个很好的缓冲作用。而Spring Event的事件没有一个缓冲。
失败重试,基于MQ,可以做失败重试,MQ自己会针对失败的消息进行重新投递,但是Spring的Event失败了没办法重试,需要自己进行异常的处理。
特殊功能,MQ针对消息提供了很多特殊的功能,比如延迟消息、顺序消息、事务消息等等,而Spring Event就是玩出花来,也就是自定义个线程池进行处理。。。
但是Spring Event相比MQ也有好处,那就是简单,非常简单。
所以,在实际的业务中,如果是在自己的业务中需要做一些解耦或者一发多收的操作,比如订单创建后,异步创建一条订单流水。这种就可以基于Spring Event来做,并且利用线程池来进行异步并提升执行效率。
但是,需要考虑失败的问题,一旦处理失败了,需要有补偿机制,比如通过定时任务进行补偿处理。
而在多个系统之间交互的时候,就不能用Spring Event了,因为他没办法跨JVM进程,只能用MQ,并且如果要用到一些延迟消息、顺序消息、事务消息等就必须要用MQ,以及如果并发量比较大,也需要借助MQ进行削峰填谷。