准备扩展的最佳数据库结构实践

6

我知道这是一个非常泛化和主观的问题,如果它不符合StackOverflow的礼仪,请随意投票关闭它。但对我来说,值得一试 ;)

直到现在,我从未构建过高流量应用程序,因此我不了解(除了一些网上的阅读材料)有关扩展实践的信息。

如何设计一个数据库,在需要扩展时,我不必重构数据库结构或应用程序代码?

我知道开发(和优化)应该一步一步进行,当瓶颈出现时优化,而且在不知道将有多少用户以及他们如何使用数据库(例如读写比率)时,几乎不可能设计完美的结构,我只是在寻找一个好的起点。

制作一个准备好进行分区分片扩展的最佳实践是什么,而必须绝对避免哪些黑客技巧

编辑一些关于我的应用程序的详细信息:

  1. 应用程序将作为多站点行为运行
  2. 我将为每个应用程序版本(db_0_0_1、db_0_0_2等)拥有一个数据库*
  3. 每个“站点”将在数据库中拥有一个模式*和一个可以访问自己模式的角色
  4. 应用程序代码将主要是PHP和一些Python(守护进程和维护任务)
  5. Web服务器可能是Nginx和lighttpd或node.js作为长轮询任务的支持(例如聊天)
  6. 缓存将使用memcached进行(加上apc用于与php代码严格相关的事情,因为它可以在php外部使用)

我赞赏你提前考虑设计,而不是盲目地跳进去,希望一切顺利。然而,我能给你的最好建议是:当你第一次认为需要分片或分区时,请不要这样做!真正地查看你的数据库利用模式,你可能会发现这是对数据库的滥用,而不是需要“扩展”。太多次了,我见过人们试图通过分片来扩展糟糕的代码。这来自于“将硬件投入问题”的想法。现在他们有更多的硬件要维护,一个共享基础设施,而剩下的代码仍然很糟糕。 - Matthew Wood
@MatthewWood 我已经用“最好的祝愿”完成了一个项目构建,本来它应该是一个“个人”项目,但后来发展成了小型中型..数据库(和代码)难以维护;)我不想再犯同样的错误;)我同意你的观点,大多数优化应该首先在代码和硬件扩展方面尝试。 - Strae
1个回答

3
这个问题非常通用,但以下是一些提示:
  • 不要在应用程序代码中使用任何会话变量(pg_backend_pid()、inet_client_addr())或会话控制(SET ROLE、SET SESSION)。

  • 不要在应用程序代码中使用显式事务控制(BEGIN/COMMIT/SET TRANSACTION)。所有这些逻辑都应该包装在UDFs中。这样可以实现无状态的语句模式池化,从而实现最快的DB池化。(请参阅pgbouncer文档pg wiki了解更多信息)

  • 将所有App<->Db通信封装在定义良好的UDF DB API中 - 这将让您使用PL/Proxy。如果对于所有SELECT来说这样做太难了,那么至少对于所有数据写入(INSERT/UPDATE/DELETE),您需要这样做。例如:INSERT INTO users(name) VALUES('Joe')需要SELECT create_user('Joe').

  • 检查您的DB模式-是否容易将所有属于给定用户的数据分离?(最有可能这将是分区键)。剩下的都是共享数据,需要复制到所有节点。

  • 在需要缓存之前考虑缓存。缓存密钥是什么?缓存超时是多少?您会使用Memcached吗?


我在我的问题中增加了一些关于我的应用程序的细节 - 您能否更详细地解释一下事务控制,以及为什么不应该在我的应用程序代码中使用它? - Strae
我已经更新了我的答案,但我觉得自己并不是这个主题的真正专家,所以我们必须等待有人提出更好的提示:0)也许是[depesz](http://www.depesz.com/index.php/2011/12/02/the-secret-ingredient-in-the-webscale-sauce/ "Pg sharding的优秀文章")? - filiprem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接