redis分佈式鎖解決多個應用進程間同步操做html
整理了不少網上文檔 發現都沒有解決以下問題。。。java
參考redis
http://www.cnblogs.com/it-cen/p/4984272.html多線程
...dom
1.時間同步問題分佈式
2.在一個進程cash後失效時間後自動釋放鎖ide
3.有些多線程race condition沒有考慮到測試
如下java版本實現完全解決 充分測試 ui
import java.util.List; import java.util.UUID; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisException; /** * Jedis實現分佈式鎖 * * @author 三文魚 * */ public class DistributionLock { private final JedisPool jedisPool; public DistributionLock(JedisPool jedisPool) { this.jedisPool = jedisPool; } /** * 獲取分佈式鎖 * * @param lockName * 競爭獲取鎖key * @param acquireTimeoutInMS * 獲取鎖超時時間 * @param lockTimeoutInMS * 鎖的超時時間 * @return 獲取鎖標識 */ public String acquireLockWithTimeout(String lockName, long acquireTimeoutInMS, long lockTimeoutInMS) { Jedis conn = null; boolean broken = false; String retIdentifier = null; try { conn = jedisPool.getResource(); String identifier = UUID.randomUUID().toString(); String lockKey = "lock:" + lockName; int lockExpire = (int) (lockTimeoutInMS / 1000); long end = System.currentTimeMillis() + acquireTimeoutInMS; while (System.currentTimeMillis() < end) { if (conn.setnx(lockKey, identifier) == 1) { conn.expire(lockKey, lockExpire); retIdentifier = identifier; } if (conn.ttl(lockKey) == -1) { conn.expire(lockKey, lockExpire); } try { Thread.sleep(10); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } catch (JedisException je) { if (conn != null) { broken = true; jedisPool.returnBrokenResource(conn); } } finally { if (conn != null && !broken) { jedisPool.returnResource(conn); } } return retIdentifier; } /** * 釋放鎖 * @param lockName 競爭獲取鎖key * @param identifier 釋放鎖標識 * @return */ public boolean releaseLock(String lockName, String identifier) { Jedis conn = null; boolean broken = false; String lockKey = "lock:" + lockName; boolean retFlag = false; try { conn = jedisPool.getResource(); while (true) { conn.watch(lockKey); if (identifier.equals(conn.get(lockKey))) { Transaction trans = conn.multi(); trans.del(lockKey); List<Object> results = trans.exec(); if (results == null) { continue; } retFlag = true; } conn.unwatch(); break; } } catch (JedisException je) { if (conn != null) { broken = true; jedisPool.returnBrokenResource(conn); } } finally { if (conn != null && !broken) { jedisPool.returnResource(conn); } } return retFlag; } }