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

分布式锁

程序员文章站 2022-07-05 11:50:50
...
  1. 数据库实现分布式锁

    1.1 利用主键唯一规则:
    ​ 数据库的唯一主键,不能重复。利用主键唯一规则,在争抢锁的时候向数据库中写一条记录,记录包括锁的id、当前占用锁的线程名、重入的次数和创建时间等信息。如果插入成功表示当前线程获取到了锁,如果插入失败证明锁被其他人占用,等待一回儿继续重试,直到抢到锁或者超时为止。

    • 获取锁

      public Boolean lock(String lockId) {
        int count = 0;
        //重试4次
        while(count < 4) {
          try{
            "insert into lock(id, count, lockName, addTime)";
            if(插入成功) {
              //获得锁
              return true;
            }
          } catch(Exception e) {
            
          }
          
          Thread.sleep(1000);
          count++;
        }
      }
      
    • 释放锁

      public Boolean release(String lockId) {
        "delete from lock where id = lockId";
        if (删除成功) {
          return true;
        } 
        return false;
      }
      

    1.2 利用MySql行锁的特性:

    • 获取锁

      public void lock() {
        connection.setAutoCommit(false);
        int count = 0;
        while(count < 4) {
          try{
            //通过for update 操作,数据库就会对该行记录加上record lock,从而阻塞其他人对该记录的操作
            select * from lock where lock_name = xxx for update;
            if(not null) {
              return ture;
            }
          } catch (Exception e) {
            
          }
          
          //没有获得锁
          sleep(1000);
          count++;
        }
        
        throw new LockException();
      }
      
    • 释放锁

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

    缺点:
    性能不高,SQL超时异常

  2. 缓存实现分布式锁
    使用Redis的setNX来实现分布式锁(如果指定的key存在,setNX失败;否则执行Set操作并返回成功)

    • 获取锁
      为key设置一个过期时间(即使获取锁的客户端挂了,过期后也会自动释放锁)
      对key的值进行判断是否过期

      public void lock() {
        for() {
          result = setNX lock_ley (value, expireTime);
          if(result || (now() > get lock && now() > (getSet lock expireTime))) {
            return true;
          }
          
          Thread.sleep(1000);
        }
      }
      
    • 释放锁

      public void release() {
        if(now() < get lock) {
          del lock
        }
      }
      
  3. zookeeper实现分布式锁

  4. 分布式锁实现原理

    • 分布式锁的实现
      1. 怎么获取锁
        能够提供一种方式,多个客户端并发操作,只能有一个客户端能满足相应的要求
      2. 怎么释放锁
        • 正常情况下释放锁
        • 异常情况下如何释放锁(即释放锁的操作没有被执行,如挂掉、没执行成功等)
          Redis正常情况下释放锁是删除key,异常情况下,只能通过超时时间自动释放
          ZooKeeper正常情况下释放锁是删除临时节点,异常情况下,服务器也会主动删除临时节点
      3. 怎么得知锁被释放了
        • 没有获取锁的客户端不断尝试获取锁
        • 服务器端通知客户端锁被释放了
          ZooKeeper通过注册watcher来得到锁释放的通知