Linux之MariaDB集群
通过上面的一系列测试,最后总结一下:
在生产环境下应该避免使用大事务,不建议在高并发写入场景下使用Galera Cluster架构,会导致集群限流,从而引起整个集群hang住,出现生产故障。针对这种情况可以考虑主从,实现读写分离等手段。
对数据一致性要求较高,并且数据写入不频繁,数据库容量也不大(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上mariadbshow 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;
}