一般从 MongoDB 中缓存存储的文档
Caching stored documents from MongoDB generically
我正在尝试优化游戏服务器以用于学习目的。我将 MongoDB 用作后端数据存储及其 Java 驱动程序。我在数据库中存储玩家数据(级别、名称、当前任务)、任务数据和一系列其他游戏数据。每个文档类型都有自己的 class 类型和适当的字段(例如 User.class
保存来自 users
collection 的文档,Quest.class
保存来自 quests
collection,等等
现在,当玩家执行操作时,我使用玩家的用户名从 users
collection 中查找文档并相应地更新它。这是非常昂贵的,因为这意味着每次用户执行操作时,都需要进行数据库查询以获取当前玩家的数据。
当然,我的下一个想法是在他们连接到服务器时加载玩家的用户文档并单独存储,然后在他们断开连接时将其删除并将更新的数据从内存保存到 MongoDB。
问题是我也想对所有其他 collection 做类似的事情,这是唯一可预见的方法(因为每个缓存都有不同的键来查找数据,通常是字符串和UUID) 类似于以下内容:
// Create a bunch of separate caches (faster than Guava Table, but ugly)
// For example, after finding a user: userCache.put("TheirUsername", user);
private HashMap<String, User> userCache = new HashMap<>();
private HashMap<UUID, Group> groupCache = new HashMap<>();
private HashMap<Integer, Quest> questCache = new HashMap<>();
// Or use a Guava Table to store all (this is slower than individual maps)
// For example, after finding a user: cache.put(User.class, "TheirUsername", user);
private Table<Class, Object, Object> cache = HashBasedTable.create();
除了拥有大量地图并将查找结果存储在这些地图中(每个缓存一个 collection)之外,是否有任何替代方法?
我很想以某种方式抽象它而不导致性能损失。我曾尝试使用 Guava 来实现 Table<Class, Object, Object>
,以便缓存本质上是动态的,让我缓存任何 class。问题是 Tables 慢很多,特别是如果每秒有数百次查找...
我不确定如何在不影响我的代码的简洁性的情况下尽可能优化 performance-wise。 Table 本质上是我喜欢做的,因为它用途广泛,但速度不够快。
基本上,您可以只使用一张从一个对象到另一个对象的映射。如果你的键都有正确的 equals() 方法(所有基本运行时 类 都有)你应该没有任何问题。
因此,您问题的基本答案是:
HashMap<Object, Object> megaCache = new HashMap<>();
megaCache.put("someUser", someUserObject);
...
User cachedUser = (User) megaCache.get("someUser");
但是,我强烈建议不要这样做!
你失去了泛型的所有美感和类型安全,并加载了一张包含各种东西的地图。 (通常,这不是运行时的主要问题,但不相关的键类型之间发生散列冲突的可能性会增加。)
宁愿像原来的 post 那样使用单个缓存,并且类型安全且清晰。
我正在尝试优化游戏服务器以用于学习目的。我将 MongoDB 用作后端数据存储及其 Java 驱动程序。我在数据库中存储玩家数据(级别、名称、当前任务)、任务数据和一系列其他游戏数据。每个文档类型都有自己的 class 类型和适当的字段(例如 User.class
保存来自 users
collection 的文档,Quest.class
保存来自 quests
collection,等等
现在,当玩家执行操作时,我使用玩家的用户名从 users
collection 中查找文档并相应地更新它。这是非常昂贵的,因为这意味着每次用户执行操作时,都需要进行数据库查询以获取当前玩家的数据。
当然,我的下一个想法是在他们连接到服务器时加载玩家的用户文档并单独存储,然后在他们断开连接时将其删除并将更新的数据从内存保存到 MongoDB。
问题是我也想对所有其他 collection 做类似的事情,这是唯一可预见的方法(因为每个缓存都有不同的键来查找数据,通常是字符串和UUID) 类似于以下内容:
// Create a bunch of separate caches (faster than Guava Table, but ugly)
// For example, after finding a user: userCache.put("TheirUsername", user);
private HashMap<String, User> userCache = new HashMap<>();
private HashMap<UUID, Group> groupCache = new HashMap<>();
private HashMap<Integer, Quest> questCache = new HashMap<>();
// Or use a Guava Table to store all (this is slower than individual maps)
// For example, after finding a user: cache.put(User.class, "TheirUsername", user);
private Table<Class, Object, Object> cache = HashBasedTable.create();
除了拥有大量地图并将查找结果存储在这些地图中(每个缓存一个 collection)之外,是否有任何替代方法?
我很想以某种方式抽象它而不导致性能损失。我曾尝试使用 Guava 来实现 Table<Class, Object, Object>
,以便缓存本质上是动态的,让我缓存任何 class。问题是 Tables 慢很多,特别是如果每秒有数百次查找...
我不确定如何在不影响我的代码的简洁性的情况下尽可能优化 performance-wise。 Table 本质上是我喜欢做的,因为它用途广泛,但速度不够快。
基本上,您可以只使用一张从一个对象到另一个对象的映射。如果你的键都有正确的 equals() 方法(所有基本运行时 类 都有)你应该没有任何问题。
因此,您问题的基本答案是:
HashMap<Object, Object> megaCache = new HashMap<>();
megaCache.put("someUser", someUserObject);
...
User cachedUser = (User) megaCache.get("someUser");
但是,我强烈建议不要这样做!
你失去了泛型的所有美感和类型安全,并加载了一张包含各种东西的地图。 (通常,这不是运行时的主要问题,但不相关的键类型之间发生散列冲突的可能性会增加。)
宁愿像原来的 post 那样使用单个缓存,并且类型安全且清晰。