- 🌱 Only those who capture the moment are real
- 🏆 Goals: Contribute more to Open Source projects
- ⚡ Fun fact: I like swimming and running
🌎 Let's code the world
:racehorse:基于SpringBoot + MySQL + Redis + RabbitMQ + Guava开发的高并发商品限时秒杀系统
方便详细写下启动步骤吗,我这种小白来学习的话就是一路坑。
有没有数据库
运行报错:
Description: Field userMapper in com.jesper.seckill.service.UserService required a bean of type 'com.jesper.seckill.mapper.UserMapper' that could not be found.
Action: Consider defining a bean of type 'com.jesper.seckill.mapper.UserMapper' in your configuration.
明明这个用户的信息已经在数据库里面了啊。。。。。。。
long stock = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);//10
if (stock < 0) {
afterPropertiesSet();
long stock2 = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);//10
if(stock2 < 0){
localOverMap.put(goodsId, true);
return Result.error(CodeMsg.SECKILL_OVER);
}
}
//判断重复秒杀
//如果重复秒杀,是否多次减库存?
SeckillOrder order = orderService.getOrderByUserIdGoodsId(user.getId(), goodsId);
if (order != null) {
return Result.error(CodeMsg.REPEATE_SECKILL);
}
预减库存后,如果是重复秒杀,redis中的库存量还是会减少,导致其他用户不能下单
在service包里的reduceStock方法有使用GoodsVo 类的getId()方法
同一个商品减库存key为SeckillKey:go1,失败一次,则后续所有该商品的所有减库存操作在redis中设为失败,一旦getSeckillResult查询时,mq暂时没执行则会通知秒杀失败。"对不起,秒杀失败" ,即一直失败
建议rediskey添加用户id,并给这个key设置过期时间,即超过最大mq延迟执行时间
do {
numAttempts++;
try {
ret = goodsMapper.reduceStockByVersion(sg);
} catch (Exception e) {
e.printStackTrace();
}
if (ret != 0)
break;
} while (numAttempts < DEFAULT_MAX_RETRIES);
你好,我想运行这个项目,密码可以说下吗
GoodsService.reduceStock()方法中,初始化SeckillGoods时,字段version始终为0问题
检验库存>0是不是就够了
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@117159c0: startup date [Wed Mar 23 20:50:25 CST 2022]; root of context hierarchy
秒杀下单时的一段代码:
//预减库存 long stock = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);//10 if (stock < 0) { afterPropertiesSet(); long stock2 = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);//10 if(stock2 < 0){ localOverMap.put(goodsId, true); return Result.error(CodeMsg.SECKILL_OVER); } }
下面这个是afterPropertiesSet方法定义,每次调用都要获取所有商品并且遍历商品,这样会消耗性能吧,而且,我只是下单某一件商品,为什么在遍历中将每件商品标记为false?原本某些标记为true的商品变为false了
public void afterPropertiesSet() { List<GoodsVo> goodsVoList = goodsService.listGoodsVo(); if (goodsVoList == null) { return; } for (GoodsVo goods : goodsVoList) { redisService.set(GoodsKey.getGoodsStock, "" + goods.getId(), goods.getStockCount()); //初始化商品都是没有处理过的 localOverMap.put(goods.getId(), false); } }
/**
* 减少库存,每次减一
*
* @return
*/
public boolean reduceStock(GoodsVo goods) {
int numAttempts = 0;
int ret = 0;
SeckillGoods sg = new SeckillGoods();
sg.setGoodsId(goods.getId());
sg.setVersion(goods.getVersion());
do {
numAttempts++;
try {
//TODO 如果version失效了,更新失败 再次执行时没有取出表中最新的version,所以不管循环几次,更新也是失败的????
ret = goodsMapper.reduceStockByVersion(sg);
} catch (Exception e) {
e.printStackTrace();
}
if (ret != 0)
break;
} while (numAttempts < DEFAULT_MAX_RETRIES);
return ret > 0;
}
怎么运行
SeckillController.list 方法中,先预减库存,然后判断是否重复秒杀。如果重复秒杀或者下订单异常,应该会出现有库存,但是返回秒杀完毕情况
我把这个项目搭在腾讯云上,带宽1Mps,内存2G,一核的,跑起来qps随着最大线程数增大变小,1000线程一起跑,14qps;200线程一起跑50qps;这个数据是正常数据吗?
我看代码里面的controller
层的SeckillController#list()
方法,即执行秒杀的方法,redis的操作完成之后,只是把消息发送到rabbitmq中,然后rabbitmq监听取出消息,就直接和数据库交互了,所以我想问一下这个异步是体现在哪个地方呀?
数据库里存的应该是随机生成的salt吧,存写死的salt,自己也没办法比较用户输入的密码是否正确了啊
redis pass 没有通过配置读取到实例化中,导致redis 设置了pass就会报错。
JedisPool jp = new JedisPool(config, redisConfig.getHost(), redisConfig.getPort(),
redisConfig.getTimeout()*1000, redisConfig.getPassword(), 0);
git中没有加redisConifg.getPassword()
在RedisPoolFactory.java中
用idea试了好几次都失败了,有没有运行成功的大佬教一下怎么运行,谢谢了
想咨询一些问题。
秒杀已经ok,谢谢楼主
点击立即秒杀 后台/do_seckill 方法中 user对象内的属性值都为null,当执行到//判断重复秒杀
SeckillOrder order = orderService.getOrderByUserIdGoodsId(user.getId(), goodsId);报空指针异常,请问为什么呢?
两个问题
1、更新库存时没有送version number,所以更新库存失败
2、秒杀成功以后,返回的int 永远是1,作为订单号返回,是查不到订单的
GoodsVo
增加
int version 和getter setter
GoodsMapper
getGoodsVoByGoodsId 增加返回 sg.version
GoodsService
reduceStock()方法增加
sg.setVersion(goods.getVersion());
OrderService
createOrder()方法
订单号要从实体类中取,否则update返回的永远是1
long orderId = orderInfo.getId();
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
本人小白,mysql的update本身具有排他锁,@update("update sk_goods_seckill set stock_count = stock_count - 1, version= version + 1 where goods_id = #{goodsId} and stock_count > 0 and version = #{version}"),更新库存应该不存在安全问题,为什么还需要根据版本来实现乐观锁,希望释疑。
哥们 一个bug 加载的时候要把订单信息加载上去
不然服务器宕机了已下单用户再次请求的话插入数据库会出错
mq的消息会一直轮询
项目当前是单服务,我想了解下有没有多服务的解决方案,比如1000个秒杀商品,拆分5个服务,每个服务分配200个商品供秒杀。这个解决方案需要解决的点在于请求路由。
- 两次MD5加密
将用户输入的密码和固定Salt通过MD5加密生成第一次加密后的密码,再讲该密码和随机生成的Salt通过MD5进行第二次加密,最后将第二次加密后的密码和第一次的固定Salt存数据库
这里存到 db 的 salt 应该是第二次加密时随机生成的 salt 吧
数据什么的都导入了。该安装的也安装了。启动后也没报错。
但是访问localhost:8080一直都404加上/login啥的也是404.想问下大佬是怎么回事
大佬,想问你一个问题,你这里为什么没有去实现隐藏秒杀地址的功能,你觉得这个没必要吗,希望你能解答一下
查看了代码,不知道是否只更新到了支付后的代码,并无找到点击支付按钮后的处理代码
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.