[英]Java concurrent counter architecture design
Having the following business case:具有以下业务案例:
Email promotional campaign says that first 1_000_000 users pressing the link will receive a Bonus. Email 促销活动说,前 1_000_000 名用户点击链接将获得奖金。 Users are going to see either the Bonus or "Sorry" message immediately during visiting web page.用户在访问 web 页面时将立即看到奖励或“抱歉”消息。
Question: how to design this solution?问题:如何设计这个解决方案?
Plain Old Java: Use in-memory synchronization using java lock semantics. Plain Old Java:使用 java 锁定语义使用内存同步。 You are correct about using AtomicInteger.您对使用 AtomicInteger 是正确的。 However, this can only work if you have only one application instance running.但是,这只有在您只运行一个应用程序实例时才有效。
With MySql: There is a feature called select for update
that helps you achieve what you are looking for.使用 MySql:有一个名为select for update
功能可帮助您实现所需的功能。 Whenever someone clicks on the link, you do select for update
in MySql to see if the bonus is still available.每当有人单击该链接时,您都会执行select for update
,以查看奖金是否仍然可用。 If it is, you do update in DB in the same transaction.如果是,您确实在同一事务中更新数据库。 Meanwhile, all other parallel reads and writes will be blocked.同时,所有其他并行读取和写入都将被阻止。 Hence you get end-to-end fully atomic operation.因此,您可以获得端到端的完全原子操作。
Redis won't work because even if INCR
is atomic, the whole flow of reading the value from Redis, performing the business logic, and updating the value in Redis won't be atomic. Redis 不起作用,因为即使INCR
是原子的,从 Redis 读取值、执行业务逻辑和更新 ZE111446745A1825B862F8727AE63BCE4 中的值的整个流程都不会是原子的。 Eg Say the user count in Redis was 999_999
and 2 users concurrently click on the link.例如,假设 Redis 中的用户数为999_999
,并且有 2 个用户同时点击链接。 The application checks the count and it's under the threshold of 1_000_000
which means, both users are eligible for a discount and you end up giving a discount to both.应用程序检查计数并且它低于1_000_000
的阈值,这意味着,两个用户都有资格获得折扣,而您最终给两个用户都打了折扣。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.