ruby-on-rails - 使用数据结构的gem在Rails中进行Postgresql复制

标签 ruby-on-rails postgresql replication

我目前正在使用Ruby on Rails设置主从应用程序。我打算使用数据结构或 Octopus gem 来处理读/写连接。

这是我第一次设置主从数据库。我对可用于实现PostgreSQL复制的各种开源工具感到困惑,例如pgpool II,pgcluster,Bucardo和热备/流复制(在PostgreSQL 9.1中内置功能)

我的要求是

  • 容错(高可用性,并且在故障转移时没有数据丢失)
  • 负载均衡

  • 提前致谢

    注意:我已经阅读了有关postgresql复制的stackoverflow帖子,但是它们已经很老了,不能帮助我确定应该使用哪种工具。

    最佳答案

    就您而言,流复制是开始的地方。它不是很灵活,但是只要您不需要在主要版本之间进行复制,它就可以满足您对数据库读取的需求。

    数据库复制101

    数据库复制是一种确保保存到特定服务器的数据存储在许多其他服务器中的方法。通常这样做是为了更好地利用有限的网络连接,确保容错能力(因此本质上是热备份),确保只读查询可以分布在大量数据库中,等等。这一切都必须完成不牺牲ACID的基本保证。

    有许多不同的重叠方法可以对复制解决方案进行分类。这些包括:

  • 页面或文件级vs行级vs语句级
  • 同步与异步
  • 主从vs多主

  • 一般而言,复制和解决方案之间的权衡需要对数据库机制和ACID保证有相对深入的了解。我将假设您相对熟悉存储机制,以及确定性操作与非确定性操作等。

    正在复制什么?文件更改(物理)vs行更改(逻辑)vs语句

    最简单的方法是将块更改复制到文件,例如存储在PostgreSQL中的预写日志中的文件。这将在页面级别复制更改,并且需要相同的文件格式。这意味着您不能跨主要版本,CPU体系结构或操作系统进行复制。例如,任何可能影响元组对齐的操作都将导致复制失败,或者更糟糕的是,损坏从属数据库。这是流复制使用的方法。设置很简单,并且始终复制数据库集群中的所有内容。

    另外,这种方法意味着您可以轻松地保证主数据库和从属数据库在文件级别上都是相同的。由于PostgreSQL WAL是群集全局的,因此这种方法不太可能复制整个数据库群集以外的任何内容。

    为了说明其工作原理,假设我:
    UPDATE my_table SET rand_value = random() WHERE id > 10000;
    

    在这种情况下,这将更改一堆数据页,并且文件操作将复制到副本。主文件和从文件之间的文件保持相同。

    Slony,Bucardo和其他人采用的另一种方法是以逻辑方式复制行。在这种方法中,将标记并记录已更改的行,并将更改发送到副本。副本从主数据库重新运行行操作。由于这些工具不是复制文件操作而是逻辑数据库操作的附加工具,因此它们可以跨CPU架构,操作系统等进行复制。通常,它们的设计目的还在于您可以复制数据库中的某些但不是全部表,允许很大的灵活性。另一方面,这会导致很多潜在的错误。 “糟糕,该表未复制”是一个实际的问题。

    在这种情况下,当我运行上面的update语句时,将触发一个触发器,以捕获插入和删除的实际行,并对这些行进行记录,复制和重新运行。因为这是在运行rand()之后发生的,所以数据库在逻辑上是一致的,但在物理上却不一定相同。

    最后一种方法是语句复制。在这种情况下,我们将复制语句,然后在副本数据库上重新运行这些语句。 PgPool的某些配置将执行此操作。在这种情况下,如果运行任何不确定性函数,则不能确保数据库在逻辑上等同于其副本。在上面的语句中,该语句本身将在每个副本上运行,以确保相关列中的伪随机数不同。

    同步与异步

    了解故障转移保证时,这一区别很重要。在异步复制系统中,更新会排队并在可能的情况下转移到副本中,然后在副本中重新运行。在同步复制系统中,接受写入的数据库将不会返回成功的提交,直到至少一定数量的副本数据库报告成功的提交为止。

    异步复制通常比同步复制更健壮,并产生更好的可用性。这是因为同步复制会引入其他故障点。如果您有一个主机和一个从机,则如果两个系统都发生故障,则数据库至少对于写操作不可用。

    但是,要权衡的是,同步复制提供了一个保证,即如果主服务器在提交后立即遭受灾难性的硬件故障,则提交的数据实际上可以在副本上使用。这是一个极低概率的事件,但是在某些情况下,重要的是要知道数据仍然可用。简而言之,这提供了异步复制中不存在的其他持久性保证。

    多主站vs主从站

    大多数复制系统是主从系统。在这种情况下,所有写入均始于一个节点,然后复制到其他节点。写操作只能在一个节点上开始。它们可能不会从其他节点开始。这使复制变得简单明了,因为我们知道从服务器代表主服务器的过去状态。

    多主复制允许写入发生在多个节点上。在异步复制系统中,这导致解决冲突的问题。这些问题实际上比大多数您添加DDL语句时所假定的问题要严重。假设两个不同的用户在两个不同的主服务器上运行上述update语句。现在,我们将具有一组必须在其间复制的记录,但是它们会发生冲突。

    多原版复制通常要求人们仔细考虑此冲突解决过程。这绝不是开箱即用的过程。通常,您编写自己的冲突解决例程。因此,除非您确实需要,否则我通常建议避免多主复制。

    关于ruby-on-rails - 使用数据结构的gem在Rails中进行Postgresql复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9566376/

    相关文章:

    ruby-on-rails - 在 Rails 3 中运行后台作业

    postgresql - 嵌套对象上的 Postgres jsonb 查询

    ruby-on-rails - 在开发环境中通过 Octopus gem 复制 Rails Postgresql

    replication - Citus 分片、复制和复制

    ruby-on-rails - 为什么 Rails 不会在运行之间重置测试数据库

    android - 如何在共享同一数据库的两个 Rails 应用程序中使用 rpush?

    ruby-on-rails - 发送电子邮件时 Heroku 超时

    sql - 函数调用的属性表示法给出错误

    ruby-on-rails - "pg"Ruby gem 从 Resque 抛出 "prepared statement already exists"错误

    svn - 如何使用 Subversion 获得 master-master 复制?