在持久性在线游戏中多久保存一次玩家的状态?


9

在在线游戏中,人们喜欢随时随地登录和注销。通常,他们的游戏成就会无缝保存在服务器上。这并不是很难实现,但是我想知道如何以有效且可行的方式完成并扩展规模。

每次发送时都保存玩家的坐标和状态是否有意义?我的node.js服务器可以轻松地做到这一点而不会阻塞响应,我想使用Mongo数据库,但是也许每秒一次并且在服务器范围内的事件中一次收集所有一次更合适?


我每10秒保存一次游戏状态。我认为这就足够了,它没有引起注意(并且我在具有512Mb RAM的上网本上运行MMORPG服务器)。
jcora 2011年

Answers:


10

我想到了像《魔兽世界》这样的传统MMORPG。

在每个玩家和自治事物(例如NPC)执行每个命令后保存

  • 持续备份。服务器可以随时关闭,并且游戏状态可以保存到该时刻(或者无论如何都尽可能近)。
  • 对服务器性能的影响;即使它是非阻塞的(即在另一个线程上),即使数据库在另一台服务器上,它也正在处理您否则不会执行的处理。如果它像您说的那样是非阻塞的,则必须由另一个线程来处理它,而该线程可能会被其他线程占用。
  • 磁盘I / O增加,从而增加了风险/故障率。如果您要使用SSD进行存储,则使用寿命特别短,这尤其值得关注。
  • 如果将数据库卸载到另一台服务器,则带宽增加;如果您要为带宽付费,这可能是一个问题,并且如果它不在单独的网卡上,则说明它占用的资源本来可以更好地用于处理播放器流量。
  • 如果服务器在保存这些命令的状态时越走越远怎么办?即,如果输入的命令多于可保存的命令,那么它们会堆积在队列中吗?这个队列是否溢出并导致错误?您是否停止一切以使队列能够赶上?
  • 在我看来,这种方法虽然听起来很简单,但需要仔细计划。例如,相互依赖的连续命令将需要保存在一起。否则,命令中间可能会发生故障,并且只会保存一个,而不会保存另一个。考虑是否有两个玩家执行交易并将两个命令保存到磁盘:“将项目1加到接收方”和“从发件人中减去1”。如果在第一个命令之后但在保存第二个命令之前发生故障,则说明您有一个重复项。(如果订单被冲销,则您有丢失的物品)

定期保存所有内容

  • 如果发生故障,服务器将有些过时。希望您使用类似日志记录的方法,以便最近的快照至少是完整且一致的,并且所有活动的参与者都将花费相同的时间。
  • 无论您使用哪种数据库系统,都可能会对批处理更新进行了优化,这比一次更新一个更新效率更高(开销更少)。
  • 如果您选择使用二进制文件系统,则此方法非常简单。制作一个新文件,将内存转储到该文件中,并在末尾添加一个标记,表明备份已完全完成。一次备份完成后,删除上一个备份(或不删除)。
  • 备份过程可能还需要考虑另一部分最后一点中提到的内容,例如保存在不应拆分的连续命令中间。您可能会选择锁定整个数据集,将其转储到磁盘上,然后再对其进行解锁,但是取决于所花费的时间,它可能会导致游戏暂停或放慢速度。

在注销时保存角色(不保存其他任何内容)

  • 对玩家而言,最重要的是他们的性格,包括他们拥有的物品,所获得的技能,他们的朋友名单等等。如果他们杀死了一个怪物,并且战利品在他们面前的地面上,然后服务器发生故障,那么他们将很伤心,因为他们没有机会捡起他们的战利品,但是他们会克服它。因此,只保存重要的内容,而不要流失小的内容。例如,不要保存NPC的位置。如果服务器出现故障,则当服务器重新启动时,它们将在应有的常规区域中产生。当然,由于某些原因而需要保留在其位置的所有“智能” NPC例外服务器何时停机。
  • 此外,玩家一次不应登录太多小时(请注意,此处我正在考虑注销时“回到大厅”)。他们最终将需要洗手间休息或吃东西,或者被父母/朋友/任何人打扰或睡觉。因此,即使对于最顽固的游戏玩家,他们也不应该连续8小时以上不间断地登录。如果“玩家”登录了很长一段时间,则很有可能是多个人或一个机器人,而这既不是理想的游戏,也不是正常的游戏。
  • 同样,您的注销过程应该已经在检查类似上述连续命令的内容。它实际上应该已经打包了字符,因此显然是将其转储到磁盘的黄金时间。

总结思想

  • 显然,我支持最后一种方法,但是我尝试对这三种方法都保持公正。
  • 很难说前两种方法中哪一种更浪费。对于第一种方法,如果角色发送多个移动命令,则这些命令将被保存到磁盘并被覆盖(如果很明显它们可以打包成一个命令)。但是使用第二种方法时,如果您有一半的人口站着,即使他们的位置与上次备份操作之后的位置完全相同,也会将它们的位置保存到磁盘中。在第三种情况下,很可能有人可以登录并立即注销,但是大多数情况下,有关播放器的许多事情都将发生变化,因此浪费似乎很小。
  • 请记住,这完全是为了在发生故障的情况下进行备份,因此应绝对减少故障。最好处理这种异常情况,但是最后,如果服务器发生故障,某些数据将丢失,并且某些播放器将被破坏。因此,只需实施您可以采用的任何方法,您认为最简单或最好的任何方法,然后继续。
  • 不要依赖于此作为默认保存;在服务器应用程序上放置一个不错的关闭按钮,该按钮可以正常关闭连接并将所有内容写入数据库。正常使用。

最后,不要把这个建议当作绝对真理。我尚未编写多人备份系统。我正在工作的一个在线“游戏”,这就是为什么我已经想到了这一点,并写了我的想法上面,但我还没有得到对尚未执行这一阶段。因此,本文是在没有实际经验的情况下编写的,而是经过大量阅读和收集有关该主题的知识后得出的。


4
从我个人观察到,商业MMO结合使用了所有这三种。在重要事件和行动(例如老板杀害/抢劫/交易)之后,会定期进行保存,以防止错过不重要的行动(并且不惩罚长时间登录的人),并始终在注销时发生。一种方法通常是不够的。几乎所有这些方法都依赖于基础SQL样式数据库,如果存在硬件故障,该数据库将透明备份和还原。
NtscCobalt

@NtscCobalt-在“ SQL样式数据库”之前,我一直与您在一起。真的需要SQL吗?那NoSQL呢?
Beatgammit 2013年

@tjameson好吧,我的评论是在接触NoSQL之前写的。我只是想说您不应该使用自己的格式,但是无论如何,我仍然建议您使用SQL,因为您应该事先了解架构(或者是懒惰并使用Entity-Key-Value),并且一致性比对该数据进行分区的能力。有关更多信息,请参见stackoverflow.com/questions/7339374/…
NtscCobalt

1

我想这取决于游戏的类型以及玩家与服务器之间的通信量。

在MMORPG中,每次将信息发送到服务器时,保存玩家位置都没有意义。可以这么说,当玩家的当前数据“陈旧”时进行更新更有意义。在重大事件中保存玩家的状态也可能是有益的,例如进入新领域,打败老板或离开商店。

在基于回合的游戏中,每次结束回合以及在对方回合之后保存玩家的状态绝对是有意义的(保存生命值损失,咒语效果等)。

同样,答案完全取决于服务器的规模和功能。这是关于找到最佳平衡并在不牺牲质量的情况下尽可能地优化。


1

如果您唯一关心的是他们何时注销,那么一个简单的答案就是在游戏世界中不再存在任何条件(由于注销或断开连接)的情况下保存他们的位置。

不过,从侧面来看,我会有些警惕客户端向服务器报告其位置,或者至少在没有某种形式的服务器端完整性检查的情况下。但是,如果您已经有此位置,则可以不必注销或断开连接而保存该位置,因为您不必担心直接从客户端获取任何数据。


是的,因此需要定期向服务器发送有关位置和XP之类的值的更新。您留下的时间越长,关于玩家是否实际累积报告的增量的争议就越大。如果您限制那些“签到”时间段,则监视/控制要容易得多。
工程师

告诉玩家何时在长时间运行的浏览器游戏中准确注销的问题实际上并不是一件容易的事。
兰博

我同意这是不平凡的,但这是一个问题,无论如何,即使您要决定何时不再显示化身,无论如何在大多数游戏中都必须以一种或另一种方式解决。一旦完成,挂入该场景并保存其最后一个有效位置应该是一个相对简单的事情。
鲁宁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.