1
ZRS 2021-06-06 20:45:10 +08:00 1
1 、2 步是原子操作吗
|
2
jsdi OP 第一步是原子操作
第二步只有一条插入订单表的 SQL,应该也是原子性的吧? |
4
ZRS 2021-06-06 21:34:07 +08:00
@jsdi 只要保证 获取库存->判断库存->更新库存 这三步是一个原子操作即可,我没实际用过 redis,查了下可以通过 lua 脚本实现。
|
5
seakingii 2021-06-06 22:23:12 +08:00 1
感觉有问题
假设有 100 商品可下订单 第一步:并发 200 个请求,此 200 个请求读取到 REDIS 的剩余库存全是 100 第二步:因为这 200 个请求的库存都大于 0,所以你会所 200 个请求全存入消息队列... |
7
revlis7 2021-06-07 00:11:27 +08:00
|
8
jsdi OP @revlis7 目前是在消费信息时更新库存。采用的是手动签收的方式,如果更新库存+生成订单这个事务没有成功,会回滚并拒绝签收此消息,rabbitmq 会重新发送该消息,从而保证消息一定会被消费。
这么设计应该可以避免超卖以及少卖的情况吧 还有另外一种想法是设置定时任务定期把 redis 中的库存信息同步到 MySQL,因为秒杀期间读取剩余库存也是从 redis 中读取的,MySQL 的记录并不需要实时更新。不知道这种想法有没有问题 |
9
lewinlan 2021-06-07 07:01:48 +08:00 via Android
1 是单线程
1-2 之间的过程又不是 |
10
ccde8259 2021-06-07 09:14:33 +08:00 via iPhone
你把消息队列的延迟拉大一点
比如消费者在生产者投递后三秒启动 |
11
Distand 2021-06-07 19:46:22 +08:00
你这个方式队列中一定会超过 100
|
12
jsdi OP @Distand 确实超过 100 了,测试的时候消息队列有 10000 多条消息😥请问这会产生什么问题?测试的时候没发现问题阿
|
13
Distand 2021-06-08 10:20:36 +08:00
@jsdi 取库存到减库存需要是原子性的,你可以用 redis decr 去原子性减库存,减完判断>=0 再写入队列,再保证下 redis 操作和 mq 操作的事务就差不多了
|
14
jsdi OP @Distand 不好意思理解错了
队列长度为什么会超过 100 ?我使用的 redis 命令是 “decr key”,如果 reuturn >= 0,进入队列,< 0,不进入队列 。 redis 中的单条命令不是保证原子性的吗?所以队列长度只能是 100 。 经过测试确实没出现问题阿,反而是消息队列有可能丢失消息导致商品少卖了,但是没有超卖的情况 |
16
kensin 2021-07-25 16:40:57 +08:00
“消息队列可靠性怎么保证?”,可以试试事务型消息,RocketMQ 中就支持。
其实对于秒杀系统而言,本来就是万里挑一,丢失一个也无所谓。 如果是重要的消息,防止丢失可以从以下三个方面考虑: 1. 网络问题导致 MQ 根本没收到。这就需要 MQ 和生产者之间有确认机制。 2. MQ 自己把消息搞丢了(比如宕机等)。这就需要打开 MQ 上的一些持久化机制。 3. 被消费者搞丢了。比如消费者取到消息后,还没完成流程,出错了。这就需要有个确认机制,在消费者消费完此条消息后,给 MQ 发送确认,然后 MQ 再删除消息。 |