关系数据库:内存分区?理论结构讨论

BRP*_*ock 7 database-design architecture

我正在使用一些相当深奥的元素(理论上很好但在实践中很少使用)重写 MMORPG 服务器引擎,并且有点怀疑。其中的一些元素是“可靠的”——但做“又一个 MMO 服务器”的目的是在生产级代码中测试其中的一些概念。

然而,我希望这里的某个人可能对 PostgreSQL 分区模型有一些实践经验,并且能够“借”一些专业知识给这个项目。

概述

下面有一个 TL;DR 版本。

  • 核心操作系统结构是一个 Linux 实例集群,可能位于云系统上。用于监控整体系统性能和使用外部 API 启动新实例的存根计划用于以后的实现;出于测试目的,我们正在考虑使用亚马逊,但我们正在敞开大门,使其成为 RackSpace 和其他提供商的可插拔模块,甚至通过重新配置物理池、“热备用”来做一些顽皮的事情专用机架上的服务器。
  • 主要的 MMO 逻辑基于“纯”实体-组件-系统模型。实体“是”长整数 ID;组件是关系数据记录或记录集(列表)(JOINable 引用);系统就是功能。系统提供有关它们需要访问哪些组件的元数据,并且方法?整个集群的数据位置基于预测这些访问的规划器,试图在同一主机上继续运行相同的系统。也就是说:访问同一实体的同一组件的系统往往位于同一台机器上。
  • 关系数据存储由 PostgreSQL 数据库支持。之所以选择它,是因为它是自由软件,并且在某些方面比 MySQL 提供“更好”(出于我们的目的)SQL/ACID 服务。让我们假设这是一个不可变的(已经有很多争论了)。
  • 服务器主机实例代表一个单一的游戏世界,占据一个连续的坐标空间:游戏世界本身没有不连续性(例如关卡;星系统;世界实例)。因此,实体可以根据动态区域划分到主机上,其“大小”可能在运行时发生变化。这些区域可以或多或少地在 SQL 中有效地分区是“给定的”:例如,我们可以定义一个“Y=-10 处的分区平面”,并根据它们的 Y 坐标或类似方式拆分实体。用于此的精确机制可能会在模拟负载下进行一些实验。更改此分区规则将是一个相对不常见的事件:也许 5 或 10 分钟的计时器可能会监视服务器负载并尝试确定更优化的拆分。
  • 服务器主机可以是数据库服务器(集群)、游戏逻辑服务器或(集群大小=1 系统)两者。我们可以在主规划器系统的控制下启动数据库实例,并以任意复杂的方式配置它们以管理加入集群等,这是一个“给定的”。这可能包括创建底层 RAMdisc 或分区规则等。
  • 因此,给定主机的数据集可能是某组表(组件)的某种组合,但只对给定的实体池特别感兴趣,这些实体是通过单独的标准选择的。出于效率的目的,我们可能会在entities表中存储一列,指示它属于哪个“服务器位置池”,或者是提供该映射的单独表,或具有该效果的某些内容。
  • 有一个固有的假设,即只要后端数据库日志不被破坏,单个记录包含足够的数据来保持完整性。IE:只要是一个交易COMMIT,我们就不会在崩溃时非常关心我们是否获得任何特定交易的“之前”或“之后”图像。我想我在口头上混淆了这个概念:换句话说,为了崩溃恢复的目的,我们并不十分担心整个交易是否丢失,只要我们丢失整个交易。丢失集群主机(例如机器着火)的可能性在规划器级别处理,如果我们检测到心跳丢失,则可以相当快地重新分配该主机的责任区域。
  • 几乎每个主机的写入量都是读取量的一半左右,这比许多数据库系统的设计预期要高得多。

概述 (TL;DR)

我们有一堆带有 PostgreSQL 的 Linux boxen。我们有一些函数可以接收数据的子集,这些数据可以使用SELECTVIEW在这些主机上运行来定义,并且写出几乎与读取一样多的更改。

纯理论模型

这是它变得脆弱的地方:

组件直接映射到关系表和行。例如,假设最终有一个 Position 组件。实体 ID 将是表上的主键,对于一致性检查,也是entities仅包含 PKSERIAL8字段的表的外键。位置表然后有,比方说,x NUMERIC, y NUMERIC, z NUMERIC列。

然后,想象一个需要位置、质量和惯性组件的重力系统,以及另一个使用这些组件和物理体积组件的碰撞系统。

在完美(即性能无关紧要)的世界中,我们知道系统将使用SELECT具有某些标准的 SQL 来处理哪些实体。也许 PhysicalVolume 可能有一个边界框,可以快速剔除那些不占用物理体积,或者明显远离可能与之碰撞的任何其他实体的实体(一些不太花哨JOIN的 Position 和 PhysicalVolume )。因此,我们有一个枚举系统定义:它将需要从哪些组件中获取数据,以及一个SELECT查询以获取作为时间点、不可变记录结构的数据。这些记录被一一输入系统的run功能,并执行任何必要的更改。如果系统写入它不读取​​的组件,我们会提前声明,以保留数据局部性。

现实开始

当然,问题是SELECT来自远程磁盘的SQL不是人们想要在主模拟循环的每个“帧”中执行的那种事情。其中一些系统的运行频率可能超过 10Hz。

现在,我知道,“在此之前没有优化”,但这似乎是一个“注定要失败”的模型,除非有一种方法可以实时使用该理论模型。

作为大型安装的进一步必要选项,规划器系统可能还希望将实体“池”(最有可能是那些“物理上位于”游戏世界某个区域的实体)迁移到单个主机上,以平衡加载并保持必须命中任何通用后端数据库的“缓存未命中”相当低。

问题(终于!)

给定的

  • 一个数据池
    • 一组视图和可更新的视图
    • ...提供输入源和输出接收器:
      • 一组特定的系统
      • (表示为表列表)
      • …应用于枚举的实体池,
      • (表示为SERIAL8 REFERENCEs的非连续选择)

……有没有合理的方法来创建

  • 一个内存中的 PostgreSQL 实例(或类似的)
    • ...维护给定数据的主要权限...
  • 在不破坏一般事务完整性的情况下?

如果这是一个不合理的设计,我的后备概念是通过尝试将视图预加载到 RAM 中的临时表或其他东西来基本上模拟相同的效果,尽管我没有花太多时间考虑这可能会表现得有多差。

任何可以为基础理论模型服务的合理替代方案都值得赞赏。

gbn*_*gbn 3

这是一个很长的问题。

首先,我当前的项目(我是数据库人员,有 MMO 引擎专家来处理)是一种基于现成引擎的 MMORPG 形式。卷就像《Eve Online》或《坦克世界》卷。

现在给出一个正交的简短答案:

  • DB和Engine完全分离
    不要因为硬件优化而混搭
  • 硬件:数据库和引擎服务器的规格将有很大不同
  • 正常设计你的数据库

当然还有更多,但我建议你过度思考这个问题并搬起石头砸自己的脚。我只是将与投资银行业务相同的技术应用到 MMO 中,因为在我看来,大多数高容量系统应该收敛到类似的架构