Skip to content

Latest commit

 

History

History
32 lines (22 loc) · 1.84 KB

分布式锁原理探究.md

File metadata and controls

32 lines (22 loc) · 1.84 KB

来源:https://gitbook.cn/books/5b24922172342470d7d17ad6/index.html

使用数据库悲观锁来实现分布式锁

  1. 需要设置自动提交为 false,即使用手动提交
  2. 悲观锁常用例子:select * from tableName where id = ? for update

在事务没有被提交之前,这个锁是一直都存在的。所以可以在事务提交之前做业务处理的逻辑。

但是在高并发的情况下,只有一个线程获得了锁,其它的线程读被挂起。也就是说每一个被挂起的线程都持有了一个数据库连接,导致数据库连接被占用完,会导致正常的业务不能访问数据库。

使用 Redis 实现分布式锁

Redis 提供了 setnx 函数来保证原子性。通过这个函数来设置一个唯一的值来获取锁,在释放的时候通过 get 方法来获取这个唯一的值,判断是否跟之前设置的值相等。如果相等,则表明是当前线程获取的锁,则通过 del 方法删除,否则不做处理。 由于 getdel 不是原子性的操作,所以会导致误删。

但是 Redis 有一个叫做 eval 的函数,支持 Lua 脚本执行,并且能够保证脚本执行的原子性,也就是在执行脚本期间,其它执行 Redis 命令的线程都会被阻塞。

if redis.call('get', KEYS[1]) == ARGV[1] 
then 
    return redis.call('del', KEYS[1])
else 
    return 0 
end

使用 Zookeeper 实现分布式锁

  1. 创建临时节点
  2. 遍历根节点下的子节点,判断自己节点的编号是不是最小。如果是则表示获取到了锁;如果不是,则获取比自己小一号的节点,然后监听该节点,并挂起当前线程
  3. 当最小编号的线程获取锁,处理完业务之后就删除自己对应的节点,删除了之后,比自己大一号的节点会获取锁,线程从阻塞变成运行。