1. 程式人生 > 資料庫 >實現redis分散式鎖

實現redis分散式鎖

因專案需要,需要對快取中資料進行頻繁的讀寫操作,為了防止併發寫覆蓋問題,在程式中加了redis實現的分散式鎖來控制併發寫的場景。

先上程式碼,後期更新。

	/**
	 * 更新充值碼中已使用次數
	 *
	 * @param request
	 */
	private void updateRechargeCodeCache(RechargeByCodeRequest request) {
		// 最大重試次數
		int retryTimes = 10;
		// 獲取充值碼資訊
		String lockKey = "recharge_card_" + request.getChannel() + "_" + request.getRechargeCode() + "_lock";
		String rechargeCodeKey = "recharge_card_" + request.getChannel() + "_" + request.getRechargeCode();
		LoggerUtils.logBizInfo("updateRechargeCodeCache,lockKey:" + lockKey + "rechargeCodeKey:" + rechargeCodeKey);
		try {
			for (int i=0; i<retryTimes; i++) {
				// 獲取分散式鎖
				if (marketCacheService.setnx(lockKey, "1", 1L, TimeUnit.SECONDS)) {
					LoggerUtils.logBizInfo("updateRechargeCodeCache,lockKey:" + lockKey + ",加鎖成功");
					String rechargeCodeValue = marketCacheService.get(rechargeCodeKey);
					LoggerUtils.logBizInfo("updateRechargeCodeCache,更新前:" + rechargeCodeValue);
					if (StringUtils.isEmpty(rechargeCodeValue)) {
						throw new MarketApplicationException(MktResultCodeEnum.SCAN_CODE_INVALID);
					}
					RechargeCodeModel rechargeCodeModel = BaseDto.fromJson(rechargeCodeValue, new TypeReference<RechargeCodeModel>() {});
					// 更新充值碼使用次數
					rechargeCodeModel.setUsedTimes(rechargeCodeModel.getUsedTimes() + 1);
					marketCacheService.set(rechargeCodeKey, rechargeCodeModel.toString(), 60L, TimeUnit.DAYS);
					LoggerUtils.logBizInfo("updateRechargeCodeCache,更新後:" + marketCacheService.get(rechargeCodeKey));
					// 刪除分散式鎖
					marketCacheService.delete(lockKey);
					LoggerUtils.logBizInfo("updateRechargeCodeCache,lockKey:" + lockKey + ",刪除鎖成功");

					break;
				} else {
					LoggerUtils.logBizInfo("updateRechargeCodeCache,lockKey:" + lockKey + ",加鎖失敗,重試次數:" + i);
					// 休眠10毫秒後重試
					Thread.sleep(10L);
				}
			}
		} catch (Exception e) {
			LoggerUtils.logBizError("更新充值碼中已使用次數失敗:" + e);
		}
	}