我目前正在使用Ruby on Rails建立一个主从应用程序。我打算使用data-fabric或octopus gem来处理读/写连接。
这是我第一次设置主从DB。我对可用于实现postgresql复制的各种开源工具感到困惑,例如pgpool II,pgcluster,Bucardo和Hot Standby / Streaming Replication(postgresql 9.1内置功能)
我的要求是
提前致谢
注意:我已经浏览了关于postgresql复制的stackoverflow帖子,但它们已经很老了,并没有帮助我得出哪个工具应该用。
答案 0 :(得分:5)
在您的情况下,流式复制是开始的地方。它不是很灵活,但只要您不需要在主要版本之间复制,它就能满足您对数据库读取的需求。
数据库复制101
数据库复制是一种确保保存到特定服务器的数据存储在许多其他服务器中的方法。这通常是为了更好地利用更有限的网络连接,确保容错(因此基本上存在热备份),确保只读查询可以分布在更多数据库等等。这一切都必须完成在不牺牲ACID的基本保障的情况下。
有许多不同的重叠方法可以对复制解决方案进行分类。其中包括:
页面或文件级vs行级vs语句级
同步与异步
Master-slave vs Multi-Master
一般而言,理解复制和解决方案之间的权衡需要对数据库机制和ACID保证有相对较强的理解。我将假设您对存储机制,确定性与非确定性操作等相对熟悉。
什么是复制?文件更改(物理)与行更改(逻辑)与语句
最简单的方法是将块更改复制到文件中,例如存储在PostgreSQL中的预写日志中。这会复制页面级别的更改,并且需要相同的文件格式。这意味着您无法跨主要版本,CPU架构或操作系统进行复制。例如,任何可能影响元组对齐的东西都会导致复制失败,或者更糟糕的是,破坏了从属数据库。这是流复制使用的方法。设置很简单,它总是复制数据库集群中的所有内容。
此外,这种方法意味着您可以轻松保证主数据库和从属数据库在文件级别下完全相同。由于PostgreSQL WAL是集群全局的,因此这种方法不可能复制整个数据库集群之外的任何东西。
作为对其工作原理的描述,假设我:
UPDATE my_table SET rand_value = random() WHERE id > 10000;
在这种情况下,这会更改一堆数据页,并将文件操作复制到副本。主文件和从文件之间的文件保持一致。
Slony,Bucardo和其他人采用的另一种方法是以逻辑方式复制行。在此方法中,标记并记录已更改的行,并将更改发送到副本。副本从master数据库重新运行行操作。因为这些是不复制文件操作而是复制逻辑数据库操作的附加工具,所以它们可以跨CPU架构,操作系统等进行复制。此外,它们通常设计为可以复制数据库中的一些但不是所有表,允许很大的灵活性。另一方面,这会导致很多错误。 "糟糕,该表未被复制"是一个真正的问题。
在这种情况下,当我运行上面的更新语句时,将触发一个触发器,捕获插入和删除的实际行,并记录,复制和重新运行行操作。因为这是在运行rand()之后发生的,所以数据库在逻辑上,但不一定在物理上相同。
最后一种方法是语句复制。在这种情况下,我们复制语句并重新运行副本上的语句。 PgPool的一些配置会这样做。在这种情况下,如果运行任何非确定性函数,则无法确保数据库在逻辑上等效于其副本。在上面的语句中,语句本身将在每个副本上运行,确保相关列中的不同的伪随机数。
同步与异步
这一区别对于了解故障转移保证非常重要。在异步复制系统中,更新会排队并在可能的情况下传输到副本并在那里重新运行。在同步复制系统中,接受write 的数据库将不会返回成功提交,直到至少一定数量的副本数据库报告成功提交。
异步复制通常比同步复制更强大并且产生更好的可用性。这是因为同步复制会引入其他故障点。如果您有一个主服务器和一个服务器,那么如果 系统发生故障,那么您的数据库至少在写操作时将变得不可用。
然而,权衡是同步复制提供了保证,如果主设备在提交后立即遭受灾难性硬件故障,则提交的数据实际上可用于副本。这是一个非常低概率的事件,但在某些情况下,重要的是您知道数据仍然可用。简而言之,这提供了异步复制中不存在的额外持久性保证。
多主与主从
大多数复制系统都是主从系统。在这种情况下,所有写入都从一个节点开始,并复制到其他节点。写入可能只在一个节点开始。它们可能不会从其他节点开始。这使得复制变得直截了当,因为我们知道从属代表了主服务器的过去状态。
多主复制允许对多个节点进行写入。在异步复制系统中,这会导致冲突解决问题。添加DDL语句时,这些问题实际上比大多数人都假设的要糟糕。假设两个不同的用户在两个不同的主服务器上运行上述更新语句。我们现在将拥有一组必须复制的记录,但它们会发生冲突。
多主复制通常要求人们仔细考虑此冲突解决过程。它永远不是一个开箱即用的过程。通常,您可以编写自己的冲突解决例程。出于这个原因,我通常建议避免多主复制,除非你真的需要它。