springboot集成redis實現(xiàn)簡單秒殺系統(tǒng)
本文實例為大家分享了springboot集成redis實現(xiàn)簡單秒殺系統(tǒng)的具體代碼,供大家參考,具體內(nèi)容如下
1. 直接service,我們會介紹兩種秒殺模式
public interface GoodsService {
/**
* 通過lua腳本實現(xiàn)的秒殺
* @param skuCode 商品編碼
* @param buyNum 購買數(shù)量
* @return 購買數(shù)量
*/
Long flashSellByLuaScript(String skuCode,int buyNum);
/**
* 通過redis 事務(wù) 實現(xiàn)的秒殺
* @param skuCode 商品編碼
* @param buyNum 購買數(shù)量
* @return 購買數(shù)量
*/
Long flashSellByRedisWatch(String skuCode,int buyNum);
}
2. service實現(xiàn)類
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
@Service
public class GoodsServiceImpl implements GoodsService {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public Long flashSellByLuaScript(String skuCode,int num) {
//下面是lua腳本
String luaScript ="local buyNum = ARGV[1]\n" +
"local goodsKey = KEYS[1] \n" +
"local goodsNum = redis.call('get',goodsKey) \n" +
"if goodsNum >= buyNum \n" +
"then redis.call('decrby',goodsKey,buyNum) \n" +
"return buyNum \n" +
"else \n" +
"return '0'\n" +
"end\n" +
"\n" ;
DefaultRedisScript<String> re = new DefaultRedisScript<String>();
//設(shè)置腳本
re.setScriptText(luaScript);
//定義返回值類型,注意,如果沒有這個定義,Spring不會返回結(jié)果
re.setResultType(String.class);
RedisSerializer<String> stringRedisSerializer = stringRedisTemplate.getStringSerializer();
//執(zhí)行LUA腳本
String result = (String) stringRedisTemplate.execute(re, stringRedisSerializer, stringRedisSerializer, null);
return Long.valueOf(result);
}
@Override
public Long flashSellByRedisWatch(String skuCode,int num){
SessionCallback<Long> sessionCallback = new SessionCallback<Long>() {
@Override
public Long execute(RedisOperations operations) throws DataAccessException {
int result = num;
//redis 樂觀鎖
//我們觀察商品編碼是否發(fā)生改變
operations.watch(skuCode);
ValueOperations<String, String> valueOperations = operations.opsForValue();
String goodsNumStr = valueOperations.get(skuCode);
Integer goodsNum = Integer.valueOf(goodsNumStr);
//標(biāo)記一個事務(wù)塊的開始。
//事務(wù)塊內(nèi)的多條命令會按照先后順序被放進一個隊列當(dāng)中,
//最后由 EXEC 命令原子性(atomic)地執(zhí)行。
operations.multi();
if (goodsNum >= num) {
valueOperations.increment(skuCode, 0 - num);
} else {
result = 0;
}
//多條命令執(zhí)行的結(jié)果集合
List exec = operations.exec();
if(exec.size()>0){
System.out.println(exec);
}
return (long) result;
}
};
return stringRedisTemplate.execute(sessionCallback);
}
//省略 其他的方法
}
3. controller
但是首先要向你的redis里面仍一個數(shù)據(jù),key='xiaomi',value='100'
@ApiOperation(value = "用事務(wù)秒殺測試接口", notes = "用事務(wù)秒殺測試接口")
@RequestMapping(value = "/miaoTransaction", method = RequestMethod.GET)
@ResponseBody
public Long miaoTransaction() {
Long res = goodsService.flashSellByRedisWatch("xiaomi", 1);
return res;
}
@ApiOperation(value = " 秒殺Lua測試接口", notes = "秒殺Lua測試接口")
@RequestMapping(value = "/miaoLua", method = RequestMethod.GET)
@ResponseBody
public Long miaoLua() {
Long res = goodsService.flashSellByRedisWatch("xiaomi", 1);
System.out.println(res.toString());
return res;
}
然后就可以用jemeter并發(fā)訪問了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于 SASL/SCRAM 讓 Kafka 實現(xiàn)動態(tài)授權(quán)認證的方法
在大數(shù)據(jù)處理和分析中?Apache Kafka?已經(jīng)成為了一個核心組件,本文將從零開始部署?ZooKeeper?和?Kafka?并通過配置?SASL/SCRAM?和?ACL(訪問控制列表)來增強?Kafka?的安全性,需要的朋友可以參考下2024-07-07
Java中HashMap與String字符串互轉(zhuǎn)的問題解決
本文介紹了Java中HashMap與String字符串互轉(zhuǎn)的問題解決,當(dāng)我們有需求將HashMap轉(zhuǎn)為Json格式的String時,需要使用FastJson/Gson將HashMap轉(zhuǎn)為String,感興趣的可以了解一下2022-03-03
Spring Boot 捕捉全局異常 統(tǒng)一返回值的問題
這篇文章主要介紹了Spring Boot 捕捉全局異常 統(tǒng)一返回值,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Java中l(wèi)ength,length(),size()詳解及區(qū)別
這篇文章主要介紹了Java中l(wèi)ength,length(),size()詳解及區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-11-11
springcloud 熔斷監(jiān)控Hystrix Dashboard和Turbine
這篇文章主要介紹了springcloud 熔斷監(jiān)控Hystrix Dashboard和Turbine,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Spring Boot實戰(zhàn)之靜態(tài)資源處理
這篇文章主要介紹了Spring Boot實戰(zhàn)之靜態(tài)資源處理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01

