解决Spring事务和锁冲突失效问题

1.问题描述

  A服务作为下游服务,就需要扛住上游服务的各种调用方式;某天上游调用的方式优化改进上线后,A服务的某接口开始出现重复数据处理问题,针对此问题当时最直观的猜想是redis分布式锁未起作用,比如redis服务故障或者什么原因?排查后发现是spring事物与锁使用不当造成的问题

代码案例

    @Transactional
    override fun doBusinessLogic(params: Any): Any? {
  
        ... 
        
        val lock = redisLock.createLock("xxxx_key")
        lock.lock()
        try {

           ...
           
        } finally {
            lock.unlock()
        }

这种写法的问题在于:当锁释放的时候事物还没有结束,此时另一个请求进入锁同步区域时读不到事物未提交的数据(这里数据库隔离级别采用的是读已提交)

2.改进

  • 事物与锁的力度问题:锁的范围应该大于事物的范围
  • 考虑spring动态代理方法的生效条件:@Transactional注解事物是通过代理实现

正确示例

@Component
class LockTransactionalSupport {

    @Transactional(rollbackFor = [Exception::class])
    fun <R> wrapperWithTransactional(action: () -> R): R {
        return action.invoke()
    }

}



@SpringBootTest
class XxxTest {

    @Autowired
    lateinit var lockTransactionalSupport: LockTransactionalSupport

    @Autowired
    lateinit var redisLock: RedisLock

    @Test
    fun testWrapperWithTransactional() {
        val lock = redisLock.createLock("my_lock_key")

        lock.lock()
        try {
            lockTransactionalSupport.wrapperWithTransactional {
            
                ...
                
                // do db save ops
                
                ...
                
                // throw err and rollback
                throw Exception("err.")
            }
        } finally {
            lock.unlock()
        }

    }
}

将锁的范围放在事物的外层
通过LockTransactionalSupport定义的函数式编程方式,用以保证@Transactional注解可以生效(对于代理方法必须要外部直接调用,才能走真正的代理逻辑)

当然如何在锁中去执行事务操作也有其他的实现方案,比如说编码的方式自己写 开启事物、提交事物或者回滚事物等
 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring事务冲突失效问题是在并发环境下常见的挑战之一,可以采用以下方法来解决这个问题。 首先,对于Spring事务冲突失效问题,可以考虑以下策略: 1. 调整事务隔离级别:通过提高事务的隔离级别,如将隔离级别设置为Serializable,可以避免脏读、不可重复读和幻读等并发访问问题。 2. 使用乐观:在进行并发操作时,通过使用版本号或时间戳等机制来对数据进行控制,从而避免冲突。 3. 使用悲观:在进行并发操作时,通过对数据进行加,限制其他事务对数据的访问,避免冲突。 4. 使用分布式锁:在分布式环境下,通过使用分布式锁来控制并发访问,避免冲突。 其次,对于冲突失效问题,可以采取以下方法: 1. 减小粒度:将应用到最小的代码块,避免住不需要同步的代码部分,从而减少冲突的可能性。 2. 使用更合适的策略:在并发情况下,选择合适的策略,如公平、非公平、读写等,以提高并发访问效率。 3. 使用分布式锁:在分布式环境下,使用分布式锁来对资源进行同步处理,避免冲突失效问题。 4. 优化系统设计:通过优化系统架构和设计,尽可能减少并发访问的需求,从而降低冲突的可能性。 总之,解决Spring事务冲突失效问题需要综合考虑事务隔离级别、策略、粒度和系统设计等多个因素。通过合理选择和调整这些策略,可以有效地缓解并发环境下的问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值