引言
本文代碼已提交至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可以控制用戶訪問的頻率,本文完!