【问题标题】:Storing A LOT of data in cache or large db queries on every page load在每次页面加载时将大量数据存储在缓存中或大型数据库查询中
【发布时间】:2012-08-25 17:25:13
【问题描述】:

我的网站对每个客户都有一个非常精细的权限系统,因此它的规模相当大。

为了限制数据库查询,我一直在用户会话开始时从 mysql 数据库加载位掩码,然后将其保存为会话数据,所以它看起来像这样。这使我可以为每个用户会话进行一次(尽管它是复杂的 JOIN 查询)查询,而无需创建巨大的会话文件。

"permissions" => array(
    "type 1" => 'bitfield'
    "type 2" => 'bitfield'
     "type 3" => array(
         entity id = 'bitfield'
         entity id = 'bitfield')
     "type 4" => array(
         entity id = 'bitfield'
         entity id = 'bitfield')
)

权限完全基于组,因此给定组中的每个人都会在他们的会话数据中复制此权限。

但是位掩码开始使用起来很痛苦,我希望转向使用 acl。然而,我一开始没有使用 acl 的原因是为了尽量减少数据库的使用..

所以.. 现在我将拥有一个完全由数据库/缓存驱动的 acl,没有任何位掩码。然而,在用户会话数据中存储大量权限似乎并不理想。 (你同意吗?)

我认为要走的路是使用平面文件缓存来存储组权限。最简单的方法是每组一个文件吗?当有 4,000 + 个组,每个组具有 4 种权限类型(2 种权限类型是全局的,具有 40 个左右的权限,2 种类型是本地权限,每个实体有 40 个左右的权限(每种类型可能有 3 或 4 个20 个权限!)。编辑:为清楚起见,这意味着每个组有 160 - 200 个权限条目

这似乎是一个相当大的缓存!每次页面加载时都使用大量数据库会更好吗?这种数据大小使位掩码变得容易得多,但它们只是不够灵活了。

由于文件由 2 个不同的服务器提供服务(会话粘连,因此将位域保存到会话数据不是问题),这使得这变得更加困难,因此任何缓存都必须在服务器之间同步。数据库位于通过专用网络连接的单独服务器上,据称是 1gig 连接。

可以提出任何解决方案吗?我认为具有这么多数据的快速访问缓存(例如 memcached)只会让我的内存使用量大增?我很想只使用大量数据库查询,但我认为这可能会给数据库服务器带来太大的压力。

相当大的问题,我希望它清楚。如果有任何需要澄清,请告诉我。任何解决方案将不胜感激!

克里斯

【问题讨论】:

  • 您可能想看看memcached。它有很多benefits over straight-up session
  • 感谢voithos,一个有用的链接!我考虑过 memcached,但认为内存使用量可能太大了。但正如有人在这个问题上所说,内存使用量可能没有我预期的那么大,所以也许我应该在测试环境中试一试。关于使用未充分利用的服务器作为内存缓存池的有趣点。我会尝试找到一些关于如何设置的指南!

标签: php mysql database caching


【解决方案1】:

我认为存储在会话中的具有约 40 个条目的数据结构不会特别庞大。所以说真的,这可能归结为设计方面的问题是如何以最佳性能将这些信息最好地放入应用程序中。

如果您开始遇到性能问题并且您的基础架构预算允许,我认为您可能会考虑将此解决方案迁移到更多可以在任意数量的服务器之间共享的面向服务的架构。我个人非常相信这种架构,因为它确实可以帮助您处理规模问题。

您可以将“权限”公开为可由该应用程序(或者您将来可能需要开发的其他应用程序)使用的服务。它可能看起来像这样:

  • 内存缓存层(memcached 或类似的),这是应用程序进行初始调用以根据组查找权限信息的地方。如果此处不存在数据,则下一层为请求提供服务
  • RESTful API。在第一次缓存未命中后,您对组的权限发出简单的 GET 请求。这将需要调用数据库层来获取信息。它还会做一些事情,例如在缓存未命中时填充缓存,在客户端发布一些新权限数据或 PUT 更新到现有权限集的情况下使缓存无效和重新填充。
    • 仅由 RESTful 服务访问的数据库层。如果您有更复杂的非关系数据结构,也许 MySQL 可能是一种 NoSQL 技术。

对于您的服务,您可能有一个非常小的数据库服务器(因为一旦填充了缓存,就应该不经常查询数据库本身)。一个内存缓存服务器,它有足够的内存来满足您的存储需求(或者如果需要冗余,可能是一个小型服务器集群),以及一个相对较小的服务器来处理 REST API(一旦开发了缓存,这也应该不经常访问。好消息是它们有几个 memcached 或类似的服务,你可以相对便宜地使用它们(比如 Amazon Elasticache)。实际上,内存缓存会首当其冲来自应用程序服务器的流量,所以你不需要扩展随着您的流量增长,数据库服务器的 REST 服务器完全可以使用。

希望这对您的思考过程有所帮助。

【讨论】:

  • 这听起来确实是一个很好的解决方案,而且绝对是我未来的目标。但是目前我不确定它是否经济(尽管我必须进一步研究成本)。如果我开发一个临时解决方案,我肯定会记住它的结构 - 以期将来将其移植到类似的东西上。我以一种令人困惑的方式解释了这些条目,实际上每组更像是 160-200 个条目。您会说使用用户会话效率低下的最大条目数是多少?我以为这么多大型嵌套数组会很慢。
  • @ChrisB 现实情况是,无论您是从服务、平面文件还是其他任何地方提取数据,它最终都会驻留在应用程序的内存中(在会话中或在您的用户权限对象中,或者任何)。而且,您的应用程序使用的内存越多,您的服务器可以根据其特定规格有效地服务的请求就越少。您可以简单地将数据库存储用于您的情况下的权限,只要您利用查询缓存,您应该能够获得良好的性能。
  • 我决定使用这种设计,使用 memcached 或 CouchBase 来支持我的内存缓存。我没有意识到设置内存缓存“云”是多么容易。查看服务器统计数据,我可以轻松地从我当前的每台服务器中使用至少 200mb 的 RAM,而不会损害任何应用程序的性能。使用 3 台服务器,这将为我提供 600mb 的 RAM 用于缓存,如果仅用于权限,这应该足够了。如果不是,我可能很快就可以使用另一个网络服务器,这可能会给我大约 1gb RAM 用于缓存!
  • @ChrisB 很高兴您能够提出合适的解决方案。 Memcached 是伟大的,就像你说的非常好用。在过去几年的工作中,我基本上经历了将我们所有的 Web 服务转换为我所描述的基于云 (AWS) 的面向服务架构的过程,我发现处理扩展问题要容易得多,以及集成新的应用程序功能/组件,因为您可以利用现有服务。
  • 另外值得注意的是,研究此解决方案的实现使我使我一直在研究的 ACL 更加高效。通过一些工作,我认为我可以将内存缓存要求降低到 400MB 以下(从大约 700MB),即使出现峰值,也可以使 600MB 到 1GB 足够。
猜你喜欢
  • 2011-07-25
  • 2020-11-13
  • 2015-08-27
  • 2015-01-29
  • 1970-01-01
  • 2019-01-17
  • 2015-01-21
  • 1970-01-01
相关资源
最近更新 更多