业务不断地在增加,集群分片中的数据也会随着时间的推移而增长,其中有至关一部分的数据是不多被使用的,例如几年前的订单记录、交易记录、商品评论等数据。这部分数据就称之为冷数据,与之相反常常被使用的数据则称之为热数据。node
咱们都知道当MySQL的单表数据量超过两千万时,读写性能就会急剧降低。若是其中存储的大部分都是高价值的热数据还好说,能够花费资金去扩展集群分片,由于这些数据能够带来收益。但若是是低价值的冷数据,就不必去花这个钱了。mysql
因此咱们要将冷数据从集群分片中剥离出来,存储至专门的归档数据库中,以腾出存储空间、减轻集群分片的存储压力。让集群分片尽可能只存储热数据,维持一个较好的读写性能,而没必要浪费存储空间在冷数据上:算法
在归档数据库上不适合使用InnoDB引擎,由于InnoDB的瞬时写入性能不高。一般会采用Percona出品的TokuDB做为归档数据库的存储引擎。由于该引擎具备以下特色:sql
上一小节介绍了冷热数据分离的概念,本小节咱们来搭建一个用于归档冷数据的高可用Replication集群。虽然是归档库,但也得让其具备高可用性,毕竟在实际的企业中是不容许数据库出现单点故障的。并且归档库中的数据也不是不会被使用到,只不过是使用概率不高而已。数据库
本文中的Replication集群架构设计以下:vim
所谓Replication集群就是咱们常说的主从架构,在Replication集群中,节点分为Master和Slave两种角色。Master主要是提供写服务,Slave则提供读服务,而且一般Slave会被设置为read_only
。后端
主从节点之间的数据同步是异步进行的,Slave使用一个线程监听Master节点的binlog
日志,当Master的binlog
日志发生变化时,该线程就会读取Master的binlog
日志内容并写入到本地的relay_log
中。而后mysql进程会定时读取relay_log
并将数据写入到本地的binlog
文件,这样就实现了主从之间的数据同步。以下图所示:浏览器
为了保证Replication集群的高可用,咱们须要让两个数据库节点之间互为主从关系,实现双向的数据同步。这样才能在主节点挂掉时进行主从切换,不然主节点在恢复后不会向从节点同步数据,会致使节点之间的数据不一致:bash
接下来开始准备集群搭建的前置环境,首先须要建立4台虚拟机,其中两台安装Percona Server作Replication集群,两台安装Haproxy和Keepalived作负载均衡和双机热备:服务器
角色 | Host | IP |
---|---|---|
Haproxy+Keepalived | HA-01 | 192.168.190.135 |
Haproxy+Keepalived | HA-02 | 192.168.190.143 |
Percona Server | node-A | 192.168.190.142 |
Percona Server | node-B | 192.168.190.131 |
每台虚拟机的配置以下:
环境版本说明:
以前说了InnoDB由于其特性不适合做为归档数据库的存储引擎,而应采用TokuDB。TokuDB能够安装在任意MySQL的衍生版本上,本文采用的是Percona Server这个MySQL衍生版做为演示。
我这里已经事先在192.168.190.142
和192.168.190.131
两个虚拟机上安装好了Percona Server,如不了解其安装方式的话,可参考:安装Percona Server数据库(in CentOS 8)。接下来,咱们就开始为Percona Server安装TokuDB。
首先,在安装TokuDB前确保系统中已有jemalloc库,没有的话可使用以下命令安装:
[root@node-A ~]# yum install -y jemalloc [root@node-A ~]# ls /usr/lib64/ |grep jemalloc # 库文件所在路径 libjemalloc.so.1 [root@node-A ~]#
在配置文件中添加jemalloc库文件所在路径的配置:
[root@node-A ~]# vim /etc/my.cnf ... [mysql_safe] malloc-lib=/usr/lib64/libjemalloc.so.1
完成配置文件的修改后,重启数据库服务:
[root@node-A ~]# systemctl restart mysqld
为了保证TokuDB的写入性能,咱们须要调整一下Linux系统的大页内存管理的设置,命令以下:
# 采用动态分配内存而不是预先分配内存 [root@node-A ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled # 开启内存的碎片整理 [root@node-A ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
经过官方提供的yum
仓库安装TokuDB引擎:
[root@node-A ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm [root@node-A ~]# percona-release setup ps80 [root@node-A ~]# yum install -y percona-server-tokudb.x86_64
接着使用ps-admin
命令将TokuDB引擎安装到MySQL上:
[root@node-A ~]# ps-admin --enable-tokudb -uroot -p
重启数据库服务:
[root@node-A ~]# systemctl restart mysqld
数据库重启完成后,再执行一次ps-admin
命令以激活TokuDB引擎:
[root@node-A ~]# ps-admin --enable-tokudb -uroot -p
最后使用show engines;
语句验证一下MySQL上是否已成功安装了TokuDB引擎:
首先在两个节点上分别建立用于同步的数据库帐户:
create user 'backup'@'%' identified by 'Abc_123456'; grant super, reload, replication slave on *.* to 'backup'@'%'; flush privileges;
而后修改MySQL配置文件:
[root@node-A ~]# vim /etc/my.cnf [mysqld] # 设置节点的id server_id=101 # 开启binlog log_bin=mysql_bin # 开启relay_log relay_log=relay_bin
另一个节点也是一样的配置,只不过server_id
不能是同样的:
[root@node-B ~]# vim /etc/my.cnf [mysqld] server_id=102 log_bin=mysql_bin relay_log=relay_bin
修改完配置文件后,重启MySQL服务:
[root@node-A ~]# systemctl restart mysqld [root@node-B ~]# systemctl restart mysqld
node-B
对node-A
的主从关系进入node-B
的MySQL命令行终端,分别执行以下语句:
mysql> stop slave; -- 中止主从同步 mysql> change master to master_host='192.168.190.142', master_port=3306, master_user='backup', master_password='Abc_123456'; -- 配置Master节点的链接信息 mysql> start slave; -- 启动主从同步
使用show slave status\G;
语句查看主从同步状态,Slave_IO_Running
和Slave_SQL_Running
的值均为Yes
才能表示主从同步状态是正常的:
node-A
对node-B
的主从关系为了实现双向同步,node-A
和node-B
须要互为主从关系,因此还须要配置node-A
对node-B
的主从关系。进入node-A
的MySQL命令行终端,分别执行以下语句,注意这里的master_host
须要为node-B
的ip:
mysql> stop slave; -- 中止主从同步 mysql> change master to master_host='192.168.190.131', master_port=3306, master_user='backup', master_password='Abc_123456'; -- 配置Master节点的链接信息 mysql> start slave; -- 启动主从同步
一样配置完成后,使用show slave status\G;
语句查看主从同步状态,Slave_IO_Running
和Slave_SQL_Running
的值均为Yes
才能表示主从同步状态是正常的:
配置好两个节点的主从同步关系以后,咱们就算是完成了Replication集群的搭建。接下来咱们在任意一个节点建立一张归档表,看看两个节点之间是否能正常同步数据。具体的建表SQL以下:
create table t_purchase_201909 ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '进货价格', purchase_num int unsigned not null comment '进货数量', purchase_sum decimal(10, 2) not null comment '进货总价', purchase_buyer int unsigned not null comment '采购者', purchase_date timestamp not null default current_timestamp comment '采购日期', company_id int unsigned not null comment '进货企业的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) engine=TokuDB comment '2019年9月的进货数据归档表';
我这里是可以正常进行同步的,如图两个节点都能看到这张表:
到此为止,咱们就完成了Replication集群的搭建及测试。接下来就是得让Replication集群具备高可用的特性,这就轮到Haproxy上场了。Haproxy是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件。使用Haproxy能够对MySQL集群进行负载均衡,赋予集群高可用性并发挥集群的性能。
Haproxy因为是老牌的负载均衡组件了,因此CentOS的yum
仓库中自带有该组件的安装包,安装起来就很是简单。安装命令以下:
[root@HA-01 ~]# yum install -y haproxy
安装完成后,编辑Haproxy的配置文件,添加监控界面及须要代理的数据库节点配置:
[root@HA-01 ~]# vim /etc/haproxy/haproxy.cfg # 在文件的末尾添加以下配置项 # 监控界面配置 listen admin_stats # 绑定的ip及监听的端口 bind 0.0.0.0:4001 # 访问协议 mode http # URI 相对地址 stats uri /dbs # 统计报告格式 stats realm Global\ statistics # 用于登陆监控界面的帐户密码 stats auth admin:abc123456 # 数据库负载均衡配置 listen proxy-mysql # 绑定的ip及监听的端口 bind 0.0.0.0:3306 # 访问协议 mode tcp # 负载均衡算法 # roundrobin:轮询 # static-rr:权重 # leastconn:最少链接 # source:请求源ip balance roundrobin # 日志格式 option tcplog # 须要被负载均衡的主机 server node-A 192.168.190.142:3306 check port 3306 weight 1 maxconn 2000 server node-B 192.168.190.131:3306 check port 3306 weight 1 maxconn 2000 # 使用keepalive检测死链 option tcpka
因为配置了3306
端口用于TCP
转发,以及4001
做为Haproxy监控界面的访问端口,因此在防火墙上须要开放这两个端口:
[root@HA-01 ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanent [root@HA-01 ~]# firewall-cmd --zone=public --add-port=4001/tcp --permanent [root@HA-01 ~]# firewall-cmd --reload
完成以上步骤后,启动Haproxy服务:
[root@HA-01 ~]# systemctl start haproxy
而后使用浏览器访问Haproxy的监控界面,初次访问会要求输入用户名密码,这里的用户名密码就是配置文件中所配置的:
登陆成功后,就会看到以下页面:
Haproxy的监控界面提供的监控信息也比较全面,在该界面下,咱们能够看到每一个主机的链接信息及其自身状态。当主机没法链接时,Status
一栏会显示DOWN
,而且背景色也会变为红色。正常状态下的值则为UP
,背景色为绿色。
另外一个Haproxy节点也是使用以上的步骤进行安装和配置,这里就再也不重复了。
Haproxy服务搭建起来后,咱们来使用远程工具测试一下可否经过Haproxy正常链接到数据库。以下:
链接成功后,在Haproxy上执行一些SQL语句,看看可否正常插入数据和查询数据:
咱们搭建Haproxy是为了让Replication集群具有高可用的,因此最后测试一下Replication集群是否已具有有高可用性,首先将其中一个节点给停掉:
[root@node-B ~]# systemctl stop mysqld
此时,从Haproxy的监控界面中,能够看到node-B
这个节点已经处于下线状态了:
如今集群中还剩一个节点,而后咱们到Haproxy上执行一些SQL语句,看看是否还能正常插入数据和查询数据:
从测试结果能够看到,插入和查询语句依旧是能正常执行的。也就是说即使此时关掉一个节点整个数据库集群还可以正常使用,说明如今Replication集群是具备高可用性了。
实现了Replication集群的高可用以后,咱们还得实现Haproxy的高可用,由于Haproxy做为一个负责接收客户端请求,并将请求转发到后端数据库集群的入口,不可避免的须要具有高可用性。不然Haproxy出现单点故障,就没法访问被Haproxy代理的全部数据库集群节点了,这对整个系统的影响是十分巨大的。
在同一时间只须要存在一个可用的Haproxy,不然客户端就不知道该连哪一个Haproxy了。这也是为何要采用Keepalived的虚拟IP的缘由,这种机制能让多个节点互相接替时依旧使用同一个IP,客户端至始至终只须要链接这个虚拟IP。因此实现Haproxy的高可用就要轮到Keepalived出场了,在安装Keepalived以前须要开启防火墙的VRRP协议:
[root@HA-01 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --protocol vrrp -j ACCEPT [root@HA-01 ~]# firewall-cmd --reload
而后就可使用yum
命令安装Keepalived了:
[root@HA-01 ~]# yum install -y keepalived
安装完成后,编辑keepalived的配置文件:
[root@HA-01 ~]# mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak # 不使用自带的配置文件 [root@HA-01 ~]# vim /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state MASTER interface ens32 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.190.101 } }
配置说明:
state MASTER
:定义节点角色为master,当角色为master时,该节点无需争抢就能获取到VIP。集群内容许有多个master,当存在多个master时,master之间就须要争抢VIP。为其余角色时,只有master下线才能获取到VIPinterface ens32
:定义可用于外部通讯的网卡名称,网卡名称能够经过ip addr
命令查看virtual_router_id 51
:定义虚拟路由的id,取值在0-255,每一个节点的值须要惟一,也就是不能配置成同样的priority 100
:定义权重,权重越高就越优先获取到VIPadvert_int 1
:定义检测间隔时间为1秒authentication
:定义心跳检查时所使用的认证信息
auth_type PASS
:定义认证类型为密码auth_pass 123456
:定义具体的密码virtual_ipaddress
:定义虚拟IP(VIP),须要为同一网段下的IP,而且每一个节点须要一致完成以上配置后,启动keepalived服务:
[root@HA-01 ~]# systemctl start keepalived
当keepalived服务启动成功,使用ip addr
命令能够查看到网卡绑定的虚拟IP:
另外一个节点也是使用以上的步骤进行安装和配置,这里就再也不重复了。不过要注意virtual_router_id
不能配置成同样的,而virtual_ipaddress
则必须配置成同一个虚拟ip。
以上咱们完成了Keepalived的安装与配置,最后咱们来测试Keepalived服务是否正常可用,以及测试Haproxy是否已具备高可用性。
首先,在其余节点上测试虚拟IP可否正常ping
通,若是不能ping
通就须要检查配置了。如图,我这里是能正常ping
通的:
常见的虚拟IP ping不通的状况:
确认可以从外部ping
通Keepalived的虚拟IP后,使用Navicat测试可否经过虚拟IP链接到数据库:
链接成功后,执行一些语句测试可否正常插入、查询数据:
到此就基本没什么问题了,最后测试一下Haproxy的高可用性,将其中一个Haproxy节点上的Keepalived和Haproxy服务给关掉:
[root@HA-01 ~]# systemctl stop keepalived [root@HA-01 ~]# systemctl stop haproxy
而后再次执行执行一些语句测试可否正常插入、查询数据,以下能正常执行表明Haproxy节点已具备高可用性:
最后将全部的服务恢复成运行状态,验证中止的节点恢复以后数据是不是一致的。以下,我这里两个Replication节点的数据都是一致的:
到此为止,咱们就完成了高可用Replication集群的搭建。接下来就是实践如何将大量的冷数据从PXC集群分片中剥离出来并归档到Replication集群中,我这里有两个PXC集群分片:
每一个分片里都有一张t_purchase
表,其建表SQL以下。
create table t_purchase ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '进货价格', purchase_num int unsigned not null comment '进货数量', purchase_sum decimal(10, 2) not null comment '进货总价', purchase_buyer int unsigned not null comment '采购者', purchase_date timestamp not null default current_timestamp comment '采购日期', company_id int unsigned not null comment '进货企业的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) comment '进货表';
每一个分片合计共存储了100w条进货数据:
其中有60w条进货数据的采购日期都是2019-11-01
以前的:
如今的需求是将2019-11-01
以前的数据都剥离出来进行归档,这要如何实现呢?本身写代码确定是比较麻烦的,好在Percona工具包里提供了一个用于归档数据的工具:pt-archiver
,使用该工具能够很轻松的完成数据归档,免除了本身写归档程序的麻烦。pt-archiver
主要有两个用途:
想要使用pt-archiver
首先得安装Percona工具包:
[root@node-A ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm [root@node-A ~]# percona-release enable ps-80 release [root@node-A ~]# yum install -y percona-toolkit
安装完成后,验证pt-archiver
命令是否可用:
[root@node-A ~]# pt-archiver --version pt-archiver 3.1.0 [root@node-A ~]#
接着就可使用pt-archiver
命令进行数据的归档了,首先须要在Replication集群中建立一张归档表,表名以归档的数据日期为后缀,存储引擎使用TokuDB。具体的建表SQL以下:
create table t_purchase_201910 ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '进货价格', purchase_num int unsigned not null comment '进货数量', purchase_sum decimal(10, 2) not null comment '进货总价', purchase_buyer int unsigned not null comment '采购者', purchase_date timestamp not null default current_timestamp comment '采购日期', company_id int unsigned not null comment '进货企业的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) engine=TokuDB comment '2019年10月的进货数据归档表';
而后使用pt-archiver
命令完成数据归档,以下示例:
[root@node-A ~]# pt-archiver --source h=192.168.190.100,P=3306,u=admin,p=Abc_123456,D=test,t=t_purchase --dest h=192.168.190.101,P=3306,u=archive,p=Abc_123456,D=test,t=t_purchase_201910 --no-check-charset --where 'purchase_date < "2019-11-01 0:0:0"' --progress 50000 --bulk-delete --bulk-insert --limit=100000 --statistics
pt-archiver
命令是使用load data
语句进行数据导入的,因此要确保MySQL开启了local_infile
。若是没有开启的话归档数据会失败,可使用set global local_infile = 'ON';
语句来开启local_infile
。命令参数说明:
--source
:指定从哪一个数据库读取数据--dest
:指定将数据归档至哪一个数据库--no-check-charset
:不检查数据的字符集--where
:指定将哪些数据进行归档,在本例中就是将2019-09-11
以前的数据进行归档--progress
:指定当归档完多少条数据时打印一次状态信息--bulk-delete
:指定批量删除归档数据。数据的删除有事务保证,不会出现未归档成功就将数据删除了的状况--bulk-insert
:指定批量写入归档数据--limit
:指定每次归档多少条数据--statistics
:归档数据完成后打印统计信息等待大约15分钟左右数据就归档完成了,输出的统计信息以下:
此时在Replication集群上能够看到那60w数据都已经存储到了归档表中:
而本来的PXC集群中就只剩40w数据了:
如此一来咱们就完成了冷热数据分离,并将大量的冷数据存储至指定的归档数据库中。
pt-archiver
能够导出大量数据并归档存储,且简便易行