当前位置:网站首页>Redis seckill demo
Redis seckill demo
2022-07-01 15:35:00 【y_ w_ x_ k】
Scheme 1 : Method plus synchronized that will do , Thread safety scheme , But the efficiency of execution is low , Not suitable for large concurrent occasions
Option two : Use optimistic lock
controller:
@RestController
public class SecondKill {
@Autowired
SecondKillSev secondKillSev;
@RequestMapping(value = "/buy",method = RequestMethod.POST)
public Mes buy(@RequestParam("proid") String proid){
String usedId=new Random().nextInt(1000)+"";
Mes mes = secondKillSev.doSecondKill(usedId, proid);
return mes;
}
}
service:
@Service
public class SecondKillSev {
Mes message;
public SecondKillSev(){
}
@Autowired
StringRedisTemplate stringRedisTemplate;
/**
* Execute seckill
* Scheme 1 :synchronized, Thread safety , But the efficiency of execution is low , Not suitable for large concurrent occasions
* Option two : Monitor transactions with optimistic locks
*/
public Mes doSecondKill(String uid, String proid){
//1. Judge uid and proid Non empty
if(uid==null || proid==null){
return Mes.getMes("400","uid and proid Can't be empty ");
}
//2. Connect redis
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
//3. Splicing key, stock key, Successful user key
String kcKey="kcKey:"+proid;
String userKey="userKey:"+proid;
// Optimistic lock solves oversold problem
//stringRedisTemplate The default is not to open things
stringRedisTemplate.setEnableTransactionSupport(true);
List<Object> txResults = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
// Monitor inventory
operations.watch(kcKey);
//4. Get inventory , If the inventory is null, The second kill has not yet started
String kc=ops.get(kcKey);
if(kc==null){
message= Mes.getMes("400"," The stock is null, The second kill hasn't started yet ");
return null;
}
//5. Judge whether the user repeats the second kill
if(operations.opsForSet().isMember(userKey, uid)){
message=Mes.getMes("400"," You can't repeat the second kill ");
return null;
}
//6. Judge the quantity of goods , If the quantity is less than 1, Then the second kill is over
if(Integer.parseInt(kc)<=0){
message=Mes.getMes("400"," The second kill is over ");
return null;
}
//7. Second kill process , stock -1, Successful user added to manifest
// With a transaction
operations.multi();
operations.opsForValue().decrement(kcKey);
operations.opsForSet().add(userKey,uid);
List exec = operations.exec();
if(exec==null || exec.size()==0){
message=Mes.getMes("400"," Seckill failure ");
return null;
}else{
return exec;
}
}
});
if(txResults==null ||txResults.size()==0){
return message;
}
return Mes.getMes("200"," Seckill success ");
}
}
But this scheme also has a disadvantage , That is, if the quantity of goods is 500, But the number of threads is 1000, That is, when the number of visits is not very large , There will be the problem that the inventory is not sold out , That is, inventory leftover problems , So it can be used lua Script to solve ;
Option three :lua Script
local userid=KEYS[1];
local prodid=KEYS[2];
local qtkey="sk:"..prodid..":qt";
local userskey="sk:"..prodid..":user";
local userExists=redis.call("sismember",userskey,userid);
if tonumber(userExists)==1 then
return 2;
end
local num=redis.call("get",qtkey);
if tonumber(num)<=0 then
return 0;
else
redis.call("decr",qtkey);
redis.call("sadd",userskey,userid);
end
return 1
Code implementation :
@Service
public class SeckillByScript {
static String secKillScript1 = "local userid=KEYS[1];\n" +
"local prodid=KEYS[2];\n" +
"local qtkey=\"sk:\"..prodid..\":qt\";\n" +
"local userskey=\"sk:\"..prodid..\":user\";\n" +
"local userExists=redis.call(\"sismember\",userskey,userid);" +
"if tonumber(userExists)==1 then\n" +
" return 2;\n" +
"end\n" +
"local num=redis.call(\"get\",qtkey);\n" +
"if tonumber(num)<=0 then\n" +
" return 0;\n" +
"else\n" +
" redis.call(\"decr\",qtkey);\n" +
" redis.call(\"sadd\",userskey,userid);\n" +
" end\n" +
" return 1";
public boolean doSecKill(String userid, String prodid) {
JedisPool jedisPool = JedisPoolUtil.getJedisPool();
Jedis jedis = jedisPool.getResource();
String sha1 = jedis.scriptLoad(secKillScript1);
Object result = jedis.evalsha(sha1, 2, userid, prodid);
String reString = String.valueOf(result);
if ("0".equals(reString)) {
System.out.println(" Empty !");
return false;
} else if ("1".equals(reString)) {
System.out.println(" Panic buying ");
return true;
} else if ("2".equals(reString)) {
System.out.println(" The user has robbed !");
return false;
} else {
System.out.println(" Panic buying exception ");
return false;
}
}
}
边栏推荐
- JS中箭头函数和普通函数的区别
- 【STM32学习】 基于STM32 USB存储设备的w25qxx自动判断容量检测
- Fix the failure of idea global search shortcut (ctrl+shift+f)
- Stm32f4-tft-spi timing logic analyzer commissioning record
- Day 3 of rhcsa study
- 【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(三)
- Raytheon technology rushes to the Beijing stock exchange and plans to raise 540million yuan
- Connect the ABAP on premises system to the central inspection system for custom code migration
- 微信小程序03-文字一左一右显示,行内块元素居中
- vim 从嫌弃到依赖(22)——自动补全
猜你喜欢
Opencv learning note 4 -- bank card number recognition
OpenSSL client programming: SSL session failure caused by an insignificant function
How to realize clock signal frequency division?
Raytheon technology rushes to the Beijing stock exchange and plans to raise 540million yuan
她就是那个「别人家的HR」|ONES 人物
【目标跟踪】|STARK
Microservice tracking SQL (support Gorm query tracking under isto control)
"Qt+pcl Chapter 6" point cloud registration ICP Series 6
《QT+PCL第六章》点云配准icp系列6
微信小程序01-底部导航栏设置
随机推荐
The solution to turn the newly created XML file into a common file in idea
采集数据工具推荐,以及采集数据列表详细图解流程
C#/VB.NET 合并PDF文档
Summary of empty string judgment in the project
微信网页订阅消息实现
swiper 轮播图,最后一张图与第一张图无缝衔接
[300 + selected interview questions from big companies continued to share] big data operation and maintenance sharp knife interview question column (III)
Go zero actual combat demo (I)
Raytheon technology rushes to the Beijing stock exchange and plans to raise 540million yuan
MySQL service is starting. MySQL service cannot be started. Solution
【一天学awk】条件与循环
Skywalking 6.4 distributed link tracking usage notes
STM32F4-TFT-SPI时序逻辑分析仪调试记录
[antenna] [3] some shortcut keys of CST
微服务追踪SQL(支持Isto管控下的gorm查询追踪)
[stm32-usb-msc problem help] stm32f411ceu6 (Weact) +w25q64+usb-msc flash uses SPI2 to read out only 520kb
【云动向】6月上云新风向!云商店热榜揭晓
Task.Run(), Task.Factory.StartNew() 和 New Task() 的行为不一致分析
Hardware design guide for s32k1xx microcontroller
Qt+pcl Chapter 6 point cloud registration ICP series 3