redis setnx 锁

/**
	 * 买家扫jp支付动态码
	  * @param scanQRCodeRequest
	  * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ScanQRCodeResponse scanQRCode(ScanQRCodeRequest scanQRCodeRequest) {
		//根据tradeNo加锁,只利用setNX的乐观锁,上锁后只能过期即可满足业务
		String tradeNo = scanQRCodeRequest.getTradeNo();
		BaseMemberInfo baseMemberInfo = WalletUtils.getTokenInfo().getMemberInfo().getBaseMemberInfo();
		String memberId = baseMemberInfo.getMemberId();
		
		String lockKey = EWALLET_SCANQRCODE_LOCK + tradeNo;
		if(redisUtil.exists(lockKey)) {
			String lockedUser = (String) redisUtil.get(lockKey);
			if(StringUtils.equals(memberId, lockedUser)) {
				return getOrderInfo(tradeNo,memberId);
			}
		}
		String result = "";
		try {
			result = (String) redisTemplate.execute(new RedisCallback() {
				@Override
				public String doInRedis(RedisConnection connection) throws DataAccessException {
					String validSeconds = scanQRCodeRequest.getValidSeconds();
					JedisCommands commands = (JedisCommands) connection.getNativeConnection();
					return commands.set(lockKey, memberId, "NX", "EX",
							Long.parseLong(validSeconds == null ? SCAN_QR_VALID_SECONDS_DEFAULT : validSeconds));
				}
			});
		} catch (Exception e) {
			log.error("set redis occured an exception", e);
			String error = WalletResponseCodeConstants.SYSTEM_ERROR.getCode();
			throw new WalletException(error, MessageResources.getMessage(error));
		}
		if (StringUtils.isEmpty(result)) {
			log.warn("tradeNo:{} is locked by {}",tradeNo,memberId);
			String error = WalletResponseCodeConstants.TRADE_HAS_LOCKED.getCode();
			throw new WalletException(error, MessageResources.getMessage(error));
		}
		
		// 变更支付订单的归属
		UpdatePayerRequest updatePayerRequest = new UpdatePayerRequest();
		String memberName = baseMemberInfo.getMemberName();
		if (StringUtils.isBlank(memberName)) {
			memberName = baseMemberInfo.getIdentitys().stream()
					.filter(identityInfo -> StringUtils.equals(identityInfo.getPlatformType(),
							WalletBussinessConstant.IDENTITY_TYPE_LOGIN_NAME.getValue()))
					.findFirst().get().getIdentity();
		}
		updatePayerRequest.setPayCstNo(memberId);
		updatePayerRequest.setPayCstName(memberName);
		updatePayerRequest.setTradeNo(tradeNo);
		tradeIntegrationService.updatePayer(updatePayerRequest);
		
		return getOrderInfo(tradeNo,memberId);
	}

key 序列化导致不能取value值

redis setnx 锁_第1张图片

key序列化 使用StringRedisSerializer

 

/**
	 * 1.项目启动时此方法先被注册成bean被spring管理  
	 * @param factory factory
	 * @return redisTemplate
	 */
	@Bean
	public RedisTemplate< Serializable , Object > redisTemplate( RedisConnectionFactory factory ) {
		RedisTemplate< Serializable , Object > template = new RedisTemplate<>();
		template.setConnectionFactory(factory);
		Jackson2JsonRedisSerializer< Object > jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);
		template.setValueSerializer(jackson2JsonRedisSerializer);
		template.setHashValueSerializer(jackson2JsonRedisSerializer);
		template.setKeySerializer(new StringRedisSerializer());
		template.setHashKeySerializer(new StringRedisSerializer());
		template.afterPropertiesSet();
		return template;
	}

value的序列化使用Jackson2JsonRedisSerializer ,其在构造方法中必须传入类型参数,在其序列过程会使用到类信息,和默认的jdk提供的JdkSerializationRedisSerializer相比速度快,序列化后的字符串短小占用的空间少

你可能感兴趣的:(redis)