分布式锁(1) ----- 介绍和基于数据库的分布式锁

分布式锁系列文章

分布式锁(1) ----- 介绍和基于数据库的分布式锁
分布式锁(2) ----- 基于redis的分布式锁
分布式锁(3) ----- 基于zookeeper的分布式锁
代码:https://github.com/shuo123/distributeLock

线程锁与分布式锁

1.java的synchronize和Lock都是属于线程锁,只能保证同一个进程内的多线程对共享变量修改访问同步。它们的原理都是设置一个可以让所有线程访问到标记,如synchronize是获取对象的monitor,而Lock类是基于AQS的volatile修饰的state。

2.分布式锁是属于进程范畴的,而且进程可以在不同的机器上。它要保证的是多个进程对共享变量修改访问同步(例如集群环境下同时修改缓存和数据库)。分布式锁也同样需要一个可以让所有进程访问到的标记(如数据库的字段,redis的数据,zookeeper的节点等)来控制同步。

实现方法

1.基于数据库的分布式锁

2.基于redis的分布式锁

3.基于zookeeper的分布式锁

基于数据库的分布式锁

基于表主键唯一

利用主键具有唯一性的性质,加锁时向数据库插入以锁名为主键的数据,解锁时删除该数据。
优化:
1.没有过期时间,如果获得锁的服务解锁失败,将导致其他服务无法获得锁。网上也有解决方法:增加过期时间字段,定期清除过期锁数据。
2.重入性,增加获得锁服务的标记字段。

基于版本号字段

为表结构增加版本号字段,每次获取数据将版本号获取到,下次修改数据时判断当前版本是否该版本号。思路是与mysql的mvcc机制差不多的。

基于排他锁

public boolean lock(){
    connection.setAutoCommit(false)
    while(true){
        try{
            result = select * from lock where lockName=xxx for update;
            if(result==null){
                return true;
            }
        }catch(Exception e){
 
        }
        sleep(1000);
    }
    return false;
}


public void unlock(){
    connection.commit();
}

1.该方法是基于mysql的innodb的行级锁,所以lockName字段必须有索引存在,但因此也有一个问题,是否使用索引是有mysql来判断的,如果mysql认为全表查询更快,会使用表锁,那将会影响lock表的所有分布式锁。

2.for update会在执行失败是一直阻塞到成功。

优缺点

优点:容易实现理解

缺点:占用数据库连接,性能较低。

参考资料

https://www.cnblogs.com/seesun2012/p/9214653.html

posted @ 2019-03-28 23:40  wuweishuo  阅读(1196)  评论(0编辑  收藏  举报