bootsrc / jseckill Goto Github PK
View Code? Open in Web Editor NEWJava秒杀 抢购 (Seckill based on Spring Boot)
Home Page: http://jseckill.appjishu.com
License: Apache License 2.0
Java秒杀 抢购 (Seckill based on Spring Boot)
Home Page: http://jseckill.appjishu.com
License: Apache License 2.0
请问你项目中什么时候会修改mysql?感觉流程截止在了redis中inventory减一
!!! 别打开
/jseckill-backend/src/main/java/com/liushaoming/jseckill/backend/boot/InitTask.java:24
需要删除无效字符。
@Component
public class InitTask implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(InitTask.class);
å
@Resource(name = "initJedisPool")
private JedisPool jedisPool;
大佬你好,想问一下你文档中说的MySQL读写分离这里你是在哪里配置的呢,谢谢
大佬你好,我在github上看到了你的秒杀项目,想问一下:
1.第一次启动项目时可以输入手机号,后来启动就再也没有输入手机号这个功能了是什么原因?
2.这个项目可以用测试工具测试吗?
还有就是如果半小时不付款,后续代码是监听redis的key实现,还是用zookeeper
不是很懂rabbitmq,所以希望有大佬能解释一下,因为看那个流程图上画的是,在redis进行秒杀的时候就是发送到名字为seckill
的队列中,在支付的时候发送到另外一个队列中去。所以就有疑问,秒杀的时候是放到一个队列中去吗?
` @OverRide
public void handleInRedis(long seckillId, long userPhone) throws SeckillException {
Jedis jedis = jedisPool.getResource();
//获取前缀,+商品的秒杀id=当前秒杀商品的key
String inventoryKey = RedisKeyPrefix.SECKILL_INVENTORY + seckillId;
//key前缀+商品的秒杀id
String boughtKey = RedisKeyPrefix.BOUGHT_USERS + seckillId;
//获取商品库存
String inventoryStr = jedis.get(inventoryKey);
//转换成int
int inventory = Integer.valueOf(inventoryStr);
if (inventory <= 0) {
logger.info("handleInRedis SECKILLSOLD_OUT. seckillId={},userPhone={}", seckillId, userPhone);
throw new SeckillException(SeckillStateEnum.SOLD_OUT);
}
//这里使用了redis的set集合,使用秒杀商品的id作为key,value是一个set集合,
//这里是先判断当前秒杀商品的秒杀集合中是否存在了用户的电话,如果存在,说明该用户已经秒杀过一次了,抛出重复秒杀异常
if (jedis.sismember(boughtKey, String.valueOf(userPhone))) {
logger.info("handleInRedis SECKILL_REPEATED. seckillId={},userPhone={}", seckillId, userPhone);
throw new SeckillException(SeckillStateEnum.REPEAT_KILL);
}
//商品redis中库存-1
jedis.decr(inventoryKey);
//往商品的set集合中添加手机号,作为成员,代表该手机号用户已经秒杀了该商品
jedis.sadd(boughtKey, String.valueOf(userPhone));
logger.info("handleInRedis_done");
}`
我给您的这个方法添加了一些注释,是不是需要在 jedis.decr(inventoryKey);这里使用分布式锁,防止多余的减库存请求进入redis,或者是在消费者调用这个方法的时候就使用分布式锁,我感觉后面这个比较好一些呢
一些 web 应用不采用 webocket有一个原因是多页面重开。你想想,同时打开几个秒杀页面就是几个 websocket 连接,这个比较难处理。不像客户端,登录一个可以踢掉另一个,在 web 上这种情况很普遍,轮询处理简单很多。
而且一旦查询到秒杀成功或者失败,就马上停止轮询,不会太消耗服务器的带宽.
1.大佬问一下支付功能怎么体现,我在输入手机号后秒杀成功,然后也没有支付界面,mysql中库存也没变。。。
2.大佬,Jemeter怎么传不同的手机号啊。。。
是否存在情况当未在指定时间段内收到ACK返回,
boolean sendAcked = false;
try {
sendAcked = channel.waitForConfirms(100); 100ms时间内
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
但Redis却被处理的情况(handleInRedis方法正常执行),
@Override
public void handleInRedis(long seckillId, long userPhone) throws SeckillException {
Jedis jedis = jedisPool.getResource();
String inventoryKey = RedisKeyPrefix.SECKILL_INVENTORY + seckillId;
String boughtKey = RedisKeyPrefix.BOUGHT_USERS + seckillId;
String inventoryStr = jedis.get(inventoryKey);
int inventory = Integer.valueOf(inventoryStr);
if (inventory <= 0) {
logger.info("handleInRedis SECKILLSOLD_OUT. seckillId={},userPhone={}", seckillId, userPhone);
throw new SeckillException(SeckillStateEnum.SOLD_OUT);
}
if (jedis.sismember(boughtKey, String.valueOf(userPhone))) {
logger.info("handleInRedis SECKILL_REPEATED. seckillId={},userPhone={}", seckillId, userPhone);
throw new SeckillException(SeckillStateEnum.REPEAT_KILL);
}
jedis.decr(inventoryKey);
jedis.sadd(boughtKey, String.valueOf(userPhone));
logger.info("handleInRedis_done");
}
导致redis库存数-1,且用户无法继续购买的问题
12/17-17:18:54 [http-nio-27000-exec-2] INFO com.liushaoming.jseckill.backend.mq.MQProducer- [mqSend] '{"seckillId":1000,"userPhone":18668042850}'
12/17-17:18:54 [pool-3-thread-6] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- ---receive_threadId_1=42
12/17-17:18:54 [pool-3-thread-6] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- [mqReceive] '{"seckillId":1000,"userPhone":18668042850}'
12/17-17:18:54 [pool-3-thread-6] INFO com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl- handleInRedis_done
12/17-17:18:54 [pool-3-thread-6] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- ------processIt----
12/17-17:18:54 [pool-3-thread-6] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- ---->ACK
java.util.concurrent.TimeoutException
at com.rabbitmq.client.impl.ChannelN.waitForConfirms(ChannelN.java:229)
at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.waitForConfirms(AutorecoveringChannel.java:697)
at com.liushaoming.jseckill.backend.mq.MQProducer.send(MQProducer.java:53)
at com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl.handleSeckillAsync(SeckillServiceImpl.java:172)
at com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl.executeSeckill(SeckillServiceImpl.java:124)
at com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl$$FastClassBySpringCGLIB$$85f44643.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
at com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl$$EnhancerBySpringCGLIB$$4cd4b877.executeSeckill(<generated>)
at com.liushaoming.jseckill.backend.controller.SeckillController.execute(SeckillController.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
12/17-17:18:54 [http-nio-27000-exec-2] INFO com.liushaoming.jseckill.backend.mq.MQProducer- sendAcked=false
12/17-17:18:54 [http-nio-27000-exec-2] INFO com.liushaoming.jseckill.backend.mq.MQProducer- !!!mqSend_NACKED,NOW_RETRY>>>
12/17-17:18:54 [http-nio-27000-exec-2] INFO com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl- ENQUEUE_PRE_SECKILL>>>seckillId=1000,userPhone=18668042850
12/17-17:18:54 [pool-3-thread-3] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- ---receive_threadId_1=38
12/17-17:18:54 [pool-3-thread-3] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- [mqReceive] '{"seckillId":1000,"userPhone":18668042850}'
12/17-17:18:54 [pool-3-thread-3] INFO com.liushaoming.jseckill.backend.service.impl.SeckillServiceImpl- handleInRedis SECKILL_REPEATED. seckillId=1000,userPhone=18668042850
12/17-17:18:54 [pool-3-thread-3] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- ------processIt----
12/17-17:18:54 [pool-3-thread-3] INFO com.liushaoming.jseckill.backend.mq.MQConsumer- --LET_MQ_ACK REASON:SeckillStateEnum.SOLD_OUT,SeckillStateEnum.REPEAT_KILL
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.