1. 程式人生 > >兩種分布式鎖實現方案(一)

兩種分布式鎖實現方案(一)

如果 pla 並發訪問 可用性 工廠類 mut con comm comment

一。為何使用分布式鎖?
當應用服務器數量超過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. private static Map<String, DistributedLockUtil> instances = new ConcurrentHashMap();
    12. public static DistributedLockUtil getInstance(String schema) {
    13. DistributedLockUtil u = instances.get(schema);
    14. if (u == null) {
    15. synchronized (schemeLock) {
    16. u = instances.get(schema);
    17. if (u == null) {
    18. u = new DistributedLockUtil(schema);
    19. instances.put(schema, u);
    20. }
    21. }
    22. }
    23. return u;
    24. }
    25. private DistributedLockUtil(String schema) {
    26. this.schema = schema;
    27. }
    28. private Object getMutex(String key) {
    29. Object mx = mutexLockMap.get(key);
    30. if (mx == null) {
    31. synchronized (mutexLock) {
    32. mx = mutexLockMap.get(key);
    33. if (mx == null) {
    34. mx = new Object();
    35. mutexLockMap.put(key, mx);
    36. }
    37. }
    38. }
    39. return mx;
    40. }
    41. private DistributedReentrantLock getLock(String key) {
    42. DistributedReentrantLock lock = cache.get(key);
    43. if (lock == null) {
    44. synchronized (getMutex(key)) {
    45. lock = cache.get(key);
    46. if (lock == null) {
    47. lock = new DistributedReentrantLock(key, schema);
    48. cache.put(key, lock);
    49. }
    50. }
    51. }
    52. return lock;
    53. }
    54. public void reset() {
    55. for (String s : cache.keySet()) {
    56. getLock(s).unlock();
    57. }
    58. }
    59. /**
    60. * 嘗試加鎖
    61. * 如果當前線程已經擁有該鎖的話,直接返回false,表示不用再次加鎖,此時不應該再調用unlock進行解鎖
    62. *
    63. * @param key
    64. * @return
    65. * @throws InterruptedException
    66. * @throws KeeperException
    67. */
    68. public LockStat lock(String key) throws InterruptedException, KeeperException {
    69. if (getLock(key).isOwner()) {
    70. return LockStat.NONEED;
    71. }
    72. getLock(key).lock();
    73. return LockStat.SUCCESS;
    74. }
    75. public void clearLock(String key) throws InterruptedException, KeeperException {
    76. synchronized (getMutex(key)) {
    77. DistributedReentrantLock l = cache.get(key);
    78. l.clear();
    79. cache.remove(key);
    80. }
    81. }
    82. public void unlock(String key, LockStat stat) throws InterruptedException, KeeperException {
    83. unlock(key, stat, false);
    84. }
    85. public void unlock(String key, LockStat stat, boolean keepalive) throws InterruptedException, KeeperException {
    86. if (stat == null) return;
    87. if (LockStat.SUCCESS.equals(stat)) {
    88. DistributedReentrantLock lock = getLock(key);
    89. boolean hasWaiter = lock.unlock();
    90. if (!hasWaiter && !keepalive) {
    91. synchronized (getMutex(key)) {
    92. lock.clear();
    93. cache.remove(key);
    94. }
    95. }
    96. }
    97. }
    98. public static enum LockStat {
    99. NONEED,
    100. SUCCESS
    101. }
    102. }

兩種分布式鎖實現方案(一)