通過Expire實現Redis鎖機制
阿新 • • 發佈:2018-11-06
在我們的業務系統中,可能因為某種原因,使用者會不斷的點選表單提交按鈕,為了較少對系統的 無意義訪問、暴力提交
以及使用者體驗,我們利用redis的過期時間簡單的實現了一種Redis鎖
當用戶提交表單的時候,我們通過對錶單資料以及使用者唯一標識例如userNo
進行加密,當做我們快取的唯一key
import java.security.MessageDigest;
public static String genLockKey(String formData, String userNo){
StringBuilder builder = new StringBuilder ();
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
StringBuffer lockKey = new StringBuffer("");
lockKey.append(userNo);
lockKey.append(formData);
md.update( lockKey.toString().getBytes() );
for ( byte b : md.digest() ){
builder.append( Integer.toHexString( ( b >> 4) & 0xf ) );
builder.append( Integer.toHexString( b & 0xf ) );
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return builder.toString();
}
然後我們判斷判斷redis 中是否快取了這個key,如果有快取,則提醒使用者不要重複提交,否則我們做redis快取
String lockKey = CryptUtils.genLockKey(formData, user.getNo());
if (RedisLock.isLock(lockKey)) {
// 不能重複提交
logger.error("提交出錯 - 不能重複提交報銷單!");
returnVo.setMsg("溫馨提示 - 不能重複提交報銷單!");
return JsonUtils.toJson(returnVo);
}
RedisLock.lock(lockKey, 2);
//.....剩餘的業務邏輯
接下來上我們RedisLock
的實現
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.RedisTemplate;
import com.ys.tools.common.SpringContextHolder;
public class RedisLock {
/**
* 加鎖
*
* @param key
* @param minutes
* 失效的分鐘數
*/
public static void lock(String key, int seconds) {
getRedisTemplate().opsForValue().set(key, key, seconds,
TimeUnit.SECONDS);
}
/**
* 判斷是否還在鎖定狀態
*
* @param key
* @return true 鎖定 false 已經解除鎖定
*/
public static boolean isLock(String key) {
Long flag = getRedisTemplate().getExpire(key);
return flag > 0;
}
/**
* 解鎖
* @param key
*/
public static void unLock(String key) {
getRedisTemplate().delete(key);
}
private static RedisTemplate<String, String> getRedisTemplate() {
return SpringContextHolder.getBean("redisTemplate");
}
}
其實業務邏輯很簡單,思想也很簡單。
對錶單資料進行快取並設定過期時間,如果過期時間內點選按鈕 快取存在 ,則進行頁面提示,如果不存在快取則進行業務處理以及增加快取防止重複點選 So Easy~~