1,利用insert 和 delete控制數據記錄來實現鎖
2,利用mysql自帶鎖
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "EX";
private static final Long RELEASE_SUCCESS = 1L;
/**
* 嘗試獲取分佈式鎖
* @param jedis Redis客戶端
* @param lockKey 鎖
* @param requestId 請求標識
* @param expireTime 超期時間
* @return 是否獲取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
try{
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
}finally{
if(jedis != null){
jedis.close();
}
}
return false;
}
/**
* 釋放分佈式鎖
* @param jedis Redis客戶端
* @param lockKey 鎖
* @param requestId 請求標識
* @return 是否釋放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
try{
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
}finally{
if(jedis != null){
jedis.close();
}
}
return false;
}
/**
* 判斷鎖是否存在
* @param jedis Redis客戶端
* @param lockKey 鎖
* @param requestId 請求標識
* @return 鎖是否存在
*/
public static boolean checkDistributedLock(Jedis jedis, String lockKey) {
try{
String value = jedis.get(lockKey);
if (StringUtils.isEmpty(value)) {
return true;
}
}finally{
jedis.close();
}
return false;
}
使用緩存實現分佈式鎖的優點
性能好。
使用緩存實現分佈式鎖的缺點
實現過於負責,需要考慮的因素太多。
創建臨時節點
可以解決單機,鎖無法釋放,非阻塞,不可衝入,非公平的問題
總結
從理解的難易程度角度(從低到高)
數據庫 > 緩存 > Zookeeper
從實現的複雜性角度(從低到高)
Zookeeper > 緩存 > 數據庫
從性能角度(從高到低)
緩存 > Zookeeper >= 數據庫
從可靠性角度(從高到低)
Zookeeper > 緩存 > 數據庫
參考:https://blog.csdn.net/u010963948/article/details/79006572