利用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 );

}

 

 

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