淘東電商項目(75) -秒殺系統(用戶操作頻率限制)

引言

本文代碼已提交至Github(版本號:a08c2b261d8cd31850ccebc38a4a6620090e619f),有興趣的同學可以下載來看看:https://github.com/ylw-github/taodong-shop

在上一篇博客《淘東電商項目(74) -秒殺系統(庫存超賣解決方案)主要講解了庫存超賣的解決,繼續完善上一篇博客的代碼,以下的第二個步驟:

@Transactional
public BaseResponse<JSONObject> spike(String phone, Long seckillId) {
	// 1.參數驗證
	if (StringUtils.isEmpty(phone)) {
		return setResultError("手機號碼不能爲空!");
	}
	if (seckillId == null) {
		return setResultError("商品庫存id不能爲空!");
	}
	SeckillEntity seckillEntity = seckillMapper.findBySeckillId(seckillId);
	if (seckillEntity == null) {
		return setResultError("商品信息不存在!");
	}
	// 2.用戶頻率限制 setnx 如果key存在話

	// 3.(悲觀鎖 )修改數據庫對應的庫存 1萬中只有100個搶購成功 提前生成好100個token 誰能夠搶購成功token放入到mq中實現異步修改庫存
	int inventoryDeduction = seckillMapper.pessimisticDeduction(seckillId);
	if (!toDaoResult(inventoryDeduction)) {
		log.info(">>>修改庫存失敗>>>>inventoryDeduction返回爲{} 秒殺失敗!", inventoryDeduction);
		return setResultError("親,請稍後重試!");
	}

	// 4.添加秒殺成功訂單 基於MQ實現異步形式
	OrderEntity orderEntity = new OrderEntity();
	orderEntity.setUserPhone(phone);
	orderEntity.setSeckillId(seckillId);
	int insertOrder = orderMapper.insertOrder(orderEntity);
	if (!toDaoResult(insertOrder)) {
		return setResultError("親,請稍後重試!");
	}
	log.info(">>>修改庫存成功>>>>inventoryDeduction返回爲{} 秒殺成功", inventoryDeduction);
	return setResultSuccess("恭喜您,秒殺成功!");
}

本文目錄結構:
l____引言
l____ 1.用戶操作頻率限制代碼實現
l____ 2. 測試

1.用戶操作頻率限制代碼實現

用戶的操作頻率限制很簡單,可以使用Redis的操作機制限制,Redis超時設置通用方法如下:

/**
 * description: 如果key存在的話返回fasle 不存在的話返回true
 * create by: YangLinWei
 * create time: 2020/5/25 5:45 下午
 */
public Boolean setNx(String key, String value, Long timeout) {
	Boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
	if (timeout != null) {
		stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
	}
	return setIfAbsent;
}

完善第二步驟:

@Transactional
public BaseResponse<JSONObject> spike(String phone, Long seckillId) {
	// 1.參數驗證
	if (StringUtils.isEmpty(phone)) {
		return setResultError("手機號碼不能爲空!");
	}
	if (seckillId == null) {
		return setResultError("商品庫存id不能爲空!");
	}
	SeckillEntity seckillEntity = seckillMapper.findBySeckillId(seckillId);
	if (seckillEntity == null) {
		return setResultError("商品信息不存在!");
	}
	// 2.用戶頻率限制 setnx 如果key存在話

	Boolean reusltNx = redisUtil.setNx(phone, seckillId + "", 10l);
	if (!reusltNx) {
		return setResultError("訪問次數過多,10秒後在實現重試!");
	}
	// 3.(悲觀鎖 )修改數據庫對應的庫存 1萬中只有100個搶購成功 提前生成好100個token 誰能夠搶購成功token放入到mq中實現異步修改庫存
	int inventoryDeduction = seckillMapper.pessimisticDeduction(seckillId);
	if (!toDaoResult(inventoryDeduction)) {
		log.info(">>>修改庫存失敗>>>>inventoryDeduction返回爲{} 秒殺失敗!", inventoryDeduction);
		return setResultError("親,請稍後重試!");
	}

	// 4.添加秒殺成功訂單 基於MQ實現異步形式
	OrderEntity orderEntity = new OrderEntity();
	orderEntity.setUserPhone(phone);
	orderEntity.setSeckillId(seckillId);
	int insertOrder = orderMapper.insertOrder(orderEntity);
	if (!toDaoResult(insertOrder)) {
		return setResultError("親,請稍後重試!");
	}
	log.info(">>>修改庫存成功>>>>inventoryDeduction返回爲{} 秒殺成功", inventoryDeduction);
	return setResultSuccess("恭喜您,秒殺成功!");
}

2. 測試

瀏覽器訪問:http://localhost:9800/spike?phone=13800000001&seckillId=100001

在這裏插入圖片描述

瀏覽器立刻再次訪問:
在這裏插入圖片描述

可以看到通過redis可以控制用戶訪問的頻率,本文完!

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