0
点赞
收藏
分享

微信扫一扫

事务失效导致线上事故

最后的执着 2022-02-08 阅读 71

先说结果

数据不一致

对外接口中事务部分成功,部分失败,导致数据异常

一个插入方法需要给不同业务插入数据,调用不同方法,部分表数据成功,部分表数据失败

代码调用链中事务有嵌套设置

外层异常,内层正常插入,导致数据异常,操作的是同以数据库,不同的代码包,用POM依赖调用
    原因分析:
        1.事务时效
            1.private、static、final的使用
            解决方法:不在类和方法上使用此类关键字

            2.通过this.xxx(调用当前类的方法)
            使用xml配置方式暴露代理对象.然后在service中通过代理对象AopContext.currentProxy()去调用方法。
        2.事务传递生效规则
            1.内部使用父层事务,如果父层级没有事务,开启新事务

               2.方法内部多层级调用都需要支持事务回滚

pom中依赖的导致事务无法生效

决定用分布式锁redisson

import org.redisson.Redisson;
import org.redisson.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.redisson.api.RedissonClient;

/**
 * @Date 2022/2/8 20:29
 * @Version 1.0
 */

@Configuration
public class RedissionConfig {
    Logger log = LoggerFactory.getLogger(RedissionConfig.class);
    
    @Value("${spring.redis.host}")
    String redisIp;
    
    @Value("${spring.redis.port}")
    String redisPort;
    
    @Value("${spring.redis.password}")
    String redisPassword;
    
    @Bean(name="redissonClient")
    public RedissonClient init(){
        Config config = new Config();
        String url = "redis://"+redisIp+":"+redisPort;
        log.info(url);
        config.useSingleServer().setAddress(url).setPassword(redisPassword);
        config.useSingleServer().setConnectionMinimumIdleSize(10);
        RedissonClient redissonClient = Redisson.create(config);
        log.info("初始化RedissonClient成功");
        return redissonClient;
    }
}

业务代码中直接加锁解决

String dataKey = winnerCandidateVO.getDataKey();
RLock lock = redissonClient.getLock("stock:" + dataKey);
lock.lock(10, TimeUnit.SECONDS);  

lock.unlock();

通过加锁确保业务的完整唯一性,记得要释放锁

redisson自带有自旋锁和释放自己加的锁,不用担心多线程释放其他线程的锁

举报

相关推荐

0 条评论