调整数据库中的临时记录以统计总数以停止超额订阅

2024-06-25 23:20:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我在看一个系统,在这个系统中,人们可以回复到一个免费的网络会议,这些网络会议可以变得非常繁忙,有很多有趣的地方,所以必须有一些方法来确保它不会被过度订阅。。。所以,我们需要倒计时,从他们预订座位到他们的订单完成并确认。这样一来,第一批点击“参加”就能获得会议席位的人数。如果用户没有完成他们的预订,他们分配的座位会被放回游泳池让其他人去抢。。。在

概述所发生的事情(我如何看待这一点)

1)用户在事件上单击“RSVP”,这将向/RSVP/{event_id}/

这将存储一个惟一的id(在这个问题的其余部分中称为token)和一个时间戳。它也在会话中存储该令牌。在

然后通知用户他们有X时间(比如5分钟)来完成其余的详细信息(name/email/d.o.b等)

但是:在将任何内容放入数据库之前,它会检查待处理订单的数量是否少于可用的总座位数,如果没有(会议没有剩余的座位),则返回“对不起,没有座位了,请继续检查,因为预订还没有完成,还有更多的座位可用”

2)如果用户及时填写,它会将他们的详细信息存储在数据库中作为“参加”。。。。在

但是,如果他们没有及时填写表格,每秒钟都有一个cron作业在运行,并且检查并删除任何时间戳超过5分钟的令牌,这样他们就失去了参加会议的机会,会议上的这个“席位”就会被放回池中。(他们将收到通知,他们没有成功,并返回到第一步)

所有这些都很容易编写,只需将记录放入数据库,做一个COUNT(*) FROM pending_bookings WHERE conference_id = {x}并计算出有多少座位已确认或订单待定,然后从可供会议使用的总座位中减去。在

但我不认为使用MySQL在这方面会有很大的扩展性——这些人(我肯定还会有)超过20万人试图抢占大约200个座位,对其中每一个人做一个计数(*)将会非常昂贵,我们不能做任何像样的缓存,因为它需要实时检查进程中有多少人。在

我曾经研究过使用Amazon SimpleDB来实现这一点,仅仅是为了它的部署和部署的可伸缩性,但是我以前使用过它,并且发现COUNT()不一定是准确的(我猜它的可伸缩性的本质),因为很明显,COUNT需要100%准确,我需要能够添加记录以及时间戳,并能够从中删除超过5分钟的记录。在


Tags: 用户订单网络id数据库系统部署count
3条回答

doing a COUNT(*) for each one of those people will get pretty expensive

你发现了吗,还是直觉?我宁愿对其进行基准测试(以及您的web服务器是否能够承载这些负载),而不是预先假设。索引(并正确选择存储引擎)在这方面可能会有很大帮助。在

此外,让人们在注册一个活动之前注册并输入他们的帐户数据,这不是更方便用户吗?因为现在你似乎更喜欢那些打字速度很快的人,或者使用一个像样的浏览器的人。在

您可以缓存数据库中的可用计数,并在发出(注册开始)、确认(注册完成)或吊销(超过5分钟)令牌时更新该计数。但是,如果您需要这种性能,那么SQL数据库并不是这样的。在

您可以使用heap(基于最快到期)实现一个相当简单的令牌代理。每次请求令牌时,它都会检查最快到期的令牌并查看它是否已过期。若是这样,就要从所分派的人那里收回,交给新人。如果没有,告诉他们稍后再试。在

当注册完成后,您必须从堆中移除该令牌(这是一个相对昂贵的操作,但您只执行了200次)。因此,堆中的标记始终等于空闲+挂起插槽的数量。在

即使在一般的硬件上,每秒处理数千个最快过期的请求(例如,Fibonacci heap)也是微不足道的。在

我没有检查,但我怀疑其他人已经解决了大部分,如果不是所有的问题,你可以下载说代币经纪人。在

在我看来,所有20万人都可以得到一个“代币”开始,但只有200人可以完成代币。在

所以我想到了两件事; 1) 为什么不记录活动本身的“剩余座位数”,这样你就不用做计数了,也不会出现超额预订的情况,因为更新活动所需的锁会阻止活动低于零。在

2)在人员订阅期间,如果剩余座位降至零,则所有剩余令牌将失效,用户将被“踢出”注册流程(对此表示友好并致歉,但所有座位现在已满等)

相关问题 更多 >