流水号产生改用悲观锁

业务场景:

平台中有一个流水号功能,之前是采用乐观锁。使用乐观锁的问题是,当当前更新数据时,没有更新的时候,还是需要返回流水号。

这就不得不重新再获取,在平台的用户访问并发很大的时候,这个乐观锁会循环很多次,导致性能下降。

解决方法:

使用悲观锁,由数据库来锁定,当退出该方法时,数据库自动释放锁。

平台配置方法:

<tx:method name="genSequenceNo" propagation="REQUIRES_NEW" isolation="READ_COMMITTED" />

REQUIRES_NEW:

创建一个新事务,如果当前存在事务,将这个事务挂起。也就是说如果当前存在事务,那么将当前的事务挂起,并开启一个新事务去执行REQUIRES_NEW标志的方法。
先来总结一下结果:
1.标志REQUIRES_NEW会新开启事务,外层事务不会影响内部事务的提交/回滚
2.标志REQUIRES_NEW的内部事务的异常,会影响外部事务的回滚

测试方法使用多线程模拟实际环境:

package com.redxun.test.sys.manager;

import java.util.List;

import com.redxun.core.util.AppBeanUtil;
import com.redxun.sys.core.manager.SysSeqIdManager;

public class SysSeqNoThread implements Runnable {
    
    private List<String> list;
    
    public SysSeqNoThread(List<String> list){
        this.list=list;
    }

    @Override
    public void run() {
        SysSeqIdManager mgr=AppBeanUtil.getBean(SysSeqIdManager.class);
        for(int i=0;i<1000;i++){
            String no=mgr.genSequenceNo("ss", "1");
            this.list.add(no);
        }         
    }
}
package com.redxun.test.sys.manager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.junit.Test;

import com.redxun.test.BaseTestCase;

public class SysSeqIdTest extends BaseTestCase{
    
    @Test
    public void getSeqNo() throws InterruptedException{
        List<String> list = Collections.synchronizedList(new ArrayList<String>());
        long start=System.currentTimeMillis();
        Thread t1=new Thread(new SysSeqNoThread(list));
        Thread t2=new Thread(new SysSeqNoThread(list));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        
        System.err.println(list.size());
        System.err.println(System.currentTimeMillis()-start);
        System.err.println("ok");
    }

}

测试了一下 产生2000个流水号,每个1.3毫秒,性能应该ok。

原文地址:https://www.cnblogs.com/yg_zhang/p/10785466.html