• 为什么要是要使用分布式锁
      • 在分布式环境下,多个线程并发访问同一共享资源,无法保证原子性,导致数据不一致的现象, synchornized,lock等锁是jvm级别的,只能锁住同一个 服务器,当分布式集群的情况下,其他的节点时可以访问的, 这样的本地锁是锁不住其他集群节点,无法解决分布式锁的问题
    • redis实现原理
      • 加锁
        • 当一个线程访问的时候,就会在redis中创建一个key 就是加锁, 其他线程来访问的时候 ,当redis中的key还存在,就无法获取锁, 只有等锁释放掉,才可以进行访问
        • key创建的时候使用的是lua脚本,保证创建key是一个原子操作,这个key的默认过期时间是30s,分布式锁的,
      • 释放锁
        • key删除机制: 业务执行完就会执行unlock,如果业务没有执行完,但是时间到了过期时间,也不会立刻删除,有一个watch Dog看门狗默认会每隔10s检查当前线程是否还存活,如果还存活并且持有锁,看门狗会自动的给当前线程续约,重置超时间
        • 且key对应有一个value和一个客户端id(uuid+线程id),value保存的是每一个客户端加锁的次数,同一个客户端可以重复加锁,这就是可重入性,删除锁需要判断value是否为0
    • zookepper实现
      • 多个客户端创建一个共同的节点(文件夹)
      • 只会有一个客户端创建成功,创建成功的就会执行业务,其他的线程来创建的时候发现已经有了文件节点,就抢不到锁,但是可以监听(watch)这个节点,当这个文件节点删除了,就会立马通知这个线程, 线程就可以创建文件节点了
      • 节点类型
        • 持久节点
        • 持久顺序节点
        • 临时节点 (连接关闭就会删除节点)
        • 临时顺序节点
      • 有序的节点在创建的时候会在节点文件名后面 拼接一个0000001的数字,都会创建成功,先创建的就是获取锁,每创建一个就加1,且只监听上一个节点,上一个节点释放锁之后,只会通知下一个节点, 并不会通知所有的节点,这样比普通节点效率更高,
      • 通知方式:
        • 锁释放后会自动通知监听他的节点(基于回调函数)
    • 数据库实现
      • 基于数据库行锁(for update)
    • 也可以使用原子类,保证原子操作