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);
}
});
}
@EventListener
public 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) {
// 邮件发送逻辑
}

本地消息表设计#

image 40
image 40

框架代码封装#

todo

其他衍生问题#

高并发业务,事件表、事件处理记录的分表设计、归档设计

📎 参考文章#

  • 一些引用
  • 引用文章

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Spring 异步事件本地消息表设计
https://blog.sephy.top/posts/spring-异步事件本地消息表设计/
作者
虾米
发布于
2024-12-19
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
虾米
coder
分类
标签
站点统计
文章
61
分类
4
标签
52
总字数
64,663
运行时长
0
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.13.9
文章许可
CC BY-NC-SA 4.0