利用redis分佈式鎖解決高併發問題

SETNX命令簡介

SETNX key value
將key的值設爲value,並且僅當key不存在。
若給定的key已經存在,則SETNX不做任何操作。
SETNX 是SET if Not eXists的簡寫。
返回整數,具體爲

  • 1,當 key 的值被設置
  • 0,當 key 的值沒被設置

實現分佈式事務的java代碼通用方法

 

public Boolean getHadoopLock(String lock) {

		// 利用lambda表達式
		return (Boolean) redisTemplate.execute( (RedisCallback) connection -> {

			long expireAt = System.currentTimeMillis() + RedisPrefixKeyConst.LOCK_EXPIRE + 1;
			Boolean acquire = connection.setNX( lock.getBytes(), String.valueOf( expireAt ).getBytes() );

			if (acquire) {
				return true;
			} else {

				byte[] value = connection.get( lock.getBytes() );

				if (Objects.nonNull( value ) && value.length > 0) {

					long expireTime = Long.parseLong( new String( value ) );

					if (expireTime < System.currentTimeMillis()) {
						// 如果鎖已經過期
						byte[] oldValue = connection.getSet( lock.getBytes(),
								String.valueOf( System.currentTimeMillis() + RedisPrefixKeyConst.LOCK_EXPIRE + 1 ).getBytes() );
						// 防止死鎖
						return Long.parseLong( new String( oldValue ) ) < System.currentTimeMillis();
					}
				}
			}
			return false;
		} );
	}

如何正確使用分佈式鎖?

String lockKey = RedisConstant.CSDN_APPLY_LOCK_REPT;
		Boolean flag = getHadoopLock( lockKey );
		if (!flag) {
			// 設置失敗次數計數器, 當到達5次時, 返回失敗
			int failCount = 1;
			while (failCount <= 5) {
				// 等待100ms重試
				try {
					Thread.sleep( 100l );
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if (getHadoopLock( lockKey )) {
					// 執行邏輯操作
					flag = true;
				} else {
					failCount++;
				}
			}
			return ;
		}

     //如果獲取到鎖的話,就執行相應的的代碼
     if(flag){
            /**
            此處放置需要要高併發的代碼
           
            */
           //代碼執行成功則釋放鎖
           redisTemplate.delete( lockKey );

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章