对于一个早期的商城系统来说,由于业务量不太大,数据承载压力不高,我们可以将所有的数据放在一台MySQL服务器上,此时的数据库架构就类似于下图所示。
随着业务量的不断增加,数据库的压力越来越大,此时我们可以将MySQL做成主从复制集群,使用Mycat完成MySQL的读写分离,其中,MySQL主库作为写库,MySQL从库作为读库,此时的数据库架构可以如下图所示,
关于Mycat如何实现MySQL读写分离,大家可以参考《Mycat之——Mycat在MySQL主从复制基础上实现读写分离》一文。
又过了一段时间,随着业务量的上涨,我们发现对于商城业务来说,不同的业务所承受的压力不同,访问的频次也是有区别的。此时,我们就会思考能否将商城中不同的业务的数据独立出来,做成单独的数据库,并且对于上层的应用程序来说,访问这些数据库时,仍旧像访问同一个数据库一样。此时,我们就会想到数据库的垂直切分。
我们可以将商城数据库分为用户数据库、商品数据库、订单数据库和仓配数据库。由于在商城业务中,订单业务和仓配业务需要时刻进行交互,前期,我们就可以将订单业务和仓配业务的数据库合并为一个数据库。最终,我们可以将商城业务划分为用户业务、商品业务和订单业务。
此时,我们的商城数据库架构可以如下图所示。
其中,对于上图中的每一部分,我们都可以做成高可用模式,有关高可用模式大家可以参考如下文章。
《Mycat之——Mycat在MySQL主从复制基础上实现读写分离》
《Mycat之——Mycat集群部署(基于HAProxy + Mycat)》
《Mycat之——高可用负载均衡集群的实现(HAProxy + Keepalived + Mycat)》
本文,我们就基于一个简单的商城数据库来实现MySQL的垂直分库。
我们可以将服务器的规划简化成下面的表格所示。
主机名 | IP地址 | 安装的服务 | 业务数据库 |
---|---|---|---|
binghe151 | 192.168.175.151 | Mycat | shop(虚拟库) |
binghe152 | 192.168.175.152 | MySQL | order_db(实体订单库) |
binghe153 | 192.168.175.153 | MySQL | product_db(实体商品库) |
binghe154 | 192.168.175.154 | MySQL | customer_db(实体用户库) |
如果需要安装MySQL 8.x版本,则可以参考《MySQL之——源码编译MySQL8.x+升级gcc+升级cmake(亲测完整版)》
如果需要安装MySQL 5.x版本,则可以参考《MySQL之——CentOS6.5 编译安装MySQL5.6或5.7》
我这里,安装的是MySQL 8.x版本。安装其他的版本也可以。
在binghe152服务器上创建订单库,SQL语句如下所示。
create database if not exists order_db;
在binghe153服务器上创建商品库,SQL语句如下所示。
create database if not exists product_db;
在binghe154服务器上创建用户库,SQL语句如下所示。
create database if not exists customer_db;
有关各数据库的数据导入,大家可以下载【商城数据库SQL脚本文件.rar】文件,解压后,分别导入到相应的数据库即可。
分别在三个MySQL数据库中创建Mycat连接MySQL的用户,如果大家安装的是MySQL 8.x版本,则在MySQL命令行执行如下命令
CREATE USER 'mycat'@'192.168.175.%' IDENTIFIED BY 'mycat';
ALTER USER 'mycat'@'192.168.175.%' IDENTIFIED WITH mysql_native_password BY 'mycat';
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'mycat'@'192.168.175.%';
FLUSH PRIVILEGES;
如果大家安装的是MySQL 5.x版本,则在MySQL命令行执行如下命令。
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'mycat'@'192.168.175.%' IDENTIFIED BY 'mycat';
FLUSH PRIVILEGES;
我这里,下载的是Mycat的1.6.7.4 release版本,连接地址为:http://dl.mycat.io/1.6.7.4/ 。 下载后直接解压到binghe151服务器的/usr/local/mycat目录下即可。
这里,需要注意的是,Mycat是使用Java语言编写的,所以安装Mycat时,需要安装JDK,大家可以按照如下方式安装JDK
到JDK官网下载JDK 1.8版本,JDK1.8的下载地址为:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html。
我这里下载的JDK安装包版本为:jdk-8u212-linux-x64.tar.gz,如果JDK版本已更新,读者下载对应的版本即可。
将下载的JDK安装包解压到/usr/local/jdk1.8.0_212目录下。并配置JDK和Mycat的系统环境变量,如下所示。
vim /etc/profile
MYCAT_HOME=/usr/local/mycat
JAVA_HOME=/usr/local/jdk1.8.0_212
CLASS_PATH=.:$JAVA_HOME/lib
PATH=$JAVA_HOME/bin:$MYCAT_HOME/bin:$PATH
export JAVA_HOME MYCAT_HOME CLASS_PATH PATH
使系统环境变量生效,如下所示。
source /etc/profile
由于Mycat垂直分库不需要配置Mycat的分片规则,也就不需要配置rule.xml文件,此时只需要配置schema.xml文件和server.xml文件。
编辑后的schema.xml文件内容如下所示。
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="shop" checkSQLschema="false" sqlMaxLimit="1000">
schema>
<dataNode name="ordb" dataHost="binghe152" database="order_db" />
<dataNode name="prodb" dataHost="binghe153" database="product_db" />
<dataNode name="custdb" dataHost="binghe154" database="customer_db" />
<dataHost name="binghe152" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()heartbeat>
<writeHost host="binghe52" url="192.168.175.152:3306" user="mycat" password="mycat"/>
dataHost>
<dataHost name="binghe153" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()heartbeat>
<writeHost host="binghe53" url="192.168.175.153:3306" user="mycat" password="mycat"/>
dataHost>
<dataHost name="binghe154" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()heartbeat>
<writeHost host="binghe54" url="192.168.175.154:3306" user="mycat" password="mycat"/>
dataHost>
mycat:schema>
由于地域信息表region_info在每个业务库中可能都需要使用到,此时,我们可以将地域信息表region_info配置成全局表,将其配置到每个业务库中。
如下所示。
另外,还需要在每个实体业务库中,创建地域信息表region_info,并将数据导入到region_info表。此时,通过Mycat管理region_info表时,数据会分别同步到每个业务数据库中。
注意:当将某个数据表在Mycat中配置成全局表时,只有通过Mycat对这个表进行增加、删除和修改操作时,数据才会同步到每个实体数据库中。
编辑后的server.xml文件如下所示。
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="useHandshakeV10">1property>
<property name="defaultSqlParser">druidparserproperty>
<property name="serverPort">3307property>
<property name="managerPort">3308property>
<property name="nonePasswordLogin">0property>
<property name="bindIp">0.0.0.0property>
<property name="charset">utf8mb4property>
<property name="frontWriteQueueSize">2048property>
<property name="txIsolation">2property>
<property name="processors">2property>
<property name="idleTimeout">1800000property>
<property name="sqlExecuteTimeout">300property>
<property name="useSqlStat">0property>
<property name="useGlobleTableCheck">0property>
<property name="sequenceHandlerType">2property>
<property name="defaultMaxLimit">1000property>
<property name="maxPacketSize">104857600property>
system>
<user name="mycat" defaultAccount="true">
<property name="usingDecrypt">1property>
<property name="password">cTwf23RrpBCEmalp/nx0BAKenNhvNs2NSr9nYiMzHADeEDEfwVWlI6hBDccJjNBJqJxnunHFp5ae63PPnMfGYA==property>
<property name="schemas">shopproperty>
user>
mycat:server>
其中,在server.xml中,使用了Mycat对密码的加密功能。user标签下的password标签的值为登录Mycat的密码,此值使用Mycat提供的加密类对密码明文进行了加密。此类存在于Mycat安装目录下的lib目录下的Mycat-server-xxx-release.jar中的io.mycat.util.DecryptUtil类,可以使用如下命令对密码进行加密。
java java -cp /usr/local/mycat/lib/Mycat-server-xxx-release.jar io.mycat.util.DecryptUtil 0:mycat:mycat
其中0:mycat:mycat为运行Jar包的参数,0表示应用程序连接Mycat时使用密文密码;第一个mycat代表连接Mycat的用户名,也就是说为哪个用户的密码加密;第二个mycat代表需要加密的密码。
加密后的结果数据如下所示
cTwf23RrpBCEmalp/nx0BAKenNhvNs2NSr9nYiMzHADeEDEfwVWlI6hBDccJjNBJqJxnunHFp5ae63PPnMfGYA==
即user标签下的password属性的值。
如果按照上述方式为连接Mycat的密码加密后,需要在user标签下配置如下选项,否则无法正确连接Mycat。
<property name="usingDecrypt">1property>
另外,在需要使用MySQL 8.x的mysql命令连接Mycat时,在server.xml文件的system标签下必须配置如下选项。
<property name="useHandshakeV10">1property>
<property name="defaultSqlParser">druidparserproperty>
否则,MySQL 8.x的mysql命令连接Mycat会失败。
使用MySQL 8.x中的mysql命令连接Mycat,如下所示。
[root@binghe151 ~]# mysql -umycat -pmycat -h192.168.175.151 -P3307 --default-auth=mysql_native_password
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.29-mycat-xxx-release-20200228205020 MyCat Server (OpenCloudDB)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
使用MySQL8.x中的mysql命令连接Mycat时,需要注意的是要在mysql命令后面添加–default-auth=mysql_native_password选项。如果使用的是MySQL 5.x的mysql命令行,则不需要在命令后面添加–default-auth=mysql_native_password选项。
接下来,查看下Mycat下的逻辑库和逻辑表,如下所示。
mysql> SHOW DATABASES;
+----------+
| DATABASE |
+----------+
| shop |
+----------+
1 row in set (0.00 sec)
mysql> USE shop;
Database changed
mysql> SHOW TABLES;
+-----------------------+
| Tables in shop |
+-----------------------+
| customer_balance_log |
| customer_inf |
| customer_level_inf |
| customer_login |
| customer_login_log |
| customer_point_log |
| order_cart |
| order_customer_addr |
| order_detail |
| order_master |
| product_brand_info |
| product_category |
| product_comment |
| product_info |
| product_pic_info |
| product_supplier_info |
| region_info |
| serial |
| shipping_info |
| warehouse_info |
| warehouse_proudct |
+-----------------------+
21 rows in set (0.00 sec)
mysql> SELECT product_id, product_code, product_name FROM product_info LIMIT 10;
+------------+------------------+---------------------------------------+
| product_id | product_code | product_name |
+------------+------------------+---------------------------------------+
| 1 | 3700000000000001 | [Columbia]打底裤示例商品-1 |
| 2 | 3600000000000001 | [TheNorthFace]小脚裤示例商品-1 |
| 3 | 3500000000000001 | [李宁]九分裤示例商品-1 |
| 4 | 3400000000000001 | [LOWA]哈伦裤示例商品-1 |
| 5 | 3300000000000001 | [JACK&JONES]连体裤示例商品-1 |
| 6 | 3200000000000001 | [诺诗兰]牛仔裤示例商品-1 |
| 7 | 3100000000000001 | [骆驼]休闲裤示例商品-1 |
| 8 | 3000000000000001 | [金狐狸]风衣示例商品-1 |
| 9 | 2900000000000001 | [Columbia]小西装示例商品-1 |
| 10 | 2800000000000001 | [李宁]外套示例商品-1 |
+------------+------------------+---------------------------------------+
10 rows in set (0.01 sec)
至此,就完成了基于Mycat对MySQL的垂直分库操作。