欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mysql实现分布式锁

程序员文章站 2022-03-06 23:50:34
...

1、最近再学分布式锁,把自己所学的一点心得分享给大家
2、首先介绍我的spring boot项目结构
mysql实现分布式锁
            
    
    博客分类: java使用mysql实现分布式锁 mysql设计模式java分布式锁 
 数据库表的结构很简单,t_lock表就一个主键字段id


mysql实现分布式锁
            
    
    博客分类: java使用mysql实现分布式锁 mysql设计模式java分布式锁 
 3、实现锁的代码

这里运用了模板设计模式

锁接口:

public interface TestLock {

 

/**

* 加锁

*/

public void getLock();

/**

* 解锁

*/

public void unLock();

 

}

锁的抽象实现类:

public abstract class AbstractTestLock implements TestLock{

 

@Override

public void getLock() {

/**

* 1、竞争锁

* 2、占有锁

* 3、任务阻塞

* 4、释放锁

*/

if(tryLock()) {

System.out.println("========获取锁的资源===========");

}else {

//等待

waitLock();

//重新获取资源

getLock();

}

}

public abstract void waitLock();

public abstract boolean tryLock();

}

 锁的实现:

@Service

public class MySqlLock extends AbstractTestLock{

 

@Resource

private LockMapper lockMapper;

 

private static final Integer ID = 1;

 

@Override

public boolean tryLock() {

try {

Lock lock = new Lock();

lock.setId(ID);

lockMapper.save(lock);

}catch (Exception e) {

return false;

}

return true;

}

 

@Override

public void unLock() {

lockMapper.delete(ID);

}

 

@Override

public void waitLock() {

try {

Thread.currentThread().sleep(10);

}catch (Exception e) {

e.printStackTrace();

}

}

 

}

仿照订单生成:

public class OrderGenerator {

// 全局订单号

public static int num = 0;

 

public String getNumber() {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

return sdf.format(new Date())+"-"+ ++num;

}

}

 

4、测试

public class MysqlLockTest extends LockApplicationTests{

 

public OrderGenerator generator = new OrderGenerator();

 

@Resource

private TestLock lock;

 

@Test

public void testGetOrderNum() throws InterruptedException {

System.out.println("=======生成唯一订单号==========");

for(int i=0; i< 50 ; i++) {

new Thread(

(Runnable) () -> { getNumber(); }

).start();

}

Thread.currentThread().join();

}

 

private void getNumber() {

try {

lock.getLock();

String number = generator.getNumber();

System.out.println(Thread.currentThread().getName() + ",生成订单ID:"+ number);

}catch (Exception e) {

e.printStackTrace();

}finally {

lock.unLock();

}

}

 

}

 

测试结果:


mysql实现分布式锁
            
    
    博客分类: java使用mysql实现分布式锁 mysql设计模式java分布式锁 
 可以看见总共生成了50个订单号,没有重复出现同样的订单号,这样子就实现了用mysql实现分布式锁。

 

5、使用mysql实现分布式锁的弊端:

    a、性能差,无法适应高并发场景,众所周知,mysql的并发瓶颈在300-700之间,当然也有可能达不到,所以一旦并发超过700的话,那么mysql就没法应用于此场景;

    b、容易死锁,一旦数据库中数据一开始有数据,那么就会一直处于死锁状态,或者删除数据失败,那么也会一直处于死锁;

    c、无法优雅的实现阻塞式锁。