首页 > 其他 > 详细

分布式锁

时间:2017-03-04 22:37:42      阅读:282      评论:0      收藏:0      [点我收藏+]

CAP理论: Consistency + Availability + Partition Fault

这3者不可能都达到,一般会牺牲强一致性,追求最终一致性。

 

分布式锁需要解决什么问题?

1)如何保证一个方法只有一个机器上的一个线程访问

2)如何并且高性能地获得锁,释放锁

3)阻塞锁

4)可重入锁

 

1.使用数据库实现

1)通过insert数据获得锁,delete数据释放锁

insert into lock(method_name) values(‘method_name‘)

delete from lock where method_name  = ‘method_name‘

优点: 简单易理解实现

缺点: a)数据库有单点故障(用多个数据库)

    b)如果释放锁失败,别的客户端永远获得不到锁(用schedule job定期清理数据)

    c)如果获得锁失败,会直接返回,不会进入队列等待直到重新获得锁(用while true阻塞)

    d)实现不了可重入锁(记住获得锁的主机信息和线程信息)

2)通过数据库自带的排它锁

public boolean tryLock(){

  connection.setAutoCommit(false);

  while(true){

    try{

      result = select * from lock where method_name = ‘method_name‘ for update

      if(result == null) return true;

    }Catch(Exception e){

    }

    sleep(1000);

    }

    return false;

}

public boolean unLock(){

  connection.commit();

}

能解决上面的 b), c) 问题, 但这个锁必须是行级锁,需要创建唯一索引,当表很小时,就算创建的是唯一索引也会被优化成表级锁。

 

2.使用缓存实现(Redis, Memcached)

获得锁: map.put(key, value)

释放锁: map.get(key)

优点: 能解决单点故障问题(集群部署),可以设置过期时间让锁自动失效,但过期时间比较难设置。

缺点: 仍然不能达到可阻塞(同样可使用while true解决),可重入(记住主机和线程信息)

 

3.使用Zookeeper实现

获得锁:创建临时结点,看是不是结点是不是最小的,如果是则获得锁

释放锁:删除临时结点

优点: 解决单点故障,重新选择leader;可阻塞,其他试图再次创建该临时结点发现自己的结点不是最小值,会设置监听器,一旦发现列表有变化则检查是否自己为最小的结点;可重入,可以将主机和线程信息作为临时结点的值;如果客户端断开连接,临时结点会自动删除,从而不释放锁。

缺点: 因为要创建和删除临时结点,而且只能通过leader服务器执行,性能可能不太好

 

分布式锁

原文:http://www.cnblogs.com/lruihan/p/6502679.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!