redis分布式锁解决多个应用进程间同步操作
整理了很多网上文档 发现都没有解决如下问题。。。
参考
http://www.cnblogs.com/it-cen/p/4984272.html
...
1.时间同步问题
2.在一个进程cash后失效时间后自动释放锁
3.有些多线程race condition没有考虑到
以下java版本实现彻底解决 充分测试
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