一、分布式事务的本质

本质上要解决,逻辑上是一个事务,但是代码又是在两个进程里面实现,spring的事务管理不能跨进程的问题。

那么就需要用第三方介质记录当前这个分布式事务逻辑的状态,一般用数据库或redis缓存记录。

二、kafka+本地消息表实现的关键点

生产者:

生产者本地业务逻辑执行完成之后,往数据库插入一条待发送的数据(在一个事务内,要么全部成功,要么全部失败)
然后从数据库去取这条待发送的数据,发送到kafka,状态更新为已发送(一个事务)。

消费者:

消费者从kafka取出消息之后,将消息数据库数据更新为待消费(在一个事务内,要么全部成功,要么全部失败)
然后从数据库去取这条待消费的数据,进行消费端的业务处理,处理完成之后,状态更新为已消费(一个事务)。

定时任务扫描数据库的待发送数据,如果有,则代表有生产者本地执行成功,
但是发送到kafka失败的情况,那就重新发送。

定时任务扫描数据库的待消费数据,如果有,则代表有消费者消息取到了,
但是执行本地逻辑没有成功,那就重新执行消费逻辑。

总结:

生产者和消费者的本地业务逻辑和往kafka存取消息的逻辑要拆分开,用第三方介质记录当前这条消息的状态。

保证生产者本地业务执行完毕了才往kafka发送,发送失败了可以重发。
保证消费者从fafka获取消息之后才执行消费逻辑,执行消费逻辑失败了可以重新执行。

其实就是保证了本地业务逻辑和kafka的存取拆分成两个事务。

三、优缺点

优点:

事务吞吐量大. 因为不需要等待其他数据源响应.
容错性好. A服务在发布事件的时候, B服务甚至可以不在线。

缺点:

1、容易出现较多的中间状态,保证不了实时性。
   比如生产者已经发送数据了,但是消费者才执行到第一步
   (拉取消息,留证据到本地数据库消息表),这个时候用户登录之后,
   可能就看不到消费后的数据。在实时性要求高的业务不太适用。

2、与具体业务场景绑定,偶尔性强,不可以共用。

四、适用场景:

1、实时性要求不高,只要满足最终一致性的情况
2、生产者的逻辑是否成功,不依赖于消费者的逻辑执行是否成功的情况,
   比如:

	下订单和出库,这就是典型的生产者的逻辑要依赖于消费者的逻辑
	是否执行成功。
	因为下订单,如果库存不够,那么订单也是不能成功的。
Logo

鸿蒙生态一站式服务平台。

更多推荐