假设我使用的方式如下:
10000 名用户发送请求数据, 一律由 nginx 直接送到消息队列里去, 先进队列的前 100 个直接扔给 celery 之类处理写入数据库, 这种情况下一般怎么通知用户结果? 直接查询数据库貌似会出现秒杀成功了但还没完成写入的情况
1 neoblackcap 2019-12-09 23:09:28 +08:00 我问你一个问题,你是如何保证消息队列只放了前 100 个请求? 假如你可以保证消息队列只放前 100 个请求,后面的直接返回秒杀失败不就可以了? |
![]() | 2 opengps 2019-12-09 23:20:58 +08:00 via Android 直接在内存查询,不要走数据库 |
3 aoscici2000 OP @neoblackcap 不是只放 100 个,是把前 100 个扔给 celery,通过个 redis 计数器之类的吧?到了 100 以后的队列就不处理了。或者直接删除队列说不定是个好选择? |
4 neoblackcap 2019-12-09 23:39:33 +08:00 @aoscici2000 那你现在不就回答出来了?多问自己几个为什么就好了 |
5 billlee 2019-12-09 23:47:44 +08:00 秒杀失败也要写记录。查不到就退避后重试。 |
![]() | 6 lihongming 2019-12-10 02:02:16 +08:00 via iPhone ![]() 秒杀哪有查库的?不说性能了,就是同步问题也够你喝的了。 一个最简单的单前段架构,也得是前段先查自己内存里的计数,小于 0 直接返回失败,大于 0 再尝试往队列里插。这里会有线程安全问题,但可以先不管,性能优先。 由于队列并不管订单处理情况,所以入队成功也不意味着订单创建成功,所以入队成功的订单状态可以改为待定,然后给用户显示个等待状态,每隔几秒用 ajax 查询一下,这时压力就不大了,可以直接查库。 至于入队失败的,直接返回失败即可。 另外你需要一个前端服务与实时库存同步的机制,比如每 5 秒同步一次,这样后端有了失败的订单以后,前端也可以接受新订单了。 |
![]() | 7 jss 2019-12-10 08:57:57 +08:00 via iPhone 我的实现很简单,消息列队都没用。锁+并发=秒杀 |
8 securityCoding 2019-12-10 09:39:32 +08:00 库存用 redis 或者直接写在内存里面 , 这一步拦住基本问题不大,查询详情页什么直接内存过期缓存就行 |
9 qinfensky 2019-12-10 13:03:18 +08:00 via iPhone 用个单例在内存中统计好不好? |