• 两种分布式锁实现方案(一)


    一。为何使用分布式锁?
    当应用服务器数量超过1台,对相同数据的访问可能造成访问冲突(特别是写冲突)。单纯使用关系数据库比如MYSQL的应用可以借助于事务来实现锁,也可以使用版本号等实现乐观锁,最大的缺陷就是可用性降低(性能差)。对于GLEASY这种满足大规模并发访问请求的应用来说,使用数据库事务来实现数据库就有些捉襟见肘了。另外对于一些不依赖数据库的应用,比如分布式文件系统,为了保证同一文件在大量读写操作情况下的正确性,必须引入分布式锁来约束对同一文件的并发操作。

    二。对分布式锁的要求
    1.高性能(分布式锁不能成为系统的性能瓶颈)
    2.避免死锁(拿到锁的结点挂掉不会导致其它结点永远无法继续)
    3.支持锁重入

    三。方案1,基于zookeeper的分布式锁

    [java] view plain copy
     
      1. /** 
      2.  * DistributedLockUtil.java 
      3.  * 分布式锁工厂类,所有分布式请求都由该工厂类负责 
      4.  */  
      5. public class DistributedLockUtil {  
      6.     private static Object schemeLock = new Object();  
      7.     private static Object mutexLock = new Object();  
      8.     private static Map<String, Object> mutexLockMap = new ConcurrentHashMap();  
      9.     private String schema;  
      10.     private Map<String, DistributedReentrantLock> cache = new ConcurrentHashMap<String, DistributedReentrantLock>();  
      11.   
      12.     private static Map<String, DistributedLockUtil> instances = new ConcurrentHashMap();  
      13.   
      14.     public static DistributedLockUtil getInstance(String schema) {  
      15.         DistributedLockUtil u = instances.get(schema);  
      16.         if (u == null) {  
      17.             synchronized (schemeLock) {  
      18.                 u = instances.get(schema);  
      19.                 if (u == null) {  
      20.                     u = new DistributedLockUtil(schema);  
      21.                     instances.put(schema, u);  
      22.                 }  
      23.             }  
      24.         }  
      25.         return u;  
      26.     }  
      27.   
      28.     private DistributedLockUtil(String schema) {  
      29.         this.schema = schema;  
      30.     }  
      31.   
      32.     private Object getMutex(String key) {  
      33.         Object mx = mutexLockMap.get(key);  
      34.         if (mx == null) {  
      35.             synchronized (mutexLock) {  
      36.                 mx = mutexLockMap.get(key);  
      37.                 if (mx == null) {  
      38.                     mx = new Object();  
      39.                     mutexLockMap.put(key, mx);  
      40.                 }  
      41.             }  
      42.         }  
      43.         return mx;  
      44.     }  
      45.   
      46.     private DistributedReentrantLock getLock(String key) {  
      47.         DistributedReentrantLock lock = cache.get(key);  
      48.         if (lock == null) {  
      49.             synchronized (getMutex(key)) {  
      50.                 lock = cache.get(key);  
      51.                 if (lock == null) {  
      52.                     lock = new DistributedReentrantLock(key, schema);  
      53.                     cache.put(key, lock);  
      54.                 }  
      55.             }  
      56.         }  
      57.         return lock;  
      58.     }  
      59.   
      60.     public void reset() {  
      61.         for (String s : cache.keySet()) {  
      62.             getLock(s).unlock();  
      63.         }  
      64.     }  
      65.   
      66.     /** 
      67.      * 尝试加锁 
      68.      * 如果当前线程已经拥有该锁的话,直接返回false,表示不用再次加锁,此时不应该再调用unlock进行解锁 
      69.      * 
      70.      * @param key 
      71.      * @return 
      72.      * @throws InterruptedException 
      73.      * @throws KeeperException 
      74.      */  
      75.     public LockStat lock(String key) throws InterruptedException, KeeperException {  
      76.         if (getLock(key).isOwner()) {  
      77.             return LockStat.NONEED;  
      78.         }  
      79.         getLock(key).lock();  
      80.         return LockStat.SUCCESS;  
      81.     }  
      82.   
      83.     public void clearLock(String key) throws InterruptedException, KeeperException {  
      84.         synchronized (getMutex(key)) {  
      85.             DistributedReentrantLock l = cache.get(key);  
      86.             l.clear();  
      87.             cache.remove(key);  
      88.         }  
      89.     }  
      90.   
      91.     public void unlock(String key, LockStat stat) throws InterruptedException, KeeperException {  
      92.         unlock(key, stat, false);  
      93.     }  
      94.   
      95.     public void unlock(String key, LockStat stat, boolean keepalive) throws InterruptedException, KeeperException {  
      96.         if (stat == null) return;  
      97.         if (LockStat.SUCCESS.equals(stat)) {  
      98.             DistributedReentrantLock lock = getLock(key);  
      99.             boolean hasWaiter = lock.unlock();  
      100.             if (!hasWaiter && !keepalive) {  
      101.                 synchronized (getMutex(key)) {  
      102.                     lock.clear();  
      103.                     cache.remove(key);  
      104.                 }  
      105.             }  
      106.         }  
      107.     }  
      108.   
      109.     public static enum LockStat {  
      110.         NONEED,  
      111.         SUCCESS  
      112.     }  
      113. }  
  • 相关阅读:
    JSP基础语法
    Tomcat服务器的安装及配置
    数据库连接失败出现4064错误
    错误页跳转
    Eclipse配置jstl标准标签库详解
    tomcat文件目录结构及功能介绍
    警告: [SetPropertiesRule]{Context/Loader} Setting property 'useSystemClassLoaderAsParent' to 'false' did not find a matching property.
    tomcat:A docBase * inside the host appBase has been specifi, and will be ignored
    Prim算法
    (值类型引用类型)和null的关系
  • 原文地址:https://www.cnblogs.com/panxuejun/p/8360537.html
Copyright © 2020-2023  润新知