我有 n 台服务器,计划使用主-主配置设置 n 台主服务器。哪种架构最好?此外,我还需要处理自动增量表的事情……
假设我的服务器是 A、B、C 和 D。将 B 的主服务器指定为 A、将 C 和 B 的主服务器指定为 C、将 D 的主服务器指定为 D 是否可以且安全?这会导致任何数据一致性问题吗?还有其他更好的方法吗?
答案1
你描述的拓扑结构称为“循环复制”。你基本上是在设置一个环,其中每个节点都充当下一个节点的主节点。高性能 MySQL不建议采用这种拓扑结构,原因如下:
- 它依赖于每个节点的可用性,因此增加了失败的概率。
- 如果从环中删除一个节点,源自该节点的复制事件将陷入无限循环,因为唯一可以过滤掉它们的节点不再可用。
答案2
这种拓扑结构可能是你的敌人,也可能是你的朋友,这取决于你在哪里执行主读写。成功使用循环复制的关键如下:循环复制交战规则:
- 将数据库上的 DML 限制到同一 DB 服务器
- 将数据库上的 SELECT 查询限制到同一个 DB 服务器
- 使用自动增量值来创建数据分界
案例
我雇主的网络托管公司托管一家汽车经销商 CRM 公司,该公司在全美(+夏威夷)拥有 859 家经销店。
他们有 3 个数据库服务器,每个服务器具有以下内容
- 192 GB RAM(16GB RAM 磁盘,162GB InnoDB 缓冲池)
- 双六核(没错,12 个 CPU)
- 1.7TB 数据量(776GB 经销商数据)
所有数据库服务器都使用循环复制
客户每个经销商都有一个数据库,因此 MySQL 实例内有一个多租户数据库布局。
客户的开发人员通过分配一定数量的经销商在 15 个 Web 服务器之间读取和写入数据来分离写入。每个 Web 服务器专门用于从三个 DB 服务器之一读取和写入。这意味着大约有 283 个经销商写入一个数据库。客户选择不使用复制-do-db也不复制忽略数据库因为这将会产生一个巨大的 DB 包含或排除列表。
每个数据库服务器的 /etc/my.cnf 的设置如下auto_increment_increment和自动增量偏移量
服务器1
[mysqld]
auto_increment_increment=10
auto_increment_offset=1
服务器2
[mysqld]
auto_increment_increment=10
auto_increment_offset=4
服务器3
[mysqld]
auto_increment_increment=10
auto_increment_offset=7
设置 auto_increment_increment 和 auto_increment_offset 是为了保护所有经销商数据库中每个 DB 服务器的 MySQL 实例中的 auto_increment 值的完整性。
只要我的客户遵循循环复制交战规则,客户就可以使用以下范例:
对于任何经销商 DLR
- 一个 DBServer W,用于写入 DLRDB
- 两台 DBServer(R1、R2)为 DLRDB 提供热备份
- 其中一个热备份可用于 mysqldump 备份,而不会干扰其他 DLRDB
客户自 2011 年 3 月以来一直使用这种拓扑结构,从未出现过任何有关数据完整性的投诉。
结束案例
我雇主的网络托管公司多年来也在数十家较小的客户提供相同的数据库拓扑/基础架构,从未出现过投诉。您可以完全信任循环复制,只要您严格遵守循环复制交战规则。
试一试 !!!
警告
MySQL 5.5 有新的命令扩展将 MASTER 更改为 IGNORE_SERVER_IDs。根据 MySQL 文档:
IGNORE_SERVER_IDS 已添加到 MySQL Cluster NDB 6.1.29、MySQL Cluster NDB 6.3.31、MySQL Cluster NDB 7.0.11 和 MySQL Cluster NDB 7.1.0(参见 Bug #47037)。此选项采用逗号分隔的 0 个或多个服务器 ID 列表。来自相应服务器的事件将被忽略,但日志轮换和删除事件除外,这些事件仍记录在中继日志中。
在循环复制中,原始服务器通常充当其自身事件的终止符,以便这些事件不会多次应用。因此,当循环中的一台服务器被移除时,此选项在循环复制中很有用。假设您有一个包含 4 台服务器的循环复制设置,服务器 ID 分别为 1、2、3 和 4,并且服务器 3 发生故障。当通过启动从服务器 2 到服务器 4 的复制来弥补差距时,您可以在服务器 4 上发出的 CHANGE MASTER TO 语句中包含 IGNORE_SERVER_IDS = (3),以告诉它使用服务器 2 而不是服务器 3 作为其主服务器。这样做会导致它忽略并且不传播任何源自不再使用的服务器的语句。
如果发出 CHANGE MASTER TO 语句时未使用任何 IGNORE_SERVER_IDS 选项,则将保留任何现有列表;RESET SLAVE 对服务器 ID 列表也没有影响。要清除忽略的服务器列表,必须使用带有空列表的选项:CHANGE MASTER TO IGNORE_SERVER_IDS = (); 如果 IGNORE_SERVER_IDS 包含服务器自己的 ID,并且服务器是在启用 --replicate-same-server-id 选项的情况下启动的,则会导致错误。
从 MySQL 5.1.47 开始,调用 CHANGE MASTER TO 会导致 MASTER_HOST、MASTER_PORT、MASTER_LOG_FILE 和 MASTER_LOG_POS 的先前值与执行前从属状态的其他信息一起写入错误日志。
此命令扩展非常适合从循环复制拓扑中删除 DB 服务器,而无需 SQL 命令在环中无限循环。