Giter Club home page Giter Club logo

jseckill's Issues

rabbitmq的生产和消费是只用了一个队列吗?

不是很懂rabbitmq,所以希望有大佬能解释一下,因为看那个流程图上画的是,在redis进行秒杀的时候就是发送到名字为seckill的队列中,在支付的时候发送到另外一个队列中去。所以就有疑问,秒杀的时候是放到一个队列中去吗?

demo

1.大佬问一下支付功能怎么体现,我在输入手机号后秒杀成功,然后也没有支付界面,mysql中库存也没变。。。
2.大佬,Jemeter怎么传不同的手机号啊。。。

RabbitMQ问题

  1. 是否没有配置消息队列最大长度限制以及溢出行为,队列满了之后默认会丢弃队头的元素,先进入队列的反而被丢弃了?
  2. 入队前redis判断库存并没有减库存,则可能导致远超库存限制的SeckillMsgBody进入队列,同个id的请求也可能重复进入队列,这样增加了MQ和consumer的压力,需要处理很多无效的请求?是否可以添加一个 set 记录历史入队的id,入队前判断已入队数量和是否重复入队再考虑是否需要入队?

客户端轮询秒杀是否成功,换成websocket是否更好

一些 web 应用不采用 webocket有一个原因是多页面重开。你想想,同时打开几个秒杀页面就是几个 websocket 连接,这个比较难处理。不像客户端,登录一个可以踢掉另一个,在 web 上这种情况很普遍,轮询处理简单很多。
而且一旦查询到秒杀成功或者失败,就马上停止轮询,不会太消耗服务器的带宽.

关于mysql读写分离

大佬你好,想问一下你文档中说的MySQL读写分离这里你是在哪里配置的呢,谢谢

请删除无效字符

/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;

秒杀输入手机号问题

大佬你好,我在github上看到了你的秒杀项目,想问一下:
1.第一次启动项目时可以输入手机号,后来启动就再也没有输入手机号这个功能了是什么原因?
2.这个项目可以用测试工具测试吗?

如果希望采用多个服务器进行消息的消费,是不是在操作redis减库存的时候加分布式锁呢?

` @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,或者是在消费者调用这个方法的时候就使用分布式锁,我感觉后面这个比较好一些呢

是否存在情况当未在指定时间段内收到ACK返回,但Redis却被处理的情况(handleInRedis方法正常执行),导致redis库存数-1的情况

是否存在情况当未在指定时间段内收到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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.