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)的多條命令會按照先后順序被放進(jìn)一個隊列當(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í)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot+Redis隊列實現(xiàn)Java版秒殺的示例代碼
- Springboot+redis+Vue實現(xiàn)秒殺的項目實踐
- springboot?+rabbitmq+redis實現(xiàn)秒殺示例
- SpringBoot+RabbitMQ+Redis實現(xiàn)商品秒殺的示例代碼
- 基于Redis結(jié)合SpringBoot的秒殺案例詳解
- SpringBoot之使用Redis實現(xiàn)分布式鎖(秒殺系統(tǒng))
- SpringBoot使用Redisson實現(xiàn)分布式鎖(秒殺系統(tǒng))
- 基于SpringBoot+Redis+Lua 實現(xiàn)高并發(fā)秒殺系統(tǒng)
相關(guān)文章
idea一招搞定同步所有配置(導(dǎo)入或?qū)С鏊信渲?
使用intellij idea很長一段時間,軟件相關(guān)的配置也都按照自己習(xí)慣的設(shè)置好,如果需要重裝軟件,還得需要重新設(shè)置,本文就詳細(xì)的介紹了idea 同步所有配置,感興趣的可以了解一下2021-07-07
通過springboot+mybatis+druid配置動態(tài)數(shù)據(jù)源
這篇文章主要介紹了通過springboot+mybatis+druid配置動態(tài)數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下2019-06-06
如何使用MybatisPlus的SQL注入器提升批量插入性能
本文給大家介紹如何使用MybatisPlus的SQL注入器提升批量插入性能,以實戰(zhàn)視角講述如何利用該特性提升MybatisPlus?的批量插入性能,感興趣的朋友跟隨小編一起看看吧2024-05-05
Spring 事務(wù)事件監(jiān)控及實現(xiàn)原理解析
本文首先會使用實例進(jìn)行講解Spring事務(wù)事件是如何使用的,然后會講解這種使用方式的實現(xiàn)原理。感興趣的朋友跟隨小編一起看看吧2018-09-09
解讀nextLine().split(“[\\s]“)的意思
這篇文章主要介紹了解讀nextLine().split(“[\\s]“)的意思,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04

