使用 Galera Cluster 而不是常规的 Master/Slave Replication 有什么缺点?Galera 的 0 从延迟时间、同步复制和无单点故障看起来很吸引人,那为什么 Galera 集群不常见呢?
我最近遇到了以前从未见过的 MySQL 情况。我们有一个有 3 个节点的 Percona 集群。master 停止处理查询,我们托管的 PHP FPM Web 应用程序变得无响应。当我检查时SHOW PROCESSLIST,MySQL 进程卡在状态:wsrep: initiating replication for write set (-1)
PHP 将所有查询定向到的主数据库和两个辅助数据库之一都是这种情况。这是我看到的输出SHOW PROCESSLIST:
mysql> show processlist;
+-------+-------------+--------------------+-----------------+---------+-------+--------------------------------------------------------+--------------------------------------------------------------------------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+-------+-------------+--------------------+-----------------+---------+-------+--------------------------------------------------------+--------------------------------------------------------------------------------------+-----------+---------------+
| 1 | system user | | NULL | Sleep | 2171 | wsrep: committing write set (542480920) | NULL | 0 | 0 |
| …Run Code Online (Sandbox Code Playgroud) 我目前正在考虑建立一个数据库集群(MySQL Galera 或 Percona),但我只有 2 台机器。
但是,根据我读过的许多来源(这篇来自 Mariadb KB 的文章),集群中的最小节点大小应为 3,以避免出现裂脑情况。
为了避免裂脑情况,集群中推荐的最小节点数为3。阻止状态转移是需要至少3 个节点才能在其中一个成员发生故障并需要重新启动时享受服务可用性的另一个原因。虽然其中两名成员将从事状态转移,但其余成员将能够继续为客户请求提供服务。
所以我想知道我是否可以在两台机器上运行 3 个(或更多)docker 容器,每个容器都运行一个数据库服务器。如果其中一台机器出现故障,集群中仍然有 3 个节点,因此不会出现裂脑问题。
感觉像是作弊,但我想不出不这样做的理由。
这个设置有意义吗?
我们正在评估一个 Galera 设置,到目前为止,除了一些具有糟糕读取性能的查询之外,我们还没有注意到许多缺点,我无法理解它。
查询本身并没有真正优化,但它在生产框上的返回时间不到 0.20 秒。在强大的 galera 3 节点设置上需要几分钟时间。(事实上,在更强大的硬件上)。
版本适用于 galera:
mysqld Ver 10.0.16-MariaDB-1~trusty-wsrep-log for
debian-linux-gnu on x86_64 (mariadb.org binary distribution, wsrep_25.10.r4144)
Run Code Online (Sandbox Code Playgroud)
和“旧”的生产机器
mysqld Ver 5.3.12-MariaDB-mariadb122~maverick for
debian-linux-gnu on x86_64 ((MariaDB - http://mariadb.com/))
Run Code Online (Sandbox Code Playgroud)
查询:
MariaDB [ticketing]> EXPLAIN SELECT DISTINCT `purchase`.`id`,
`purchase`.`invoiceid`, `purchase`.`userid`, `purchase`.`currencyid`, `purchase`.`purchasestatusid`, `purchase`.`isdeleted`,
`purchase`.`emailshistory`, `purchase`.`created`,
`purchase`.`paymentfee` FROM `purchase`
INNER JOIN `payment` ON payment.purchaseid = purchase.id
WHERE (invoiceid IS NULL) AND (purchasetypeid = 1)
AND (purchase.created >= '2015-01-19 10:40:17')
AND (paymenttypeid = 15) ORDER BY `created` DESC;
+------+-------------+----------+--------+-------------------------------------------------------------------+-----------------+---------+------------------------------+-------+----------------------------------------------+
| …Run Code Online (Sandbox Code Playgroud) 我们使用这些版本:
# rpm -qa | egrep '(galera|maria)'
mariadb-libs-5.5.41-2.el7_0.x86_64
mariadb-galera-common-5.5.40-6.el7ost.x86_64
mariadb-galera-server-5.5.40-6.el7ost.x86_64
mariadb-5.5.41-2.el7_0.x86_64
galera-25.3.5-6.el7ost.x86_64
Run Code Online (Sandbox Code Playgroud)
那是我们的grastate.dat
# cat /var/lib/mysql/data/grastate.dat
# GALERA saved state
version: 2.1
uuid: e7ead849-f2a3-11e4-bfda-7f651f709ee3
seqno: -1
cert_index:
Run Code Online (Sandbox Code Playgroud)
在seqno: -1 外观腥。在其他集群上有一个数字。我不知道为什么。根据文档,这似乎“崩溃了”。-1 是在停电之后。但是这个集群是健康的。
修改时间很早
# stat /var/lib/mysql/data/grastate.dat
File: â/var/lib/mysql/data/grastate.datâ
Size: 104 Blocks: 8 IO Block: 4096 regular file
Device: fd09h/64777d Inode: 108 Links: 1
Access: (0660/-rw-rw----) Uid: ( 1000/ mysql) Gid: ( 1000/ mysql)
Context: system_u:object_r:mysqld_db_t:s0
Access: 2015-07-29 14:51:25.170699518 +0200
Modify: 2015-06-02 11:50:21.564360655 +0200
Change: 2015-06-02 11:50:21.564360655 +0200
Birth: -
Run Code Online (Sandbox Code Playgroud)
来自日志(没有错误,只有信息和警告): …
我有三台要在其上安装 Galera 集群的服务器,我按照此链接进行安装和配置。但是当我想启动第一台服务器时,我收到了这个错误:
root@node107:/home/debian# service mysql start --wsrep-new-clusterping
Job for mysql.service failed. See 'systemctl status mysql.service' and 'journalctl -xn' for details.
Run Code Online (Sandbox Code Playgroud)
和 :
root@node107:/home/debian# journalctl -xn
-- Logs begin at Tue 2016-03-01 19:02:04 IRST, end at Tue 2016-03-01 19:39:32 IRST. --
Mar 01 19:39:31 node107 mysqld[5102]: 160301 19:39:31 [ERROR] WSREP: gcs/src/gcs.cpp:gcs_open():1379: Failed to open channel 'test_cluster' at 'gcomm://192.168.120.107,192.168.120.111,192.168.120.11
Mar 01 19:39:31 node107 mysqld[5102]: 160301 19:39:31 [ERROR] WSREP: gcs connect failed: Connection timed out
Mar 01 19:39:31 node107 mysqld[5102]: …Run Code Online (Sandbox Code Playgroud) 如何重启 MariaDB Galera 集群?
在所有节点都崩溃后,我尝试恢复集群但没有成功。我只有2个节点。
正如文档所说,我在其中一个节点上设置了一个参数:
set global wsrep_provider_options="pc.bootstrap=true";
Run Code Online (Sandbox Code Playgroud)
然后尝试启动第一个节点:
systemctl start mariadb
Run Code Online (Sandbox Code Playgroud)
之后我收到一个错误:
Oct 11 16:11:12 proxy1 sh[2367]: 2016-10-11 16:11:12 140291677038720 [Note] /usr/sbin/mysqld (mysqld 10.1.18-MariaDB) starting as process 2402 ...
Oct 11 16:11:15 proxy1 sh[2367]: WSREP: Recovered position b6c1dc93-8fa7-11e6-933e-e64cd44e3be0:141
Oct 11 16:11:15 proxy1 mysqld[2434]: 2016-10-11 16:11:15 140047023368320 [Note] /usr/sbin/mysqld (mysqld 10.1.18-MariaDB) starting as process 2434 ...
Oct 11 16:11:15 proxy1 mysqld[2434]: 2016-10-11 16:11:15 140047023368320 [Note] WSREP: Read nil XID from storage engines, skipping position init
Oct 11 16:11:15 proxy1 …Run Code Online (Sandbox Code Playgroud) 我们正在使用主服务器的完整备份恢复我们的从服务器,并收到一堆重复的密钥错误。一旦从站被追上,它就不会抛出任何错误(只有当它落后于主站时)。我们复制所有数据库表。我们使用一个 MariaDB Galera 集群作为主,一个 MariaDB 实例作为从。
这些是完成的步骤:
通过检查变量获取 master 的 GTID "gtid_binlog_position"。保存此值。
使用以下命令备份 master:
mysql -u -p --routines --triggers --single-transaction --gtid --master-data --dump-slave --add-drop-database <dbnames> | gzip > /tmp/backup.sql.gz.
完成此备份大约需要 20 分钟。
将数据库导入从属。
运行RESET SLAVE ALL,并将 GTID 位置设置为第一步中的值。这是通过命令完成的SET GLOBAL gtid_slave_pos = "<gtid from step 1>";,然后CHANGE MASTER TO ...
在此之后,我收到"Duplicate Entry for key 'PRIMARY', error code 1062"错误。
这些是使用的设置:
[mysqld]
innodb_buffer_pool_size = 6G
gtid_domain_id=100
log-slave-updates=true
open_files_limit=1000000
innodb_large_prefix = on
innodb_file_format = barracuda
innodb_file_per_table …Run Code Online (Sandbox Code Playgroud) 我崩溃了我所有的 3 个节点。启动所有节点后,我注意到 mariadb 已死。我无法再次运行它。
我在所有服务器上使用 CentOS 7
我尝试启动第一个节点,然后再启动其他节点,但没有成功。
首先,我试图按照文档中的说明找到最新的 seqno。因此,我查看了所有 3 个节点上的此文件:/var/lib/mysql/grastate.dat并注意到所有 3 个节点上的内容都相同(uuid 相同且 seqno 相同)!这是这个文件:
# GALERA saved state
version: 2.1
uuid: ec3e180d-bbff-11e6-b989-3273ac13ba57
seqno: -1
cert_index:
Run Code Online (Sandbox Code Playgroud)
好的。由于所有节点都是相同的,我可以将任何节点作为新节点运行并向其添加另一个节点。我使用了下一个命令:
galera_new_cluster
Run Code Online (Sandbox Code Playgroud)
它没有用。节点未启动。
这是我得到的:
-- Unit mariadb.service has begun starting up.
Dec 07 18:20:55 GlusterDC1_1 sh[4298]: 2016-12-07 18:20:55 139806456780992 [Note] /usr/sbin/mysqld (mysqld 10.1.19-MariaDB) starting as process 4332 ...
Dec 07 18:20:58 GlusterDC1_1 sh[4298]: WSREP: Recovered position ec3e180d-bbff-11e6-b989-3273ac13ba57:83
Dec 07 18:20:58 GlusterDC1_1 mysqld[4364]: 2016-12-07 18:20:58 139830894778560 [Note] /usr/sbin/mysqld (mysqld 10.1.19-MariaDB) …Run Code Online (Sandbox Code Playgroud) 我正在运行一个插入很多行的应用程序,我们遇到了一些低性能。所以我开始用 sysbench 和 oltp_insert.lua(实际上是用随机密钥插入)对 Galera 集群进行基准测试。
集群的性能真的很差。
用同样的测试:
表结构是这样的:
Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
到目前为止我尝试过的(没有成功):
wsrep_slave_threads=16wsrep_sync_wait=0(虽然我不执行读取)配置:
[mysqld]
binlog_format=ROW
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0
datadir=/var/lib/mysql
innodb_buffer_pool_size = 300MB
innodb_large_prefix=1
innodb_file_format=Barracuda …Run Code Online (Sandbox Code Playgroud) galera ×10
mariadb ×7
mysql ×6
clustering ×3
mariadb-10.1 ×2
linux ×1
mysql-5.7 ×1
ndbcluster ×1
recovery ×1
replication ×1