双方玩家断开连接时未完成棋局的处理方案探讨
棋局中途玩家离场的状态保存与结束判定方案
现有方案的局限
- Redis存储状态:仅依赖玩家返回时检查超时,会导致大量超时状态堆积在Redis中无法及时清理;若后台定时扫库,又会额外消耗资源且存在延迟。
- Celery定时器:高并发场景下,大量定时任务会占用Celery调度资源,且玩家提前返回时的任务取消逻辑容易出现遗漏,引发误判。
更高效的组合解决方案:Redis原生过期机制 + 键空间通知
核心逻辑
- 状态存储与过期配置
将棋局状态(棋盘数据、玩家信息、回合进度等)序列化后存入Redis,为该键设置可配置的过期时间(如30分钟),同时关联棋局ID、玩家ID等元信息。 - 超时事件触发
开启Redis的键空间通知(notify-keyspace-events Ex),监听键的expired事件。当棋局状态键过期时,直接触发业务逻辑:标记棋局为超时结束、判定胜负(如双方离场则判和,单方离场则判另一方胜)、清理关联资源。 - 玩家返回续期处理
玩家返回时,先查询Redis中是否存在对应棋局状态:- 若存在,调用
EXPIRE命令重置该键的过期时间,恢复游戏进程; - 若已过期,提示玩家棋局已结束,引导开启新对局。
- 若存在,调用
方案优势
- 利用Redis原生过期机制,无需额外定时任务调度,性能损耗极低,高并发场景下稳定性更强;
- 续期逻辑简单直接,避免了Celery任务取消的复杂操作;
- 过期事件实时触发,超时判定无延迟,资源清理及时。
生产环境常规处理方式
- 多维度兜底校验
除Redis过期时间外,业务层额外记录棋局的最后活跃时间。玩家返回时,即使Redis键未过期,也需校验最后活跃时间与当前时间的间隔,避免Redis过期机制的微小延迟导致逻辑异常。 - 分布式锁保障一致性
多服务实例部署时,对棋局状态的更新操作(如续期、落子)加Redis分布式锁,防止并发修改引发的状态不一致。 - 持久化备份
定期将活跃棋局状态同步到持久化数据库(如MySQL、MongoDB),避免Redis宕机导致的状态丢失。Redis恢复后,可从数据库同步未过期的棋局状态。 - 分级超时策略
根据游戏类型设置差异化超时:休闲类棋局设30-60分钟超时,竞技类设10-15分钟;支持玩家主动申请延长超时(需经对方同意或系统审核)。 - 离线缓冲机制
玩家短暂离线(如网络波动)时,设置1-2分钟的缓冲期,缓冲期内不启动超时计时,避免误判。
内容的提问来源于stack exchange,提问作者Артем Асеев
相关产品推荐
相关产品推荐

