2

我正在编写一个服务器应用程序,它必须每秒执行大量由连接的客户端触发的 MySQL 查询,我想知道除了良好的结构化数据库之外,提高性能的最佳方法是什么。

我的想法是缓存一些数据并只发送缓存的数据而不是执行新的查询。就像数据库有不同的表一样,缓存必须处理这些不同的“结构”(对象)。由于连接到服务器的客户端能够间接更改数据,因此我必须能够编辑缓存的数据(并且在某些时候能够更新我的数据库,但这应该不会太难)。这是我需要做的简短列表:

  • 编辑缓存的数据/对象
  • 删除旧数据/对象并添加新数据/对象
  • 按某种优先级排序数据(最后使用)
  • 通过某种 id 识别数据

我认为向量或队列/priority_queue 都是一个好主意。这样,我可以为我想要缓存的每个表/对象创建一个队列或向量(没有执行任何测试,因为我想在浪费时间之前获得更多意见)。存储在这些缓存结构中的最大对象大约为 1 KB(很可能更小),最小的可能为 96 字节。

每个缓存结构我不必存储超过 50.000 个对象,我认为我可以使用 10 种不同的结构(每个人都使用不同的对象类型)。

最重要的部分是速度,否则我只能执行查询。这不仅是我必须进行查询,而且之后还要创建一个新对象,而不是仅仅重用或重新发送旧对象。

所以这是我的问题:

  • 根据提供的信息缓存数据/对象的最佳方法是什么?为什么?

编辑:哦,当我指的是结构时,我不是指结构,我只是不知道我应该如何引用向量队列映射等,同时容器可能会更好:)。

4

1 回答 1

1

有很多事情需要考虑,但总的来说,我会在您的情况下将关系映射基于行数据网关模式 (RDG)。如果您没有太多不同的对象类型,那么这种架构方法应该可以很好地扩展。如果您将缓存簿记约束到 Finder 类,RDG 应该有助于您的缓存实现。

如果您有时间并且愿意,请查看Martin Fowler 的企业应用程序架构模式。这是一个很好的信息。

现在到具体...

  • 通过某种 id 识别数据

通常,您会为此在数据库中使用一些自动递增的整数列。您可以使用 unordered_map 快速从缓存中提取这些对象。由于您的缓存中有所有对象,为了优化,您还可以实现一些find*函数来首先搜索缓存。您可以使用 unordered_map/unordered_multimap 来“索引”一些数据,如果您的搜索时间受到高度限制,或者只是坚持使用良好的旧地图/多地图。但是,这会使工作加倍,并且您已经在数据库中免费获得了这些类型的查询。

  • 编辑缓存的数据/对象

在您实际将脏数据写入数据库之前,系统的其余部分不应该看到脏数据。启动更新后,如果一切按预期进行,您可以将缓存中的对象替换为您用于更新的对象,或者简单地删除缓存中的对象并让其他读者从数据库中获取它(这将导致再次缓存对象)。您可以通过克隆原始网关对象来实现这一点,但底线是您应该实现一些锁定策略。

  • 删除旧数据/对象并添加新数据/对象

在这里,您只需从缓存中删除对象,然后尝试从数据库中删除。如果在数据库中删除失败,其他读者将缓存它。只要确保您在删除过程中没有客户端可以访问相同的记录。添加新记录时,您只需实例化网关对象,将其传递给域级别对象,完成更改后,在网关对象上调用 insert。您可以将新的 Gateway 对象放入缓存中,也可以让第一个读者将其放入缓存中。

  • 按某种优先级排序数据(最后使用)
  • 根据提供的信息缓存数据/对象的最佳方法是什么?为什么?

这是选择最佳缓存算法的问题。这不是一个容易回答的问题,但 LRU 应该可以正常工作。没有实际的指标,就没有正确的答案,但是 LRU 很容易实现,如果它不符合您的要求,只需执行指标并决定新算法。确保您可以通过良好的缓存接口无缝地做到这一点。要记住的另一件事是您的域级别对象永远不应该依赖于缓存的限制。如果您需要 100k 个对象,但只有 50k 个缓存,那么您仍然在内存中拥有所有 100k 个对象,但其中有 50k 个对象在缓存中。换句话说,你的对象不应该依赖于你的缓存状态,也不应该关心你是否有缓存。

接下来,如果您仍然坚持使用 RDG 的想法,那么您只是在缓存中缓存网关对象。您可以通过 shared_ptr 将网关对象的实例保存在缓存中,但如果您想避免脏写,还应该考虑锁定策略(乐观与悲观)。此外,您的所有网关(每个表一个)都可以继承相同的接口,因此您可以概括您的保存/加载策略,并且您可以在保持简单的同时使用单个池。(查看 boost::pool。也许它可以帮助您实现缓存。)

最后一点:

蛋糕是一个谎言!:D 无论您决定做什么,请确保它基于大量的性能指标。如果您将性能提高了 20%,并且您花了 2 个月的时间来做这件事,那么考虑在您的硬件上增加几 GB 的 RAM 可能是值得的。做一些简单的可验证的概念证明,这将为您提供足够的信息,是否实现您的缓存支付,如果没有,请尝试一些经过测试且可靠的现成解决方案(memcached 等,正如@Layne 已经评论的那样)。

于 2012-09-24T01:20:25.763 回答