【问题标题】:Web game concurrency control网页游戏并发控制
【发布时间】:2011-05-07 08:02:10
【问题描述】:

还有一些其他关于并发的 SO 问题,但它们并不能完全解决我的情况。

假设我有一个游戏,用户可以在其中进行互动、打架等等。在任何给定时间,玩家都可能参与与其他玩家的多次互动,所有人都可以看到事件的发生。当这些玩家中的任何一个访问该网站时,它需要更新所涉及的所有数据并将其显示给用户。

示例情况:玩家 A 正在与玩家 B 战斗,并且在这场战斗中每隔几分钟就会发生一次事件。同时,玩家 A 也在与玩家 C 交互。运气不好的是,这两个交互的事件恰好在同一秒发生。

当那一秒到来时,再次碰巧,玩家 B 和玩家 C 同时访问该站点,以检查他们与玩家 A 的战斗状态。战斗需要更新玩家 A 的信息。如果我编码不正确,A的数据可能会乱码。

我有两场比赛遇到这种情况,每场比赛都有不同的解决方案和不同的问题。其中一个使用锁,因此当用户访问该站点时,他们会在数据库行上获取锁,读取他们成功获取的锁的数据,然后写入更改并释放锁。但有时,出于未知的原因,这会失败并且锁会永远卡住,用户抱怨,我们必须手动修复它。我的另一个游戏使用守护进程来执行这些事务,使问题(几乎)没有实际意义,因为只有一个进程会进行这些更改。但玩家仍然可以同时做其他事情,并可能导致同样的问题。

我已经阅读了一些关于此问题的不同解决方案的信息,例如乐观控制或基于时间戳的控制。我想问一下:

  1. 其中哪些最常用于像我这样的情况,哪些最容易实现?

  2. 我的下一个项目是使用 Kohana (PHP) 及其 ORM,因此我的 db 写入默认情况下采用“仅覆盖所有这些字段”的形式。我需要为此编写自己的更新查询,还是可以获得与 ORM 兼容的解决方案?

  3. 涉及多个表的事务怎么办?战斗的结果必须改变战斗表,玩家信息表,可能还有更多的东西。哪些解决方案在这里更容易使用?我的所有表都需要事务时间戳列吗?

  4. 这些解决方案中的很多都表示,当发生冲突时,要么重试,要么忽略。这对我意味着什么? “重试”是否意味着重新启动我的整个脚本,这会导致用户额外的加载时间?我不认为忽略是一个有效的选择,因为事件必须在某个时候执行。在我发现的其他问题中,向用户显示冲突错误通常是一个有效的选项 - 对我来说不是。

  5. 并发控制对性能有何影响 - 是否值得?

【问题讨论】:

    标签: php database web-applications concurrency


    【解决方案1】:

    我认为您正在寻找的内容已经包含在您的问题中:交易。 如果您使用的是 MySQL,则需要使用 innoDb 引擎设置表才能使用事务。一些文档:

    尽可能不要尝试重新发明轮子。

    【讨论】:

    • 但是在我读取要修改的数据后,其他人不能在我进行计算时修改数据吗?在提交我的事务之前,我必须手动验证数据没有被更改,但验证和提交本身不是原子的。或者我的查询应该是“更新 WHERE 所有数据是我所期望的”,如果我有 0 行受到影响,我知道我需要重试?
    • 啊 - 选择更新。所以对于 2. 我必须在我的 ORM 中修改一些东西。对于问题 4 - 我不需要重试,因为它总是会读取最新数据?
    • 问题是,由于 php 单请求操作模式,用户可能会看到某些内容(第一个请求)并在另一个用户之后执行其他操作。但是他们通常知道它可能会发生(这就是为什么在某些游戏中,你有 F5 大用户几乎实时地检查正在发生的事情:p),但只要你在任何计算之前开始事务并在最后提交或回滚,如果您在执行操作之前检查执行某事的条件是否满足,您应该不会有问题。
    猜你喜欢
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多