定期将所有已登录角色保存在MMO中​​的性能优势是什么?


26

大多数MMORPGS具有Worldsave系统,该系统每隔X小时保存一次所有字符。我想原因是性能。那么,为什么在性能上比在断开连接时保存字符更好呢?


34
这不是为了表现;这会牺牲正确性的性能,这一点更为重要。
梅森惠勒

时间在这里真的起什么作用吗?AFAIK,mmo中的每个动作都会立即保存。您会收到一个项目,并且该项目会立即添加到服务器上,而不会延迟您的帐户,否则服务器将必须记住您已这样做,然后在5分钟后再执行此操作,这没有任何好处。否则客户端将不得不记住并在5分钟后将其发送,这现在使您容易受到黑客攻击,因为在这5分钟内任何人都可以更改/添加要发送的数据。
HopefullyHelpful

4
@HopefullyHelpful不,那不是事实。MMO中的每个动作都会立即存储内存中,但这只是暂时的。即使使用SSD,将所有内容直接保存到永久性存储仍然太昂贵。即使使用直接保存到数据库的游戏,数据库本身也不会立即将数据保存到磁盘(或至少仅保存事务日志,而不保存一致的数据-这需要在崩溃时进行重建,并且需要相当长的时间)时间)。但是由于另一个原因-保持一致性,节省断开连接是一个坏主意。
a安

1
我认为这个问题将更多地体现在间隔和实时保存字符的性能优势上。
安东尼

2
@Luaan:完全有可能将每个状态更改保存到持久存储中,即使是在机械硬盘上也是如此。(在繁忙的服务器上可能需要一些)。诀窍是更新单个对象。相反,您保存一个事务日志“ Player(A)。库存+ = Object(B)`。定期刷新整个状态。要恢复,请重新加载最新的完整保存并从事务日志中应用最新的事务。 “按顺序写入一个文件,可以达到机械硬盘的最高性能。但是要保持事务日志的大小合理,则需要定期进行完全保存
。– MSalters

Answers:


66

这不是为了性能。这是故障保护。如果世界每隔几分钟保存一次,那么如果服务器发生故障并关闭,则每个人只会损失几分钟的进度。

通过节省断开连接的时间,如果服务器出现问题,则每个人都将失去自登录以来所做的一切。对于那些玩特别长时间的游戏(在MMO中​​很常见)的人,他们将丢失大量数据。

他们牺牲一点性能来消除海量数据丢失的风险。

当然,您可以轻松地将播放器数据存储在客户端计算机上,从而减少网络流量。这里的问题是它容易受到黑客攻击。一旦一个人弄清楚了如何作弊,他们就会分享它,每个人都在做。


编辑:正如@Philipp指出的那样,这也删除了重复项的功能。在断开连接保存系统中,如果在服务器崩溃之前进行了交易,而一个人在崩溃之前注销,则这两个玩家都将回滚到上一次注销的时间,即删除项目或复制它们。


评论不作进一步讨论;此对话已转移至聊天
乔什(Josh)

5

早期仅在断开连接时保存的系统往往也会在播放器处于活动状态时定期保存。在那些通常是MUD(多用户地下城)中的系统中,角色一直保存在内存中,直到将它们定期转储到文件中为止。

这意味着,如果用户在没有“露营”的情况下断开连接,他们通常会发现自己离开了几个房间,并且从上次保存开始便丢失了一堆战利品,XP等。在这方面,它的行为很像今天控制台RPG的播放方式(您必须在不关闭控制台的情况下保存游戏,否则自上次保存以来便失去了一切)。

该系统之所以能够达到预期的目的,是因为角色之间无法进行交互,除非它们可以通过“邮件”系统来相互发送消息和项目。丢失物品和进步的机会往往非常可观,但在大多数情况下一次只能影响一个角色。

世界保存功能的出现是因为角色最终能够直接彼此交互,因此所有角色都必须处于一致的状态,否则可能会发生重复和删除。在MUD场景中这不是问题,因为很难以导致项目或货币重复的方式滥用系统,但是在早期的MMO MUD中却非常容易做到。玩家A给玩家B一个项目,玩家B保存,玩家A断开而不保存。即时复制。

Worldsave 不是性能优势,而是旨在防止作弊。我记得在确实提前宣布worldsave事件的系统上玩过,并且经常在服务器更新其所有文件时挂了整个系统一分钟。虽然这可以防止作弊,但对于这些系统的用户来说并不是很方便。

这使我们进入了当前的状况。今天,我们不再使用worldsave类型的函数。我们使用数据库。这使我们可以确保尽可能减少重复和删除。这些字符作为记录存在于数据库中,并且玩家之间的每笔交易都是文字数据库交易;该操作已完全提交或将被回滚。

除非存在系统中的异常错误,否则您将获得保存单个角色文件的好处(快速保存时间)和worldsaves的好处(无作弊),而没有两者的缺点(失去重大进展和重复项)。

在设计现代MMO时,您需要在数据库中创建存储过程,并使用这些过程执行事务。例如,在两个参与者之间进行交易时,可能看起来像这样:

start transaction;
insert into inventory (playerid, itemid) values (111, 222);
delete from inventory where playerid=111 and itemid=444;
insert into inventory (playerid, itemid) values (333, 444);
delete from inventory where playerid=333 and itemid=222;
commit;

(注意:此SQL并不是以实用的方式编写的,仅是作为示例)。

这样,如果在提交之前发生崩溃,则系统将回滚到玩家111和玩家333仍具有原始项目的状态,而在提交之后交易完成。没有重复的机会,因为数据库会保证同时保存字符。

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.