【问题标题】:Improve MMO game performance提高 MMO 游戏性能
【发布时间】:2012-10-03 12:58:42
【问题描述】:

我们都知道 MMO 游戏的流行趋势。玩家在现场面对面。

我关心的领域是存储玩家动作和游戏结果。

通过 NPGSQL 适配器使用 Csharp 和 PostgreSql v9.0

游戏客户端是基于浏览器的 ASP.NET,并为所有与数据库相关的处理调用 Csharp 函数

要理解我的查询,请考虑以下场景

我们将游戏进度存储在 postgres 表中。

例如锦标赛开始时有四名玩家和以下活动

  1. 每个玩家一开始有 100 个生命值
  2. 玩家 1 进行打击(我们参考图表将打击转换为随机范围 % 的生命值)
  3. 玩家 2 有 92HP,并且还击,所以玩家 1 有 98HP

以上两轮现在将在游戏进度表中,因为

ROW Player1HP Player2HP Strikefrom StrikeTo ReturnStrikeHP Round TimeStamp StrikeMethod
1      100       100         0        0            0          0
2       98        92        P1        P2           2          1

要确定锦标赛是否结束,我们检查 3 名玩家的生命值为零或游戏时间已超过上次进度的规定超时值

我们的桌子有一个主键作为锦标赛 ID,基于 playerids 的随机 32 个字符代码(每个玩家 8 个)

还有护甲、法力、法术等其他栏目,每个玩家都会结转,总共有48个栏目——每个玩家12个栏目和他们的属性

最后有一个 gameResult 表,其中包含锦标赛的结果,带有锦标赛 ID、锦标赛时间戳、游戏结果(完成、PlayerSurrender、InvalidSession、SecurityHack、TimeOut)、winnerPlayer、playerMetrics、rowIDfrom、rowIDto

查询

我的问题集中在减少游戏数据库或 Sql 上的负载 查询

a) 如何检测玩家是否未同时登录并打开两个游戏会话但无需参考数据库或使用 Sql

b) 如何控制 GameProgress 表中记录的激增。让玩家更快得到响应。服务器在高峰时段或 1000 名玩家在线时开始延迟

There is a tremendous flow of sql queries, for ex. even in the current game version
There are average/minimum 100 tournaments online per 12 minutes or 500 players / hour
In Game Progress table, We are storing each player move 
    a 12 round tourament of 4 player there can be 48 records
    plus around same number for spells or special items
    a total of 96 per tourament or 48000 record inserts per hour (500 players/hour)

我还考虑在 Csharp 中使用后台进程,该进程不断将过期的锦标赛记录从 GameProgresstable 移动到另一个数据库,在该数据库中我们的服务器没有游戏负载。

c) 我们应该多久运行一次充满 postgres 的 vaccum。

我对可以提高性能的新应用程序开源或 toPay 持开放态度。例如。我们使用 FastCsvReader http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader 来改进服务器日志文件的枚举。

问候 阿文德

【问题讨论】:

    标签: c# asp.net postgresql mmo


    【解决方案1】:
     How to detect if a player has not logged in simutaneously and opened two game sessions 
     but without having to refer to a Database or using Sql
    

    假设您使用多个服务器,您会在某处创建一个仅注册登录和注销的进程。每当两者之一发生时,您都会调用它。您可以使用该过程来检查用户是否已经登录。您可以通过例如在所有服务器上运行此过程并使用算法仅对一部分用户使用 serverx 来平衡此过程。假设您有 10 台服务器,请执行 (userId % 10) 以获取用户注册登录/注销的服务器的 ID。

    这样,您只需在内存中通过服务器之间的调用进行这些检查。可能您将需要超时/刷新调用,以便断开连接的用户或崩溃的服务器不会让用户永远保持登录状态。

    How to control the surge of records into the GameProgress table. so that players get
    response quicker. The Server starts to lag at peak hours or when 1000 players are
    online
    

    #1 将 postgress 数据库切换为使用 SSD 进行存储

    #2 将整个过程提升到内存中,不要将数据库用于实时工作

    #3 更新数据库中的记录而不是创建新记录

    #4 使用多个数据库并将用户分布在它们之上

    #5 ....

    Our table has a primarykey as tournamentid a random 32 character code on basis of
    playerids. 
    

    随机生成的主键是非常糟糕的做法恕我直言。使用一个序列,否则任何东西都保证是唯一的。如果你的随机码不够随机,你会得到非常讨厌的错误。您只需要在每个游戏中生成一次,因此它不是性能瓶颈。

    【讨论】:

    • 对不起!我忘了在primarykey中提到时间戳,它实际上是锦标赛ID+游戏开始时间的组合。我们不生成它,而是将所有玩家 ID 和时间戳结合起来,它不能比这个更独特。 SSD 对于这种流量是否可靠。 Postgres 是一个独立于驱动的数据库软件。
    • 随机主键列的另一个问题是它倾向于更均匀地分布必须在索引扫描中命中的索引页。这不一定是好事。
    【解决方案2】:

    我推荐的另一件事是考虑将系统中经常更新的部分移至 VoltDB 之类的东西,尽管它具有复杂性成本。这会带来复杂性成本,您可能希望获得他们的商业许可/支持。但是,如果您还具有灾难恢复功能,主内存数据库在这种负载上的好处可能是值得的。然后,您的 PostgreSQL 实例可以处理长期数据,而 VoltDB 可以处理实时处理。

    【讨论】:

    • 谢谢,我会研究一下 voltDb。同时,您建议将所有内容或至少实时锦标赛的数据放入内存并仅在完成后保存它们,这真是太棒了。它将服务器执行速度提高到新高。
    猜你喜欢
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    相关资源
    最近更新 更多