如何在用户离线时修改其SQL数据?多人网页游戏开发相关问题
多人网页游戏离线玩家数据准实时更新解决方案
针对你提到的「离线玩家数据需要定时更新且支持全量玩家实时查询」的需求,以下两种是生产环境常用的可落地方案:
方案1:服务器端常驻定时任务(高可靠首选)
- 依赖服务器端定时调度能力实现全局批量更新,可选工具包括Linux自带的
cron、PHP生态的Workerman、Python生态的Celery Beat、Java生态的xxl-job等 - 首先修改玩家表结构,新增3个字段:
x_remaining_calc:INT类型,记录x字段还需要执行扣减的总次数last_x_calc_time:DATETIME类型,记录x字段上次执行扣减的时间- 给
x_remaining_calc和last_x_calc_time加联合索引,优化查询性能
- 编写定时任务每10秒执行1次以下SQL,批量更新所有待处理的玩家数据:
UPDATE player_table SET x = x - 1, x_remaining_calc = x_remaining_calc - 1, last_x_calc_time = NOW() WHERE x_remaining_calc > 0 AND last_x_calc_time < DATE_SUB(NOW(), INTERVAL 10 SECOND)
- 优势:数据全局一致,不管有没有玩家查询,数据都会按时更新,适合大流量高并发的游戏场景
方案2:查询触发式增量更新(中小项目低成本首选)
- 不需要额外部署定时任务服务,利用玩家的查询请求顺带更新目标数据,完美适配「所有玩家可查看他人数据」的需求
- 同样需要新增上述
x_remaining_calc和last_x_calc_time两个字段 - 每次执行玩家数据查询请求(不管是查自己还是查其他玩家)前,先对本次查询涉及的所有玩家ID执行一次批量更新:
UPDATE player_table SET x = x - LEAST(x_remaining_calc, FLOOR(TIMESTAMPDIFF(SECOND, last_x_calc_time, NOW()) / 10)), x_remaining_calc = x_remaining_calc - LEAST(x_remaining_calc, FLOOR(TIMESTAMPDIFF(SECOND, last_x_calc_time, NOW()) / 10)), last_x_calc_time = NOW() WHERE player_id IN (/* 替换为本次查询涉及的所有玩家ID列表 */) AND x_remaining_calc > 0
- 优势:无额外服务依赖,资源消耗极低,只要有玩家查询对应数据,数据就会更新到最新状态,就算长时间没有玩家查询某个离线用户的数据,旧数据也不会影响任何业务逻辑
注意事项
- 所有数据更新操作必须在数据库层面执行原子计算,不要先将数据查询到后端业务层计算后再回写,避免并发请求导致的数据不一致
- 不要尝试依赖前端页面刷新触发更新,离线用户不会打开页面,完全无法触发更新操作
内容的提问来源于stack exchange,提问作者raivo
相关产品推荐
相关产品推荐

