1. 问题场景描述
//1.开启事务.
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus transaction = transactionManager.getTransaction(definition);
//2.业务代码.
。。。。
//3.发送业务数据中唯一key到kafka(业务代码中将key所在数据条插入了数据库).
//4.提交事务(或在前面代码中遇到异常回滚).
transactionManager.commit(transaction);
另一个地方有代码消费kafka指定topic:
//监听器.
//拿到key后,会先查数据库中这条数据是否存在,然后才有后续操作.
上面出现的问题是测试反应:有时会出现 key是存在的(来源于前端页面),但是在kafka拿到key之后在数据库中查不到 直接返回不存在。
2. 原因
在上面的第一个地方代码中,第3步发送给kafka后,此时还未进行事务提交,但是可能另一个地方的kafka已经消费了,它去查第一个地方未提交的数据,就会出现查不到的情况。当然也有可能在它消费查询之前,第一个地方的代码已经提交了,所以第二个地方kafka消费后查不到数据的情况是偶现。
解决办法
第一个地方在发送数据到kafka的时候,其实前面的业务代码已经成功了,这条数据其实只是仅仅没提交而已,所以可以在kafka的消费端,拿这个key去查数据库的时候,开启事务,设置为读未提交,那么就可以拿到第一个地方未提交的数据,这个事务中只包含这一个查数据库的操作,查完后直接提交事务:
kafka消费端:
//1.拿到key
//2.开启事务,并设置为读未提交。
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
TransactionStatus transaction = transactionManager.getTransaction(definition);
//3.拿着key去查数据库。
//提交事务(或回滚)
transactionManager.commit(transaction);