有没有办法使诸如MMORPG的动态世界水平扩展?


11

想象一下,一个拥有500多个播放器的开放世界,其数据更改速度高达20个更新/播放器/秒。上一次我在类似的MMORPG中工作时,它使用SQL,因此很笨拙,无法始终查询数据库。而是将所有播放器作为C ++对象从数据库加载到内存中并使用它们。也就是说,它是垂直缩放的。可以使该服务器水平扩展吗?是否有一个旨在同时支持该数量的更新的数据库?


为什么要每秒更新数据库20次?
巴伦2013年

@Balon是我感到困惑的地方。如果我不更新数据库中的内容,而只更新内存中的内容,那么不同机器之间的状态将不同。但是我想数据库更新有一些巨大的开销,所以它真的不能用于这么多的更新吗?
MaiaVictor

2
如果您真的真的认为不同的机器(甚至进程)需要对数百个对象进行20Hz更新,则完全绕开数据库并直接使用消息传递系统。但是,您真正想要的并不是您真正想要的。您想要的是拥有一个合理的范围,该范围的人员需要知道什么,然后有一种方法可以在这些范围之间整齐地传输对象。您应该回答以下问题:为什么需要在不同的机器之间进行20Hz更新才能获得很好的答案,所以有人可能会想到一种解决问题的新方法。
Patrick Hughes

@PatrickHughes我不知道我需要什么,我只是在解释游戏的工作原理。字符移动2〜3个图块/秒。打猎的玩家可能被一些怪物包围着,因此,至少每秒钟玩家10格。然后,物品会在地板上,玩家的背包上腐烂。有攻击者朝着玩家的方向移动,有攻击者朝着怪物的方向移动。这会削弱生命值,会消耗法力值,还会对玩家施加毒药伤害。因此,事情的变化真的很快。这是游戏设计。这样的设计如何垂直缩放?
MaiaVictor

1
不久前,我在HackerNews上看到了这个消息:paralleluniverse.co他们正在开发一个数据库,该数据库可以为您完成所有的空间分割/分布工作。我想在幕后,他们正在做以下答案中的所有事情。
拖船

Answers:


17

500名玩家都进行交流的测试案例,即250K信息流以20Hz的速度传播。假设每个消息100字节,则其内部带宽约为500MB /秒。听起来雄心勃勃。特别是在过程之间。

如果将播放器分成100个组,则速度会降低到20MB /秒,依此类推。这就是为什么MMO具有区域,并且在这些区域中几乎没有影响的气泡,等等,直到带宽变得合理为止,等等。

最初的问题可以说是,如果您有10个人全部共享实时信息,但是您希望有500个人全部共享,那将是通信链接的指数增长,而我们如何解决这个问题。恐怕没有我听说过的魔术子弹可以神奇地使几何级数消失。

不要使用数据库进行通信,这就是消息传递的目的。使用数据库执行交易并存储您不希望玩家输掉的信息。我熟悉的大多数MMO仅每1-10分钟或在诸如区域转换或在设计中输入“安全”区域等方便点时使用动态播放器信息更新数据库。

无论距离多远,您可能都必须重新设计每个玩家的游戏需求,才能实时更新每个其他玩家的背包内容。

还要将更新模式从20Hz更改为基于距离的速度,1英里远的人不需要知道您在230.6秒时移动了1英尺,然后在231.4秒时又移动了1英尺,他们就可以应对您每10英尺移动15英尺的情况秒。


真棒和翔实的答案,谢谢。但是我可能要补充一点,尽管世界变化非常快,但是一个玩家只能看到紧邻他的其他玩家。我认为它不是几何图形-500个玩家将信息发送到服务器;服务器会定期向这500个玩家发送信息。如我所见,它是线性的。但要点是第4段:如果我仅使用数据库进行存储,则将数据加载到内存中。如果要将数据加载到计算机中的内存中,那么我将创建世界的不同步版本。那是我不明白的。
MaiaVictor

对于1个客户端:1 msg输出+ 1 msg输入=2。对于2个客户端:2 msg输出,2 msg输入=4。对于3个客户端:3 msg输出,3 msg输入=9。这样就可以了。就像这样:发送状态msg,服务器将结果发送给我,其他2个客户端(1进3出)和3个客户端都进行此操作(1进9出)。尽管对于三个客户端中的一个客户端,它看起来是线性的,但是您可以将其乘以所有客户端,以获得系统的总吞吐量。对于取消同步,即使在同一物理设备上的进程也不同步,直到创建并发送状态消息为止,这只是管道清空的位置(本地RAM或网络)的问题。
Patrick Hughes

5

使用关注区域过滤。如果一个世界分成3台服务器,并且服务器1上的区域与服务器3的区域相距甚远,则根本没有理由让他们共享有关实体的信息。

同样,在单个服务器上,仅将相关信息发送给客户端。如果玩家A在地图上与玩家B完全相反的一端,则没有理由将有关B的更新发送给A,反之亦然。

如果您在一个连续的世界中有多个服务器,则服务器2上的某个边缘附近的实体将与服务器1上的实体接近。您可以将实体的“权威”服务器中的更新发送到其他服务器(如果适用) ,并根据需要将所有消息转发到权威服务器。

是的,在这种情况下,特定实体的一台服务器将有些过时。不要试图解决这个问题。只是处理它。假设实体可能有点过时。仅在权威拥有实体的服务器上执行任何需要最新信息的逻辑。当一个实体影响另一个实体时,请发送一条消息,并假设它可能需要经过多个游戏逻辑滴答之后才能处理并更新您的视图。

这种设计还使线程化单个服务器变得更加容易。任何实体都不应直接修改另一个实体,而只能发送消息,并且应假定本地每个服务器/每个线程的代理缓存已过时。

例如,如果实体A攻击实体B,则不要检查B的寿命,如果它命中0,则不发送死亡消息。只需发送“损坏”消息,让B的权威服务器处理它,然后处理如果实体A关心服务器B稍后发出的“实体死亡”消息。

这同样适用于任何大型的,可扩展的非游戏应用程序。中央数据库并不是一种神奇的即时共享技术。为了保持高吞吐量,两台服务器必须批量异步地与消息通信。因此,诸如AMPQ等技术的普及。数据库用于存储并出于必要而支持同步,从而使其可以用于通信,而不是因为它们本身是用于同步或通信的。


谢谢,这结束了我大部分剩余的疑问。另外,您还给了我将服务器分开的想法,而不是按区域分开-这样看起来会更流畅。每个服务器负责x个播放器。我真的很喜欢这个!这是用的吗?而且,还有一件事。正如我上面所问的,我刚刚了解了一个新的NoSQL数据库Couchbase。除了非常快的读写速度外,它应该像CouchDB一样:每秒高达20万次更新!也许这实际上可以像“实时共享世界模型”那样工作,还是没有呢?
MaiaVictor 2013年

除了通常的服务器粗分片之外,我还不知道是否在野外使用了该技术。仅通过玩家和地理区域来做到这一点,就意味着每个服务器可能需要了解分布在不同区域中的大量实体,从而增加了服务器负载并大大增加了服务器之间的通信。按区域进行操作意味着您的服务器可能会在拥挤的区域上超负荷(尽管在这种情况下您可以动态拆分和合并区域),但是这意味着每台服务器都有一组较小的相关非玩家实体和几何体来跟踪。
肖恩·米德迪奇

@Dokkat:可能有某种“软区域”,在该软区域中,每个服务器主要处理游戏世界中特定部分的玩家,但是如果他们偏离玩家太远,则将它们透明地移交给另一台服务器他们原始服务器的区域。您只需要确保切换足够顺畅,玩家就不会真正注意到它。您甚至可以尝试使用一些奇特的自适应技术,以将交互播放器的群集保持在同一服务器上,即使它们恰好位于区域边界上。
Ilmari Karonen


2

不要将数据库视为某种实时共享的世界模型,该模型始终存储所有内容,就像您已经注意到的那样,这可能行不通。

而是将数据库更像是一个自动更新的保存文件:您仅偶尔更新数据库,例如,当玩家登录或注销或从一个区域移动到另一个区域时,或者在您不想成为重要事件时在服务器崩溃的情况下丢失。

就像您的原始示例一样,实际的实时世界状态应由游戏服务器保存在内存中。现在,水平扩展的诀窍在于,并非每个服务器都需要随时了解所有信息。例如,如果玩家A在服务器A的区域A中玩游戏,则运行区域B的服务器B通常不需要知道玩家A的背包里有什么东西-并且,如果确实由于某些原因需要知道它(例如,因为区域B中的玩家B在A)上施放了某种远程监视咒语,所以它可以向另一台服务器询问该信息

这确实需要您为服务器分配明确的责任,以便当服务器B想了解玩家A的背包时,它将知道哪个服务器具有有关该服务器的权威信息。您可能还希望包括某种更新订阅机制,以便例如服务器B可以告诉服务器A“ 我有某人在监视玩家A,让我了解他们所做的一切,直到我告诉其他人为止。 ”您可能会还希望包括一些重要的全球性事件的全球广播系统,玩家无论身在何处都可能需要了解这些事件;当然,此类事件也应记录在数据库中,但是让它们主动广播到所有服务器意味着服务器不必继续轮询数据库以获取更新。


很棒的答案!这正是我要问的,谢谢。因此,也许关键在于将服务器划分为多个区域,并将逻辑保留在内存中。不过,我可能会补充:我刚刚了解了一个新的NoSQL数据库Couchbase。除了非常快的读写速度外,它应该像CouchDB一样:每秒高达20万次更新!也许这实际上可以像“实时共享世界模型”那样工作,还是没有呢?
MaiaVictor

@Dokkat不,不会。Couchbase不是魔术。
菲利普

2

其他答复也很好地指出了如何使用数据库,而不是使用数据库进行通信。您可能需要考虑的另一方面是根据需要如何将信息传达给其他实体来对更新进行分类。您可以分发消息传递并使用pubsub机制在实体之间传递更新,而不是与服务器进行通信。例如,您可能会根据与您接近的人来区别对待位置:

  • 精确的实时定位在半径R内可能有用
  • 半径2 * R内精度较低,频率较低的位置更新可能会有用
  • 半径2 * R以上可能不需要位置信息

您可以通过定期扫描半径2 * R(或基于实体的更新速率和最大速度的半径的倍数)内的实体,并将该实体订阅另一个实体的精确或不精确的位置信息,来传达实体的位置信息。

您可以针对不同类型的信息采用不同的策略,将常见的事物分组到相同的消息队列中,或者对需要发送到不同实体的消息使用不同的队列(或者只是将它们发送到最广泛的实体集,如果它们被丢弃,则将其丢弃) '没有用)。

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.