【问题标题】:MySQL dual masterMySQL 双主
【发布时间】:2010-10-22 15:56:58
【问题描述】:

对于我当前的项目,我们正在考虑为地理上分离的设置设置双主复制拓扑;一个分贝在美国东海岸,另一个分贝在日本。 我很好奇是否有人尝试过这个以及有什么经验。

另外,我很好奇解决这个问题的其他选择;我们正在考虑消息队列。

谢谢!

【问题讨论】:

    标签: mysql replication


    【解决方案1】:

    只是关于你计划的技术方面的说明:你必须知道 MySQL does not officially support 多主复制(只有 MySQL Cluster 提供同步复制的支持)。

    但是,即使使用正常的 MySQL 复制设置,至少有一个“hack”可以使多主复制成为可能。请参阅 Patrick Galbraith 的"MySQL Multi-Master Replication" 以获得可能的解决方案。我对这种设置没有任何经验,所以我不敢判断这种方法的可行性。

    【讨论】:

      【解决方案2】:

      在地理上复制数据库时需要考虑几件事情。如果您出于性能原因这样做,请确保您的复制模型支持您的数据“最终一致”,因为在两个或多个位置使复制成为最新可能需要时间。如果您的吞吐量或位置之间的响应时间不佳,则主动复制可能不是最佳选择。

      【讨论】:

        【解决方案3】:

        在正确的情况下,将 mysql 设置为双主服务器确实可以正常工作。但我不确定它是否非常适合您的场景。

        首先,mysql中的dual master setup实际上是一个ring-setup。服务器 A 定义为 B 的主服务器,而 B 同时定义为 A 的主服务器,因此两个服务器都充当主服务器和从服务器。复制通过发送一个二进制日志来工作,该日志包含从属设备在认为合适时插入的 sql 语句,这通常是立即的。但是,如果您使用本地插入来锤击它,则需要一段时间才能赶上。顺便说一下,从属插入是顺序的,因此您不会从多核等中获得任何好处。

        双主 mysql 的主要用途是通过自动故障转移在服务器级别具有冗余(通常在 linux 上使用 heartbeat)。不包括 mysql-cluster(出于各种原因),这是 mysql 唯一可用的自动故障转移。在google 上很容易找到基本双主的设置。心跳的东西需要更多的工作。但这并不是您真正要问的,因为它实际上就像一个单一的数据库服务器。

        如果您想要双主设置,因为您总是想写入本地数据库(同时写入两个数据库),您需要在编写应用程序时牢记这一点。您永远不能在数据库中拥有自动递增的值,并且当您拥有唯一值时,您必须确保两个位置永远不会写入相同的值。例如,位置 A 可以写入奇数唯一数,而位置 B 可以写入偶数唯一数。原因是您不能保证服务器在任何给定时间都是同步的,所以如果您在 A 中插入了一个唯一行,然后在第二个服务器赶上之前在 B 中插入了一个重叠的唯一行,您将有一个损坏的系统。如果有什么东西先坏了,整个系统就会停止。

        总而言之:这是可能的,但如果您要在此基础上构建业务软件,则需要非常小心。

        【讨论】:

        • 可以使用 --auto-increment-increment 和 --auto-increment-offset 选项实现多个主服务器的自动增量。每个 master 都有一个唯一的 auto-increment-offset,它们共享相同的 auto-increment-increment,即 >= master 的数量。
        【解决方案4】:

        由于 MySQL 复制的一对多架构,您必须有一个具有多个 master 的复制环:也就是说,每个 master 都从一个循环中的下一个复制。对于两个,它们相互复制。早在 v3.23 就已支持此功能。

        在我以前工作的地方,我们使用 v3.23 与相当多的客户一起做,作为提供您所要求的内容的一种方式。我们使用 Internet 上的 SSH 隧道进行复制。我们花了一些时间让它变得可靠,有几次我们不得不将一个数据库的二进制副本复制到另一个数据库(幸运的是,它们都没有超过 2Gb,也不需要 24 小时访问)。此外,v3 中的复制不如 v4 稳定,但即使在 v5 中,如果检测到任何类型的错误,它也会停止。

        为了适应不可避免的复制延迟,我们重新构建了应用程序,使其不依赖于AUTOINCREMENT 字段(并从表中删除了该属性)。由于我们开发了数据访问层,这相当简单;它不是使用 mysql_insert_id() 来创建新对象,而是首先创建新 ID 并将其与行的其余部分一起插入。我们还实现了存储在 ID 上半部分的站点 ID,因为它们是 BIGINTs。这也意味着当我们的客户需要三个位置的数据库时,我们不必更改应用程序。 :-)

        它不是 100% 健壮的。 InnoDB 刚刚获得了一些可见性,因此我们不能轻易使用事务,尽管我们考虑过。因此,当尝试使用相同 ID 创建两个对象时,偶尔会出现竞争条件。这意味着一个失败,我们试图在应用程序中报告。但是,监视复制并在它崩溃时修复它仍然是某人工作的重要组成部分。重要的是,在我们变得太不同步之前修复它,因为在少数情况下,数据库在两个站点中都被使用,如果我们不得不重建一个,很快就会变得难以重新集成。

        参与其中是一个很好的练习,但我不会再这样做了。不在 MySQL 中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-05
          • 2012-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-03
          相关资源
          最近更新 更多