Skip to main content

游戏对外服缓存

tip

本篇内容是游戏对外服相关的扩展。

本篇文档不是必读内容,但介绍了一种性能提升的技巧,建议在时间充裕时阅读。

介绍

我们对业务数据做缓存时,一般的做法是通过 Caffeinecache2kehcacheJetCache 等专业的缓存库,将业务数据缓存在游戏逻辑服中,以实现对业务数据的缓存。

而游戏对外服缓存,可以将一些热点的业务数据缓存在游戏对外服中。 当玩家每次访问相关路由时,会直接从游戏对外服内存中取数据。 这样既能避免反复请求游戏逻辑服,又能减少序列化(编码)业务数据,从而做到性能的超级提升。

当我们把游戏对外服缓存与专业的缓存库做结合时,可以发挥更大的性能效果。 因为我们可以将热点数据缓存在游戏对外服中,之后其他玩家访问热点数据时, 就不需要去游戏逻辑服中取数据,而是直接在游戏对外服这一环节中就能得到数据了。


游戏对外服缓存对性能有着巨大的提升,主要体现在几个方面

  1. 当玩家访问缓存数据时,响应更快了,因为请求链更少了。
  2. 直接在游戏对外服中取数据,无需将请求传递到游戏逻辑服中,无需对业务数据做序列化操作。
  3. 避免请求传递到游戏逻辑服中,节省系统资源。

特点

  1. 零学习成本
  2. 可快速响应玩家请求。
  3. 简化了缓存的使用,即使没有在游戏逻辑服中对这些业务数据做缓存, 只要在游戏对外服配置好相关的路由缓存,就能达到缓存的效果。
  4. 减少请求传递,同时游戏对外服缓存还可以减少请求的传递, 使得业务数据在游戏对外服就能处理,而不需要经过游戏逻辑服。
  5. 避免序列化操作,由于路由对应的业务数据是以 byte[] 类型缓存在游戏对外服的, 所以从缓存中取得的业务数据,将不再需要序列化(编码)操作了。 简单点说,就是不需要将业务对象转换成 byte[] 类型了。
  6. 支持条件缓存,同一 action 支持不同的请求参数。
  7. 支持路由范围缓存配置

对比各解决方案

为了让开发者更好的理解游戏对外服缓存的优势,这里先引入两个开发者常用的第三方解决方案来做对比。


与 Hazelcast、Redis 等第三方解决方案相比较

  • Redis 有一些额外的开销,比如序列化和反序列化数据、对数据进行压缩和解压缩、网络IO、网络波动等方面。 使用游戏对外服缓存特性可以有效避免这些问题,并且性能是 Redis 的数百倍
  • Hazelcast 也有一些额外的开销,每个节点占用的内存几乎相同, 无论这些内存数据是否对你有用,都会强行占用你的内存。 如果其中一个节点占用了 1G 内存,那么其他节点也将占用 1G 内存。 每次数据发生变动时,都需要经过N个节点的序列化、N个节点的网络IO等操作。 对于不熟悉 Hazelcast 的开发者来说,安装、配置和调试 Hazelcast 集群可能会比较复杂,需要花费一定的时间和精力。

使用 Hazelcast、Redis 等第三方解决方案,缺点

  • 第三方解决方案需要你进行额外的安装(安装成本、机器资源占用成本)。
  • 在项目中引入第三方后,需要学习相关 API 的使用(学习成本)。
  • 需要你进行很多额外的工作,例如数据的存储、更新等(使用成本、维护成本)。

对比小结

最重要的是,开发者使用游戏对外服缓存时,是无感知的(零学习成本)。

游戏对外服缓存HazelcastRedis描述
高性能两者比 Redis 快数百倍
零安装成本
零学习成本
零使用成本
零维护成本
内存占用按需增加节点均等内存加载所有
序列化次数00N每次访问缓存时
网络 io 次数00N每次访问缓存时

使用场景

使用场景举例

  • 如一些配置数据信息 : 装备的配置、道具的配置... 等。
  • 排行榜,如果及时性要求不高的,比如能接受 1、5、10、N 分钟同步一次的这种延迟排行榜,且数据量不多的(百来条或几百条)。
  • 更多举例后续补充...

游戏对外服缓存的适用场景

  • 热点数据
  • 请求较为频繁的,数据不常变动的。
tip

你可以将游戏对外服看成一台另类的 "Nginx、OpenResty" 等服务器, 可为整体架构做一些前置抵挡、功能扩展等职责。

游戏对外服缓存并不是用于取代 Hazelcast、Redis 之类的,只是在某些业务场景下会具备更大的优势。

缓存处理流程图

external_cache

缓存处理流程图说明

  • Player : 玩家。
  • ExternalServer : 游戏对外服。
  • request : 玩家发送请求。
  • response : 游戏对外服的响应数据。
  • cacheData : 缓存数据。检测到该请求有对应的缓存,将缓存结果发送给玩家,否则到游戏逻辑服中获取。

如何使用

游戏对外服缓存的使用与路由访问权限控制类似, 如果你之前了解过这部分的内容,那么花几分钟就能上手了。

  • code 2,框架内置的缓存类
  • code 3,添加全局配置中
  • code 4,配置缓存 3-1
void extractedExternalCache() {
DefaultExternalCmdCache externalCmdCache = new DefaultExternalCmdCache();
ExternalGlobalConfig.externalCmdCache = externalCmdCache;
externalCmdCache.addCmd(3, 1);
}

当玩家请求 3-1 时,如果在游戏对外服中找到了缓存数据,就直接在游戏对外服环节将数据响应给玩家。

如果没有找到缓存数据,请求将被传递到游戏逻辑服,由游戏逻辑服的操作进行处理。 在操作完成后,游戏逻辑服将返回结果给游戏对外服,并将该结果保存到缓存中。 下次其他玩家请求 3-1 时,就可以从缓存中获取结果,从而实现快速响应。

更多配置

CmdCacheOption

CmdCacheOption 是游戏对外服的缓存配置对象,缓存配置对象可以让我们在游戏对外服缓存上做更精细的控制。


代码说明

  • code 3,缓存过期时间 1 小时。
  • code 4,缓存过期检测时间间隔 5 分钟。
  • code 5, 同一个 action 的缓存数量上限设置为 256 条。
  • code 6,构建缓存配置项。
CmdCacheOption createCmdCacheOption() {
return CmdCacheOption.newBuilder()
.setExpireTime(Duration.ofHours(1))
.setExpireCheckTime(Duration.ofMinutes(5))
.setCacheLimit(256)
.build();
}
tip

即使不设置,框架默认也是这个配置,这里只是展示如何创建的缓存配置选项。

配置不同的 CmdCacheOption

  • code 7,设置默认的缓存配置项,之后添加的路由缓存都将使用这个缓存配置。
  • code 9,添加路由缓存 22-1,将使用默认的缓存配置。
  • code 11 ~ 17,创建一个新的缓存配置对象,并设置到 22-2 、22-3 的路由中。 (不会使用默认的配置,而是使用 optionCustom 这个缓存配置对象。)
...
void extractedExternalCache() {
DefaultExternalCmdCache externalCmdCache = new DefaultExternalCmdCache();
ExternalGlobalConfig.externalCmdCache = externalCmdCache;

CmdCacheOption defaultOption = createCmdCacheOption()
externalCmdCache.setCmdCacheOption(defaultOption);

externalCmdCache.addCmd(22, 1);

CmdCacheOption optionCustom = CmdCacheOption.newBuilder()
.setExpireTime(Duration.ofSeconds(30))
.setExpireCheckTime(Duration.ofSeconds(5))
.build();

externalCmdCache.addCmd(22, 2, optionCustom);
externalCmdCache.addCmd(22, 3, optionCustom);
}

路由范围缓存配置

这里,我们添加了主路由为 2 的值,游戏对外服会对主路由为 2 下所有子路由的数据进行缓存。 通过路由范围缓存,我们可以避免为每个路由做单独的配置。

举个例子,对于 2-1、2-2、2-N 等子路由,即使你没有为这些子路由配置相关的缓存,缓存仍然会生效。 子路由使用的缓存配置与主路由使用的缓存配置相同。

void extractedExternalCache() {
DefaultExternalCmdCache externalCmdCache = ...
externalCmdCache.addCmd(2);
}

Example Source Code

see https://github.com/iohao/ioGameExamples

path : SimpleExample/example/example-external-cache

  • CacheApplication
  • WsClient

之后在模拟客户端的控制台中分别输入 22-1、22-2、22-3 来观察效果。