Mysql数据库作为开源数据库中比较成功的代表,在很多功能上面已经非常完美,特别是其复制功能实现了用户数据的高度冗余,但是即使复制过程再快,从复制的原理来看,复制永远不能摆脱异步复制这个特性,即使是最新的半同步复制也不能完美解决这个问题,半同步复制解决的仅仅是数据安全级别的问题,只要是异步复制,就有可能造成数据的不统一,所以我们需要寻求一种解决方案,实现各节点之间数据的完全实时同步,那就是Mysql的集群技术,本文将从集群的架构原理,集群系统的配置搭建以及管理来深入理解Mysql集群是如何工作的,有了对其的深入理解,我们才能够根据我们实际生产环境中的场景设计Mysql的架构模式,才能真正实现整套系统的最佳性能以及高可用性。
可能很多人对Mysql的复制已经非常了解,我们在此不妨再共同梳理一下复制的基本原理以及流程,以便跟集群架构作出对比。首先,复制功能是需要借助于二进制日志(binlog)功能才能够实现,为方便理解与交流,如下图所示
图 Mysql复制原理图
该图比较简明得画出了Mysql复制中主从节点通过二进制日志文件如何进行复制的过程,主节点将对数据产生影响的语句写进本地二进制日志文件(如果二进制日志格式为ROW的话则是将变化的行写入二进制日志),从节点上面的I/O线程通过请求与接收操作将主节点的二进制日志文件拉回本地,生成中继日志,再通过SQL进程将中继日志中的语句进行解析并执行,由此保证了两个节点数据的相对时间内的一致性。
以上为Mysql的复制原理,而关于复制跟集群的区别又在哪里呢?大致为如下两点:
1.复制是一个服务器向另外一个服务器发送消息(数据)的方式
2.集群包含成员,消息,冗余和自动故障转移等功能
最重要的一点:集群是无共享存储,却能保证各节点的数据实时同步。
以下正文便进入了我们对Mysql集群的学习与探讨,通过对集群的不断了解,我们可以将集群与复制功能同用,共同提高系统高可用性。
下面这个图是从官方文档拿来的,可以非常有层次的列出了不同节点类型之间的关系,在集群中,节点的概念并非以实际物理机器或者虚拟机,而是以集群中不同组件,如SQL节点,管理节点,存储节点来统计的,所以在一个物理机或者虚拟机上面可以有N个节点,比如同时拥有SQL节点,管理节点或者存储节点,但是在生产环境中,尽量保证每个节点对应一台机器,否则集群的功能就完全体现不出来了。
分为四层:
各层类型 |
功能 |
应用程序层 |
负责与Mysql服务器通信的各种应用程序 |
MYSQL服务器层 |
处理SQL命令,并与NDB存储引擎通信的MYSQL服务器 |
NDB集群组件层 |
NDB集群组件有时也称为数据节点,负责处理查询,然后将结果返回非MYSQL服务器 |
集群管理层 |
负责对整个集群进行监控,管理 |
图集群各层功能
集群提供的功能大致如下:
1.节点恢复
2.日志
3.检查点:
本地检查点【用于清除部分重做日志】 :本地检查点删除日志文件的尾部,当所有数据节点的日志都被刷新到磁盘的时候讲创建全局检查点
全局检查点【用于不同数据节点之间的同步】 :在磁盘上创建一个所有节点数据的事务一致性快照
4.系统恢复
5.热备份以及恢复: 创建每个数据节点的同步备份,包括数据库中的对象的元数据,数据本身和当前事务日志。
6.无单点故障
7.故障转移
8.数据分区
9.联机操作:进行维护工作,正常关闭服务器或者给数据加锁,练级添加新的数据节点,改变表结构,甚至重组集群中的数据。
定义:clusterdir=/opt/mysql_cluster
datadir=/opt/mysql_cluster/data
操作系统: Red HatEnterprise Linux Server release 6.3 (Santiago) 64bit
主机名 |
IP地址 |
类型 |
配置文件 |
数据目录 |
mgmd |
192.168.9.100 |
mgmd |
$clusterdir/config.ini |
$clusterdir/logs |
ndbd01 |
192.168.9.101 |
ndbd |
$clusterdir /my.cnf |
$clusterdir/ndbdata |
ndbd02 |
192.168.9.102 |
ndbd |
$clusterdir /my.cnf |
$clusterdir/ndbdata |
mysqld01 |
192.168.9.201 |
sqld |
/etc/my.cnf |
$datadir |
mysqld02 |
192.168.9.202 |
sqld |
/etc/my.cnf |
$datadir |
每个实验节点的配置:
1.内存:512MB
2.硬盘:40GB
生产环境以实际情况为标准。
配置前,声明一下所有节点均需要注意的设置,就是所有节点的iptables均需要关闭或者设置适当的规则,否则在各个节点启动或者执行的过程中均会出现非常纠结的问题。所以在每个节点上面均关闭iptables以及selinux为好,根据笔者实验,总结以下两点:
1.如果mgmd节点不关闭iptables,则会出现ndbd节点启动的时候无法连接
2.如果ndbd节点不关闭iptables,则sql节点在连接过程中会出现一系列问题
列出几点错误,以便各位在搭建之前可以先了解,届时可以顺利解决该问题。
【1】首先在Mgm客户端通过SHOW命令查看的时候
mysqld(API)总是不能同时在线,会出现如:
图 SQL节点连接不稳定
【2】每个SQL节点上面进行数据操作的时候均会变得巨慢无比
图 SQL 数据操作极慢
图操作数据库时间
【3】SQL节点持续报错
图 SQL节点报错
关闭防火墙之后:
图 SQL节点显示连接的NDBD节点
关于防火墙引起的问题已经提前声明了,在后面的配置中由此引起相同的问题只要关闭防火墙即可,所以在启动各个服务之前首先检查当前ipables状态。
假设mysql-cluster-gpl-7.2.10-linux2.6-x86_64.tar.gz已经下载完成并置于/tmp目录下方。
[root@mgmd tmp]# cat /etc/hosts
192.168.9.100 mgmd 192.168.9.101 ndbd01 192.168.9.102 ndbd02 192.168.9.201 mysqld01 192.168.9.202 mysqld02 |
[root@mgmd ~]# mkdir/opt/mysql_cluster/logs
[root@mgmd ~]# chown mysql.mysql /opt/mysql_cluster/logs/ -R
[root@mgmd ~]# cat/opt/mysql_cluster/config.ini
[NDBD DEFAULT] NoOfReplicas=2 [NDB_MGMD] NodeId=1 hostname=mgmd datadir=/opt/mysql_cluster/logs [NDBD] NodeId=11 hostname=ndbd01 datadir=/opt/mysql_cluster/ndbdata [NDBD] NodeId=12 hostname=ndbd02 datadir=/opt/mysql_cluster/ndbdata [MYSQLD] NodeId=21 hostname=mysqld01 [MYSQLD] NodeId=22 hostname=mysqld02 |
图mgmd节点启动成功并加入集群
图查看生成的日志文件以及Pid文件
创建mysql用户,解压重命名集群目录与mgmd一致。
其配置文件有所不同
图两个ndbd节点的配置文件,一致
[root@ndbd01~]# mdkir /opt/mysql_cluster/ndbdata/
[root@ndbd01~]#chown �CR mysql.mysql /opt/mysql_cluster/ndbdata/
首次启动ndbd节点的时候需要加上--initial-start参数,表示初始化启动过程,后面的操作均不需要再次执行,否则会摧毁一切数据。
图启动ndbd节点
图查看启动生成的文件
配置sqld节点的时候,配置文件my.cnf尽量放置于/etc/目录下,否则通过mysql.server脚本启动的时候会报错.
[root@mysqld01 ~]#/opt/mysql_cluster/scripts/mysql_install_db \
--user=mysql --basedir=/opt/mysql_cluster/--datadir=/opt/mysql_cluster/data/
图初始化数据库文件
[root@mysqld01 ~]# cat /etc/my.cnf
[mysqld] ndbcluster ndb-connectstring=mgmd [mysql_cluster] ndb-connectstring=mgmd |
[root@mysqld01 ~]# cat/opt/mysql_cluster/support-files/mysql.server |grep -v grep |grep basedir |grep-v '#'|head -n 2
basedir=/opt/mysql_cluster datadir=$basedir/data |
图将mysql.server设置为系统服务
图查看mysql进程状态
图查看数据库
另外一个节点mysqd02上面的操作跟mysqld01上完全一致。全部启动成功之后,登录管理节点查看集群中所有节点状态。
图集群所有节点状态
根据以上的所有操作,简单的mysql集群系统已经基本搭建完成,均可正常工作。
下面测试数据同步测试以及故障测试。
[root@mysqld01~]# /opt/mysql_cluster/bin/mysql -e "setpassword=password('passw0rd')"
[root@mysqld02~]# /opt/mysql_cluster/bin/mysql -e "setpassword=password('passw0rd')"
[root@mysqld01~]# /opt/mysql_cluster/bin/mysql -uroot-ppassw0rd --prompt="\\u@\\h:\\d \\r:\\m:\\s >"
root@localhost:(none) 08:48:31 > CREATE DATABASE clovemfong; Query OK, 1 row affected (0.04 sec) root@localhost:(none) 08:48:31 > CREATE TABLE clovemfong.t1 (id int auto_increment,name varchar(30),PRIMARY KEY(id)) ENGINE=NDBCLUSTER; Query OK, 0 rows affected (0.02 sec) |
[root@mysqld02~]# /opt/mysql_cluster/bin/mysql -uroot-ppassw0rd --prompt="\\u@\\h:\\d \\r:\\m:\\s >"
图在mysqld02节点查看被创建的表
图插入数据并查看
图删除数据,查看两边数据显示
从4.1的测试我们得知在Mysql集群中,实现了任何SQL节点操作数据的一致性,当然前提是所有的表存储引擎需要设置为NDBCLUSTER。
本节将对集群中可能出现的可能做个排列组合进行说明,其实想想也就知道了。
【1】mysqld01 挂掉
这样的情况对数据完全没有影响,因为数据时保存在ndbd节点上面的,该类节点挂掉之后,应用程序仅仅需要将请求转发给另一mysqld节点即可。
【2】ndbd01 挂掉
这样的情况,仅仅是数据丢掉了一个副本而已,也不会有影响。
【3】mysqld01 && ndbd01同时挂掉
此类情况对数据而言少了一个副本,mysqld节点少一个,不影响。
此时写入数据的时候,会出现两种情况,ndbd01此时成功启动了,这种情况下面,ndbd02会立即同步ndbd01上面的数据,此时ndbd02如果挂了,不会影响数据的一致性,第二种情况,写完了数据,在ndbd01重启启动完成之前ndbd02也挂了,此时刚刚写好的数据必定丢失,不过这种情况不多见,这种情况就相当于连个ndbd同时不工作了。
【4】mysqld01 && mysql02 && ndbd01 同时挂掉。
在这样的情况下面,只要重启启动好某个mysqld节点或者添加新的mysqld节点即可,关于ndbd节点,同样也是,要么重启ndbd01节点,要么添加一台新的节点进入集群。由此引申如何动态添加一个新的节点到集群中去了。
所有的集群系统中都会涉及到一个动态添加节点的问题,要在保证服务不被打断的情况下面做到节点的动态添加是一个集群必备的功能。
在网络上面能够找到不少关于数据节点的添加,确实在实际生产环境中,动态添加数据节点是一个必须得面对的问题,而平时负载较大的mysqld节点也有面临宕机的情况,所以考虑mysqld节点的动态添加也是有必要的。
4.3.1 动态加入mysqld节点
【1】修改/etc/hosts文件并同步到所有节点
图加入新节点
【2】修改config.ini文件
图加入新节点信息
【3】停止管理节点
图停止Node 1―mgmd
【5】重启加载配置文件
图重新加载管理节点配置文件
【6】轮流重启ndbd节点
图轮流重启ndbd节点
【7】启动新的mysqld节点
按照之前mysqld的启动流程启动即可
[root@mysqld03 ~]# /opt/mysql_cluster/scripts/mysql_install_db\
--user=mysql --basedir=/opt/mysql_cluster/--datadir=/opt/mysql_cluster/data/
【8】查看状态
4.3.2 动态加入ndbd节点
根据实际项目,我们添加ndbd节点的场景可能有所不同,可以分为两种:
1.添加一个或者多个节点作为新的副本,即加入原来的组中
2.添加2个或者其他偶数级别的节点作为新的组,用于分区使用。
一般从网络上面的文章来看第二种比较多,不过个人觉得第一种的情况非常大,因为很有可能我只想添加一台新的存储节点。
我们第一种开始进行操作:
4.3.2.1 加入一个节点作为新的副本
关于这个问题,我通过实验已经得出结论。
1.必须离线状态才可以进行该操作,即关闭整个集群
2.原来ndbd节点由于检测到副本数[NoOfReplicas]需要修改重新启动的时候必须加initial参数,也就意味着摧毁所有原来的数据
从以上两点可以知晓,如果需要这样得添加节点,我们需要先进行数据的备份,然后再最终在所有的节点上面进行恢复才行。
4.3.2 加入偶数节点作为新的分组,如添加2个
注意:剩余的就不贴了,有点麻烦,我将文档传到附件中,有兴趣继续的朋友可以download,呵呵