Spring 异步事件本地消息表设计
463 字
2 分钟
Spring 异步事件本地消息表设计
解决问题
日常使用 spring 的 application event 实现业务解耦时,默认实现无法跟踪事件是否正常发送,下游业务是否正常消费。
例如用户下单成功后,需要给用户发送邮件通知,普通代码如下
@Transactional(rollbackFor = Exception.class)public void createOrder(CreateOrderCmd cmd) { Order order = doSaveOrder(cmd); EmailContext emailCtx = prepareEmailContext(order); sendEmail(emailCtx);}
public void sendEmail(EmailContext emailCtx) { // 邮件发送逻辑}以上代码有小概率出现 邮件发送成功,用户下单失败数据库回滚场景
改良后的代码如下
@Transactional(rollbackFor = Exception.class)public void createOrder(CreateOrderCmd cmd) { Order order = doSaveOrder(cmd); // 在数据库事务提交后执行发送邮件 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { // 事务同步只在事务存在且成功提交时触发,如果事务回滚,afterCommit() 不会执行 @Override public void afterCommit() { EmailContext emailCtx = prepareEmailContext(order); sendEmail(emailCtx); } });}
public void sendEmail(EmailContext emailCtx) { // 邮件发送逻辑}以上写法,能够保证数据库提交后才触发发送短信发送操作,但是无法保证邮件发送操作正常完成(例如邮件网关拒收)
改进方案
@Transactional(rollbackFor = Exception.class)public void createOrder(CreateOrderCmd cmd) { Order order = doSaveOrder(cmd); OrderCreatedEvent event = new OrderCreatedEvent(); // ... setEvent saveLocalEvent(event);
// 在数据库事务提交后执行发送短信 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { applicationEventPublisher.publishEvent(event); // 更新事件发送状态 updateEventSendStatus(event); } });}
@EventListenerpublic void orderCreatedEventHandler(OrderCreatedEvent event) { EmailContext emailCtx = prepareEmailContext(event); sendEmail(emailCtx); // 保存事件消费记录 saveLocalEventHandleLog(event);}
@Transactional(rollbackFor = Exception.class)public void saveLocalEventHandleLog(Object event) { // 将事件处理记录保存到数据库中}
public void saveLocalEvent(Object event) { // 保存到数据库}
public void sendEmail(EmailContext emailCtx) { // 邮件发送逻辑}本地消息表设计

框架代码封装
todo
其他衍生问题
高并发业务,事件表、事件处理记录的分表设计、归档设计
📎 参考文章
- 一些引用
- 引用文章
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
Spring 异步事件本地消息表设计
https://blog.sephy.top/posts/spring-异步事件本地消息表设计/相关文章智能推荐
1
jasypt-maven-plugin 使用
技术分享mvn jasypt:encrypt-value -Djasypt.encryptor.password="加密用的密码" -Djasypt.plugin.value="需要进行加密的原文"
2
如何做好技术评审
方法论技术评审流程与要点指南。包含评审准备、评审要点、常见问题、评审 checklist 等。
3
SpringBoot 在 Docker 容器中的 1 号进程
技术分享踩到了 1 个坑, 发现平滑关机在 docker 容器中没有按照预想的执行
4
系统开发实践-Spring Cloud 异常封装及传递处理
技术分享准备将 RPC 协议从 dubbo 切换为 feign, 记录一些系统设计细节
服务端的异常输出设计
OpenFeign 的异常传递捕捉处理
5
DDD记录
方法论这篇文章讨论了在 充血模型 和 贫血模型 之间找到平衡点,强调在实践中可以适当妥协。通过 DDD 中的 聚合根 和 领域服务 思想,减少不必要的服务类,简化设计,同时借鉴 CQRS 来优化查询逻辑。文章建议,尽管充血模型增加复杂度,但可以通过适度的领域服务管理和领域事件来达到合理的业务处理和开发效率。
随机文章随机推荐













