You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Next.js、PlanetScale与Ably的实时竞答系统并发问题咨询

实时竞答系统多数据库事务场景优化方案

一、拆分事务,缩小锁持有范围

原方案把所有操作塞进单个大事务,会拉长锁的持有时间,加剧并发冲突。建议按业务维度拆分:

  • 用户权限验证独立处理:将userDeadline表的验证与更新单独做成小事务,或者直接用INSERT ... ON DUPLICATE KEY UPDATE原子语句完成,这部分属于用户维度操作,和游戏维度逻辑隔离,不会和其他用户的游戏操作产生锁竞争。
  • 核心竞态逻辑单独封装:仅把“判断游戏是否需要升级等级”这一核心竞态场景留在事务内,其他非核心操作(比如插入猜测记录、验证答案正确性)移出事务,或异步处理。

二、优化游戏等级升级的核心竞态逻辑

针对“猜测次数>level*X时升级到level2,且仅升级一次”的需求,用数据库原子操作替代先查后改的逻辑:

UPDATE game
SET level = 2, updated_at = NOW()
WHERE game_id = ? 
  AND level = 1 
  AND (SELECT COUNT(*) FROM guess WHERE game_id = ?) > 1 * X;

执行这条语句后,通过受影响行数判断是否升级成功:如果受影响行数>0,说明升级生效,此时再通过Ably向所有客户端推送等级升级事件。这种方式把判断与更新逻辑原子化,不需要包裹大事务,能大幅降低锁冲突概率。

另外可以用Redis缓存游戏当前level:用户提交答案时先查缓存,若已是level2直接跳过升级判断;若为level1再走上述数据库原子更新逻辑,更新成功后同步刷新缓存,减少数据库查询压力。

三、异步化非核心操作

将不需要同步完成的操作丢到异步队列(如BullMQ)处理:

  • 用户提交答案后,先完成权限验证、答案正确性校验、核心等级判断,再把插入guess表的操作异步执行,缩短同步请求的响应时间,减少事务内操作数量。
  • 验证答案正确后,异步更新game表的关闭状态,同时通过Ably推送游戏结束事件,只要保证事件推送与数据库更新最终一致即可,无需强同步。

四、结合Pub/Sub做事件驱动

利用Ably的实时消息能力,将部分逻辑从数据库事务转移到事件流:

  • 用户提交答案并通过权限验证后,先向Ably发送guess_submitted事件(包含game_id、user_id、answer等信息),后台服务监听该事件统一处理插入猜测记录、统计次数、等级升级判断等操作,分散并发请求对数据库的直接冲击。
  • 当后台服务判定游戏需要升级时,发送game_level_up事件到Ably,所有客户端监听该事件即可同步界面状态,无需依赖数据库同步通知。

五、数据库层面针对性优化

针对PlanetScale(MySQL兼容)的特性做优化:

  • 给game表的game_id+level加联合索引,guess表的game_id加索引,userDeadline表的user_id+game_id加联合索引,提升查询与更新的效率。
  • 严格控制事务时长,PlanetScale对长事务支持有限,确保事务仅包含必须的原子操作,时长控制在毫秒级。
  • 开启读写分离,将查询类操作(如查询游戏信息、统计猜测次数)路由到只读副本,减轻主库压力。

内容的提问来源于stack exchange,提问作者Pieter Moeyersons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:45:17