threadLocal的使用场景--事务下的日志记录

threadLocal在系统中的使用场景,每发生一笔交易,无论成功失败都要进行数据库记录作为交易日志,成功的不需要多少,失败的时候就需要做一些事务回滚,这里使用的事务回滚是通过异常机制来控制(也可以手动回滚)。当发生异常时就事务回滚,并通过threadLocal记录异常发生时的交易快照以及失败原因,在调用层进行获取并记录;看起来是很正常的一个方案,线上不久就开始出现问题:插入交易日志时,交易流水号重复的问题(每一笔一个唯一流水号)。
根据业务分析一下场景
场景1,如果是交易正常结束,则正常返回一个交易日志,并进行流水日志保存
场景2,如果交易失败,会抛出异常进行事务回滚,在controller 层会对此异常进行捕捉, 并对threadlocal中的值的保存,
原本以为是保存后并没有对threadLocal 中的值进行清理,导致了这个问题,所以就很开心的添加了清理操作,愉快的上线了,但是依然出现了上述问题,好吧装逼失败,只能继续定位
一步步来,发生了异常,对当前threadLocal 进行set值,然后异常抛出到上层,在catch时进行threadLocal的获取日志信息,进行保存,这个时候能对应threadLocal 清理的问题已经无所谓了,因为如果发生了异常就会对threadLocal 中进行覆盖,然后再在ctrl获取,这样进行循环,一切都看起来那么自然,但是问题总归是客观存在的,能出现上述的问题只能是在某一个异常的地方没有对threadLocal 进行覆盖,导致最后保存的还是上一个失败交易的日志,最终保存的时候出现问题
经过代码review 确实是一个第三方异常没有做覆盖处理,导致了此问题

此问题 的引申,是否有更好的方式可以解决此问题,1 request,因为每次的request必须是新的,不会出现request共享问题,所以也可以解决上述的问题

2使用异常机制,将异常机制做到足够细致,可以包含各个细节的异常都可以以枚举的形式,这样不需要threadLocal 或者request,只需要根据异常的信息进行保存就可以知道出现的详细信息了

猜你喜欢

转载自ludizhang.iteye.com/blog/2308731