请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

会出现多抢库存为-1的情况

KillTask的代码

    int num = Integer.parseInt(jedis.get("kill_num"));
    if (num > 0) {
        jedis.watch("kill_num", "kill_user");
        Transaction transaction = jedis.multi();
        transaction.decr("kill_num");
        transaction.rpush("kill_user", "9527");
        transaction.exec();
    } else {
        Application.pool.shutdown();
    }

在库存为1的时候。如果两个线程同时去取jedis.get(“kill_num”),都拿到num=1.然后,都进入了redis事务的代码。最后就会出现库存为-1或-2的现象。我本地的测试也出现了这种情况。请老师提供解决方案。
jedis.watch之前取num的代码,老师没有做到事务的一致性。

正在回答 回答被采纳积分+3

3回答

FrankLi_ 2019-12-22 22:39:01

改成先watch再get做判断就不会了。现在的代码的确可能会超卖,发生在线程1get之后判断了还没有watch,其他线程扣减完成了的情况。我建议用lua脚本,性能会更高。

0 回复 有任何疑惑可以回复我~
大喵爱学习 2019-11-16 16:12:11

哈哈,同学,太感谢你啦!找到问题啦

0 回复 有任何疑惑可以回复我~
神思者 2019-07-16 23:44:33

我在Linux上运行redis的结果是正常的,你是在Linux上运行的redis吗?

0 回复 有任何疑惑可以回复我~
  • 提问者 Peter陳 #1
    我的redis是在centos7上建的docker容器。你的代码判断库存数量,是在redis的watch操作之前。如果两个线程同时进入了(库存>0),那是没法避免-1的情况。这个你可以分析一下。
    你的正常,跟你的服务器性能等因素有关。这个肯定不是一个100%复现的bug
    回复 有任何疑惑可以回复我~ 2019-07-17 00:39:42
  • 神思者 回复 提问者 Peter陳 #2
    嗯,watch语句应该放在条件判断之前,你观察的真仔细,找到这个bug,我一会儿更新一下。如果有什么技术问题,欢迎继续提问,祝你学习愉快。
    回复 有任何疑惑可以回复我~ 2019-07-17 08:34:59
  • 老师,上面同学提的问题不太理解,一号和二号线程同时获得num=1,可是一号线程被执行之后版本号改变了,二号线程的版本号与后来的版本号不是冲突了吗
    回复 有任何疑惑可以回复我~ 2019-08-01 14:06:47
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信