如何在Ubuntu16.04服务器上使用MariaDB10.1配置Galera集群
介绍
集群通过将更改分布到不同的服务器来增加数据库的高可用性。 如果其中一个实例发生故障,其他实例可以快速继续服务。
集群有两种通用配置,主动-被动和主动-主动。 在主动-被动集群中,所有写入都在单个主动服务器上完成,然后复制到一个或多个被动服务器,这些被动服务器准备仅在主动服务器发生故障时接管。 一些主动-被动集群还允许在被动节点上执行 SELECT 操作。 在主动-主动集群中,每个节点都是可读写的,对一个节点所做的更改会复制到所有节点。
在本指南中,我们将配置一个主动-主动的 MariaDB Galera 集群。 出于演示目的,我们将配置和测试三个节点,即最小的可配置集群。
先决条件
要继续进行,您将需要:
- 三台 Ubuntu 16.04 服务器,每台服务器都有一个非 root 用户,具有
sudo
权限和专用网络,如果您可以使用的话。- 如需帮助设置具有这些权限的用户,请遵循我们的 Initial Server Setup with Ubuntu 16.04 指南。
- 有关设置专用网络的帮助,请参阅 如何设置和使用 DigitalOcean 专用网络 。
一旦所有这些先决条件都到位,我们就可以安装 MariaDB。
第 1 步 — 将 MariaDB 10.1 存储库添加到所有服务器
MariaDB 10.1 不包含在默认的 Ubuntu 存储库中,因此我们首先将由 MariaDB 项目维护的外部 Ubuntu 存储库添加到我们的所有三台服务器。
注意: MariaDB 是一个备受推崇的提供商,但并非所有外部存储库都是可靠的。 请务必仅从受信任的来源安装。
首先,我们将使用 apt-key
命令添加 MariaDB 存储库密钥,apt 将使用该命令来验证包的真实性。
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
一旦我们在数据库中获得了可信密钥,我们就可以添加存储库。 之后我们需要运行 apt-get update
以包含来自新存储库的包清单:
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu xenial main' sudo apt-get update
注意:添加仓库后必须运行update
。 否则,您将从不包含 Galera 包的 Ubuntu 包安装 10.0 版。
在所有三台服务器上更新存储库后,我们就可以安装 MariaDB。 关于 MariaDB 需要注意的一点是,它起源于 MySQL 的替代品,因此在许多配置文件和启动脚本中,您会看到 mysql
而不是 mariadb
。 为了一致性起见,我们在本指南中使用 mysql
,其中任何一个都可以工作。
第 2 步 — 在所有服务器上安装 MariaDB
从 10.1 版本开始,MariaDB Server 和 MariaDB Galera Server 包合并,所以安装 mariadb-server
会自动安装 Galera 和几个依赖:
sudo apt-get install mariadb-server
在安装过程中,系统会要求您为 MariaDB 管理用户设置密码。 无论您选择什么,一旦复制开始,此根密码将被第一个节点的密码覆盖。
我们应该拥有开始配置集群所需的所有部分,但是由于我们将在后面的步骤中依赖 rsync
,因此我们要确保它已安装。
sudo apt-get install rsync
这将确认 rsync
的最新版本已经可用或提示您升级或安装它。
一旦我们在三台服务器上安装了 MariaDB,我们就可以开始配置了。
第 3 步 — 配置第一个节点
集群中的每个节点都需要具有几乎相同的配置。 因此,我们将在第一台机器上完成所有配置,然后将其复制到其他节点。
默认情况下,MariaDB 配置为检查 /etc/mysql/conf.d
目录以获取以 .cnf
结尾的附加配置设置。 我们将在此目录中创建一个包含所有集群特定指令的文件:
sudo nano /etc/mysql/conf.d/galera.cnf
将以下配置复制并粘贴到文件中。 您将需要更改以红色突出显示的设置。 我们将在下面解释每个部分的含义。
/etc/mysql/conf.d/galera.cnf
[mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name="test_cluster" wsrep_cluster_address="gcomm://first_ip,second_ip,third_ip" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address="this_node_ip" wsrep_node_name="this_node_name"
- 第一部分 修改或重新声明 MariaDB/MySQL 设置,使集群能够正常运行。 例如,Galera Cluster 不能与 MyISAM 或类似的非事务性存储引擎一起使用,并且
mysqld
不能绑定到 localhost 的 IP 地址。 您可以在 Galera Cluster 系统配置页面 上了解更详细的设置。 - “Galera Provider Configuration”部分 配置提供 WriteSet 复制 API 的 MariaDB 组件。 这在我们的例子中意味着 Galera,因为 Galera 是一个 wsrep(WriteSet Replication)提供者。 我们指定通用参数来配置初始复制环境。 这不需要任何自定义,但您可以了解更多关于 Galera 配置选项 的信息。
- “Galera Cluster Configuration”部分定义集群,通过IP地址或可解析的域名识别集群成员,并为集群创建一个名称,以确保成员加入正确的组。 您可以将
wsrep_cluster_name
更改为比test_cluster
更有意义的内容或保持原样,但您 必须 使用您三个的地址更新wsrep_cluster_address
服务器。 如果您的服务器有私有 IP 地址,请在此处使用它们。 - “Galera 同步配置”部分 定义了集群如何在成员之间进行通信和同步数据。 这仅用于节点上线时发生的状态传输。 对于我们的初始设置,我们使用
rsync
,因为它通常可用并且可以满足我们现在的需要。 - “Galera Node Configuration”部分明确了当前服务器的IP地址和名称。 这在尝试诊断日志中的问题以及以多种方式引用每个服务器时很有帮助。
wsrep_node_address
必须与您所在机器的地址匹配,但您可以选择任何您想要的名称,以帮助您识别日志文件中的节点。
当您对集群配置文件感到满意时,将内容复制到剪贴板,保存并关闭文件。
第 4 步 — 配置剩余节点
在剩余的每个节点上,打开配置文件:
sudo nano /etc/mysql/conf.d/galera.cnf
粘贴您从第一个节点复制的配置,然后更新“Galera 节点配置”以使用您正在设置的特定节点的 IP 地址或可解析域名。 最后,更新其名称,您可以将其设置为任何有助于您在日志文件中识别节点的名称:
/etc/mysql/conf.d/galera.cnf
. . . # Galera Node Configuration wsrep_node_address="this_node_ip" wsrep_node_name="this_node_name" . . .
保存并退出每个服务器上的文件。 我们几乎已准备好启动集群,但在此之前,我们需要确保适当的端口已打开。
第 5 步 — 在每台服务器上打开防火墙
在每台服务器上,让我们检查防火墙的状态:
sudo ufw status
在这种情况下,只允许通过 SSH:
OutputStatus: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)
由于在这种情况下只允许 ssh 流量,我们需要为 MySQL 和 Galera 流量添加规则。 如果我们尝试启动集群,我们会因为防火墙规则而失败。
Galera 可以使用四个端口:
- 3306 对于使用 mysqldump 方法的 MySQL 客户端连接和状态快照传输。
- 4567 对于 Galera Cluster 复制流量,多播复制在此端口上使用 UDP 传输和 TCP。
- 4568 用于增量状态转移。
- 4444 对于所有其他状态快照传输。
在我们的示例中,我们将在进行设置时打开所有四个端口。 一旦我们确认复制工作正常,我们就想关闭我们实际上不使用的所有端口,并将流量限制在集群中的服务器上。
使用以下命令打开端口:
sudo ufw allow 3306,4567,4568,4444/tcp sudo ufw allow 4567/udp
注意: 根据您的服务器上运行的其他内容,您可能希望立即限制访问。 UFW Essentials: Common Firewall Rules and Commands 指南可以帮助解决这个问题。
第 6 步 — 启动集群
首先,我们需要停止正在运行的 MariaDB 服务,以便我们的集群可以联机。
在所有三台服务器上停止 MariaDB:
在所有三台服务器上使用以下命令停止 mysql,以便我们可以将它们恢复到集群中:
sudo systemctl stop mysql
systemctl
不会显示所有服务管理命令的结果,所以为了确保我们成功,我们将使用以下命令:
sudo systemctl status mysql
如果最后一行如下所示,则该命令成功。
Output . . . Aug 19 02:55:15 galera-01 systemd[1]: Stopped MariaDB database server.
一旦我们关闭了所有服务器上的 mysql
,我们就可以继续了。
调出第一个节点:
要启动第一个节点,我们需要使用一个特殊的启动脚本。 我们配置集群的方式是,每个上线的节点都尝试连接到其 galera.cnf
文件中指定的至少一个其他节点以获取其初始状态。 如果不使用允许 systemd 传递 --wsrep-new-cluster
参数的 galera_new_cluster
脚本,正常的 systemctl start mysql
将失败,因为没有运行节点来连接第一个节点。
sudo galera_new_cluster
当这个脚本成功时,节点注册为集群的一部分,我们可以通过以下命令看到它:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Output+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 1 | +--------------------+-------+
在剩下的节点上,我们可以正常启动mysql
。 他们将搜索集群列表中在线的任何成员,因此当他们找到一个时,他们将加入集群。
调出第二个节点:
开始mysql
:
sudo systemctl start mysql
随着每个节点上线,我们应该看到我们的集群大小增加:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Output+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 2 | +--------------------+-------+
调出第三个节点:
开始mysql
:
sudo systemctl start mysql
如果一切正常,集群大小应该设置为三个:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Output+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 3 | +--------------------+-------+
此时,整个集群应该是在线并且可以通信的。 然而,在我们测试复制之前,还有一个配置细节需要注意。
第 7 步 — 配置 Debian 维护用户
目前,Ubuntu和Debian的MariaDB服务器作为特殊维护用户进行日志轮换等日常维护。 当我们安装 MariaDB 时,该用户的凭据是随机生成的,存储在 /etc/mysql/debian.cnf
中,并插入到 MariaDB 的 mysql
数据库中。
一旦我们启动集群,第一个节点的密码就会复制到其他节点,因此 debian.cnf
中的值不再与数据库中的密码匹配。 这意味着使用维护帐户的任何东西都将尝试使用配置文件中的密码连接到数据库,并且除了第一个节点之外的所有节点都将失败。
为了纠正这个问题,我们将第一个节点的 debian.cnf
复制到其余节点。
从第一个节点复制:
使用文本编辑器打开 debian.cnf
文件:
sudo nano /etc/mysql/debian.cnf
该文件应类似于:
[client] host = localhost user = debian-sys-maint password = 03P8rdlknkXr1upf socket = /var/run/mysqld/mysqld.sock [mysql_upgrade] host = localhost user = debian-sys-maint password = 03P8rdlknkXr1upf socket = /var/run/mysqld/mysqld.sock basedir = /usr
将信息复制到剪贴板。
更新第二个节点:
在您的第二个节点上,打开相同的文件:
sudo nano /etc/mysql/debian.cnf
尽管文件顶部的警告说“请勿触摸!” 我们需要进行更改以使集群正常工作。 您可以放心地删除当前信息并粘贴第一个节点配置中的内容。 他们现在应该完全一样了。 保存并关闭文件。
更新第三个节点:
在您的第三个节点上,打开相同的文件:
sudo nano /etc/mysql/debian.cnf
删除当前信息并粘贴第一个节点配置中的内容。 保存并关闭文件。
不匹配不会影响我们测试复制的能力,但最好尽早处理以避免以后出现故障。
注意: 完成后,您可以通过提供本地debian.conf
的密码来测试维护帐户是否能够连接,如下所示:
sudo cat /etc/mysql/debian.cnf
从输出中复制密码。 然后连接到mysql
:
mysql -u debian-sys-maint -p
在提示符处,提供您复制的密码。 如果你能连接,一切都很好。
如果不是,请验证文件中的密码是否与第一个节点相同,然后替换为以下内容:
update mysql.user set password=PASSWORD('password_from_debian.cnf') where User='debian-sys-maint';
重复以测试剩余的节点。
第 8 步 — 测试复制
到目前为止,我们已经完成了这些步骤,以便我们的集群可以执行从任何节点到任何其他节点的复制,称为主动-主动或主-主复制。 让我们测试一下复制是否按预期工作。
写入第一个节点:
我们将从在我们的第一个节点上进行数据库更改开始。 以下命令将创建一个名为 playground
的数据库和一个名为 equipment
的表。
mysql -u root -p -e 'CREATE DATABASE playground; CREATE TABLE playground.equipment ( id INT NOT NULL AUTO_INCREMENT, type VARCHAR(50), quant INT, color VARCHAR(25), PRIMARY KEY(id)); INSERT INTO playground.equipment (type, quant, color) VALUES ("slide", 2, "blue");'
现在我们的表中有一个值。
在第二个节点上读写:
接下来,我们将查看第二个节点以验证复制是否正常工作:
mysql -u root -p -e 'SELECT * FROM playground.equipment;'
如果复制工作正常,我们在第一个节点上输入的数据将在第二个节点上可见:
Output+----+-------+-------+-------+ | id | type | quant | color | +----+-------+-------+-------+ | 1 | slide | 2 | blue | +----+-------+-------+-------+
从同一个节点,我们可以将数据写入集群:
mysql -u root -p -e 'INSERT INTO playground.equipment (type, quant, color) VALUES ("swing", 10, "yellow");'
在第三个节点上读写:
从第三个节点,我们可以通过再次查询来读取所有这些数据:
mysql -u root -p -e 'SELECT * FROM playground.equipment;'
Output +----+-------+-------+--------+ | id | type | quant | color | +----+-------+-------+--------+ | 1 | slide | 2 | blue | | 2 | swing | 10 | yellow | +----+-------+-------+--------+
同样,我们可以从该节点添加另一个值:
mysql -u root -p -e 'INSERT INTO playground.equipment (type, quant, color) VALUES ("seesaw", 3, "green");'
在第一个节点上阅读:
回到第一个节点,我们可以验证我们的数据是否无处不在:
mysql -u root -p -e 'SELECT * FROM playground.equipment;'
Output +----+--------+-------+--------+ | id | type | quant | color | +----+--------+-------+--------+ | 1 | slide | 2 | blue | | 2 | swing | 10 | yellow | | 3 | seesaw | 3 | green | +----+--------+-------+--------+
我们已经测试了我们可以写入所有节点并且复制正在正确执行。
结论
此时,您应该配置了一个工作的三节点 Galera 测试集群。 如果您计划在生产环境中使用 Galera 集群,建议您从不少于五个节点开始。
在生产使用之前,您可能需要查看一些 其他状态快照传输 (sst) 代理 ,例如“xtrabackup”,它允许您非常快速地设置新节点,而不会对您的活动造成大的中断节点。 这不会影响实际的复制,但在初始化节点时是一个问题。
最后,如果您的集群成员不在专用网络上,您还需要设置 SSL 以在数据在服务器之间移动时保护您的数据。