Linux之MariaDB集群


原文链接: Linux之MariaDB集群

通过上面的一系列测试,最后总结一下:

  1. 在生产环境下应该避免使用大事务,不建议在高并发写入场景下使用Galera Cluster架构,会导致集群限流,从而引起整个集群hang住,出现生产故障。针对这种情况可以考虑主从,实现读写分离等手段。

  2. 对数据一致性要求较高,并且数据写入不频繁,数据库容量也不大(50GB左右),网络状况良好的情况下,可以考虑使用Galera方案

CentOS镜像解决方案

创建并编辑MariaDB的源配置

sudo vi /etc/yum.repos.d/MariaDB.repo

写入配置文件

# MariaDB 10.1 CentOS repository list - created 2016-12-31 08:44 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum/10.1/centos7-amd64
gpgkey = https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum//RPM-GPG-KEY-MariaDB
gpgcheck = 1

MariaDB 10.2 CentOS repository list - created 2017-08-15 08:02 UTC

http://downloads.mariadb.org/mariadb/repositories/

[mariadb]
name = MariaDB
baseurl = https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum/10.2/centos7-amd64
gpgkey= https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck=1


执行安装命令
yum clean all  # 防止报错
yum makecache
sudo yum install mariadb-server

如果在用阿里云的服务器,可以将上述配置中的域名替换成
    http://mirrors.aliyun.com/
以上yum配置经修改后同样的适用于其他源,详细内容请往下看
yum -y install MariaDB-server MariaDB-client
## Ubuntu镜像
sudo apt install software-properties-common

sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://mirrors.tuna.tsinghua.edu.cn/mariadb/repo/10.2/ubuntu xenial main'

sudo apt-get install mariadb-client
sudo apt-get install mariadb-galera-server galera

## 配置文件MariaDB及Galera
sudo apt install xtrabackup
 /etc/my.cnf.d/galera.cnf

[galera]
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_address="gcomm://192.168.1.112,192.168.1.113 "
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0
wsrep_cluster_name="GaleraCluster"
wsrep_node_address="192.168.1.112"
wsrep_node_name="node1"
wsrep_sst_method=xtrabackup
wsrep_sst_auth=root:command

[galera]
wsrep_causal_reads=ON #节点应用完事务才返回查询请求
wsrep_provider_options="gcache.size=4G" #同步复制缓冲池
wsrep_certify_nonPK=ON #为没有显式申明主键的表生成一个用于certificationtest的主键,默认为ON
#log-bin=/app/galera/mysql-bin #如果不接从库,注释掉
#log_slave_updates=1 #如果不接从库,注释掉
query_cache_size=0 #关闭查询缓存
wsrep_on=ON #开启全同步复制模式
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name=MariaDB-Galera-Cluster
wsrep_cluster_address="gcomm://192.168.1.104,192.168.1.105,192.168.1.106"
wsrep_node_name=mariadb-a03
wsrep_node_address=192.168.1.104
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2 #主键自增模式修改为交叉模式
wsrep_slave_threads=8 #开启并行复制线程,根据CPU核数设置
innodb_flush_log_at_trx_commit=0 #事务提交每隔1秒刷盘
innodb_buffer_pool_size=2G
wsrep_sst_method=rsync
```
注意:
此处wsrep_cluster_address为集群中所有节点或非自己的任意集群节点ip即可。
不同节点的配置内容基本类似。
要保证wsrep_cluster_name必须一致,wsrep_node_address为本服务器地址。
wsrep_sst_auth为本机MariaDB用户及密码。
SST有三种全量拷贝方式:mysqldump、rsync和xtrabackup。SST的方法可以通过wsrep_sst_method这个参数来设置。

4.CentOS 7下启动MariaDB-Galera集群

CentOS 7使用了systemd作为它的初始化系统。不幸的是,systemd并不能传递命令行参数到相应的运行文件中。所以下面的命令是不能被执行的的:

#systemctl start mariadb –wsrep_new_cluster

systemctl:unrecognized option ‘-wsrep_new_cluster’

可以通过如下方案避免这样的问题:
[root@Node1]# mysqld_safe -wsrep-new-cluster
直接用mysql相应命令代入相关参数启动Node1及相关集群,此时新集群中只有Node1。
[root@Node2]#systemctl start mariadb
启动Node2上mariadb
show global stauts like ‘wsrep%’
检查Node2是否接入集群
[root@Node1]#ctrl+
关闭Node1上的MariaDB,此时集群中只有Node2节点
[root@Node1]# systemctl start mariadb
在Node1上用systemd启动mariadb,此时Node1节点接入到Node2节点所在集群。

grant all on . to 'galera'@'localhost' identified by '123456';

MariaDB一个节点初始化安装(galera-node1):

# mysql_install_db --defaults-file=/etc/my.cnf.d/server.cnf --user=mysql

在 galera-node1 节点上通过bootstrap启动集群(第一次启动一定要使用--wsrep-new-cluster,再次启动就不需要)

mysqld_safe --defaults-file=/etc/my.cnf.d/server.cnf --user=mysql  --wsrep-new-cluster &

在 galera-node1 节点上设置root密码以及安全设置(192.168.1.104,192.168.1.105,192.168.1.106)

/usr/bin/mysql_secure_installation
或
mysql_secure_installation

在galera-node2,galera-node3节点启动MariaDB:

mysqld_safe --defaults-file=/etc/my.cnf.d/server.cnf --user=mysql  &

验证

SHOW STATUS LIKE 'wsrep_cluster_size';
show global status like 'ws%';
注释:

wsrep_cluster_status为Primary,表示节点为主节点,正常读写。

wsrep_ready为ON,表示集群正常运行。

wsrep_cluster_size为3,表示集群有三个节点。

模拟脑裂后的处理

下面模拟在网络抖动发生丢包的情况下,两个节点失联导致脑裂。首先,在192.168.1.105和192.168.1.106两个节点上分别执行:

iptables -A INPUT -p tcp --sport 4567 -j DROP

iptables -A INPUT -p tcp --dport 4567 -j DROP

以上命令用来禁止wsrep全同步复制4567端口通信。

然后我们在192.168.1.104节点查看:

MariaDB [(none)]> show global statuslike 'ws%';
可以看到下面的几个值:
wsrep_cluster_size    1
wsrep_cluster_status  non-Primary
wsrep_ready         OFF

MariaDB [(none)]> use test_db;
ERROR 1047 (08S01): WSREP has not yetprepared node for application use

MariaDB [(none)]> select@@wsrep_node_name;
ERROR 1205 (HY000): Lock wait timeoutexceeded; try restarting transaction

现在已经出现脑裂的情况,并且集群无法执行任何命令。

为了解决这个问题,可以执行:

set global wsrep_provider_options="pc.bootstrap=true";

通过这个命令来强制恢复出现脑裂的节点。

避免脏读

Galera Cluster不是真正意义上的全同步复制,存在延迟。我们可以在一个节点上面执行FLUSH TABLES WITH READ LOCK;全局读锁。

然后在其他节点执行写操作,观察延迟情况。

比如我们在192.168.1.106节点执行全局读锁设置:

################################################################################

可将cluster 同步方式设置成为

wsrep_sst_method=xtrabackup  #所有节点都要更改

xtrabackup 安装 FROM http://allcmd.com/post/id/198
INSTALL MARIADB

192.168.80.111 node1 db1

192.168.80.110 node2 db2

192.168.80.101 node3 db3

all node
因为官方源连接不稳定,最好使用迅雷下载下来,放到每个node /var/cache/yum/下的目录里
使用aliyun.repo http://mirrors.aliyun.com/help/centos
epel.repo http://mirrors.aliyun.com/help/epel

cat << EOF >/etc/yum.repos.d/mariadb.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
EOF

yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/socat-1.7.2.3-1.el6.x86_64.rpm -y

yum install MariaDB-Galera-server MariaDB-client rsync galera -y

/etc/init.d/mysql start && chkconfig mysql on

/usr/bin/mysql_secure_installation ##不设置密码

mkdir /mariadb_data && mount /dev/mapper/VG_SYSTEM-lv_mysql_data /mariadb_data/

echo "/dev/mapper/VG_SYSTEM-lv_mysql_data /mariadb_data ext4 defaults 0 0" >>/etc/fstab

mysql -uroot -p

DELETE FROM mysql.user WHERE user='';
GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* to sst_user@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
quit

/etc/init.d/mysql stop

all node

rm -rf /etc/my.cnf.d/*

cat >/etc/my.cnf.d/galera_common.cnf <<HERE
[mysqld]
datadir=/mariadb_data/data
character_set_server=utf8
wsrep-cluster-name = "szqs_d3_2_cluster"
wsrep-provider = /usr/lib64/galera/libgalera_smm.so
wsrep-provider-options = "gcache.size=256M;gcache.page_size=128M"
wsrep-sst-auth = "sst_user:password"
binlog-format = row
default-storage-engine = InnoDB
innodb-doublewrite = 1
innodb-autoinc-lock-mode = 2
innodb-flush-log-at-trx-commit = 2
innodb-locks-unsafe-for-binlog = 1
HERE

db1

cat >/etc/my.cnf.d/galera_db00.cnf <<HERE
[mysqld]
wsrep-node-name = "db1"
wsrep-sst-receive-address = 192.168.80.111
wsrep-node-incoming-address = 192.168.80.111
bind-address = 192.168.80.111
wsrep_sst_method = rsync

wsrep-cluster-address = gcomm://192.168.80.111,192.168.80.101,192.168.80.110
HERE

/etc/init.d/mysql start --wsrep-new-cluster

db2

cat >/etc/my.cnf.d/galera_db00.cnf <<HERE
[mysqld]
wsrep-node-name = "db2"
wsrep-sst-receive-address = 192.168.80.110
wsrep-node-incoming-address = 192.168.80.110
bind-address = 192.168.80.110
wsrep_sst_method = rsync
wsrep-cluster-address = gcomm://192.168.80.111,192.168.80.101,192.168.80.110
HERE

/etc/init.d/mysql start

db3

cat >/etc/my.cnf.d/galera_db00.cnf <<HERE
[mysqld]
wsrep-node-name = "db3"
wsrep-sst-receive-address = 192.168.80.101
wsrep-node-incoming-address = 192.168.80.101
bind-address = 192.168.80.101
wsrep_sst_method = rsync
wsrep-cluster-address = gcomm://192.168.80.111,192.168.80.101,192.168.80.110
HERE

/etc/init.d/mysql start

检测集群

show status like 'wsrep%';

配置NGINX转发

mkdir /home/nginx/tcp_conf.d
vim /home/nginx/nginx.conf

添加stream模块

stream {
include /home/nginx/tcp_conf.d/*.conf;
}

vim /home/nginx/tcp_conf.d/tcp.conf

upstream szqs_d3_1 {
    hash $remote_addr consistent;
    server 192.168.80.101:3306 weight=5 max_fails=3 fail_timeout=30s;
    server 192.168.80.110:3306 weight=5 max_fails=3 fail_timeout=30s;
    server 192.168.80.111:3306 weight=5 max_fails=3 fail_timeout=30s;
}

server {
    listen 3306;
    proxy_connect_timeout 1s;
    proxy_timeout 3s;
    proxy_pass szqs_d3_1;
}
`