分佈式部署中不可避免用到分佈式鎖,目前比較經常使用的實現方式通常有基於數據庫的樂觀鎖、基於redis的分佈式鎖和基於zookeeper的分佈式鎖。本文只說redis的實現方式,使用jedis做爲鏈接器。redis
比較簡單,直接上代碼吧。數據庫
public class PaasLock { private static final String KEY_NNXX = "NX"; private static final String KEY_EXPX = "PX"; private static final String KEY_SUCCESS = "OK"; private static final String KEY_PREFIX = "paas.lock."; private static final Long KEY_RELEASE_NUM = 1L; //影響redis行數 private static Random RANDOM = new Random(100); private static final String REDIS_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; private RedisDao redisDao; //封裝jedis private String lockKey; public PaasLock() { //使用uuid生成不重複的key this(KEY_PREFIX + UUID.randomUUID().toString().replaceAll("-", "")); } //自定義key public PaasLock(String lockKey) { if (lockKey == null || lockKey.isEmpty()) throw new RuntimeException("lockKey is null or empty . . ."); this.lockKey = KEY_PREFIX + lockKey; this.redisDao = SpringContexts.getBean(RedisDao.class); } /** * 獲取鎖 * * @param requestId * @param expireTime 毫秒,鎖自己的超時時間 * @param waitTime 毫秒,獲取鎖等待時間 * @return true獲取成功,false獲取失敗 */ public boolean tryGetDistributedLock(String requestId, long expireTime, long waitTime) { long nanoTime = System.nanoTime(); long timeOut = waitTime * 1000000; //納秒10^6 = 1毫秒 try { //循環等待鎖釋放 while (System.nanoTime() - nanoTime < timeOut) { String res = redisDao.set(this.lockKey, requestId, KEY_NNXX, KEY_EXPX, expireTime); if (KEY_SUCCESS.equals(res)) { return true;// this.lock; } Thread.currentThread().sleep(5L, RANDOM.nextInt(30)); } } catch (Exception ex) { throw new RuntimeException("locking error", ex); } return false; } /** * 釋放鎖 * * @param requestId * @return */ public boolean releaseDistributedLock(String requestId) { Object result = redisDao.eval(REDIS_SCRIPT, Collections.singletonList(this.lockKey), Collections.singletonList(requestId)); if (KEY_RELEASE_NUM.equals(result)) { //只能釋放本身的鎖,防止被別的線程釋放 System.out.println("release lock..,res=" + requestId); return true; } return false; } }
調用方法dom
PaasLock lock = new PaasLock(); if (lock.tryGetDistributedLock(resId, 3000, 30000)) { try { do ..... } finally { lock.releaseDistributedLock(resId); } } else{ ..... 其餘處理 }
參考網上一些資料改造一下,比較簡單,供你們參考。。。分佈式