主要内容:
分库分表概述、Mycat中间件部署、分片规则(枚举法、求模法、全局表)
一、分库分表概述
关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间。分库分表(Sharding)是一种数据库架构设计技术,用于解决单个数据库或单个表的数据量过大、性能瓶颈和扩展性问题。通过将数据分散到多个数据库实例或多个表中,分库分表可以提高系统的性能、可扩展性和可用性。
- 数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。
- 数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。
1、 分库分表基本概念
分库(Database Sharding)
- 将数据分散到多个数据库实例中,每个数据库实例存储部分数据。分库可以提高系统的并发处理能力和扩展性。
分表(Table Sharding)
- 将数据分散到多个表中,每个表存储部分数据。分表可以减少单个表的数据量,提高查询性能和写入性能。
2、 分库分表优点
提高性能: 通过将数据分散到多个数据库实例或多个表中,可以减少单个数据库或表的数据量,提高查询性能和写入性能。
提高可扩展性: 分库分表可以水平扩展系统,通过增加数据库实例或表的数量,提高系统的处理能力。
提高可用性: 分库分表可以提高系统的可用性,通过将数据分散到多个数据库实例或多个表中,避免单点故障。
**提高数据安全性:**分库分表可以提高数据的安全性,通过将数据分散到多个数据库实例或多个表中,避免数据集中存储带来的安全风险。
3、分库分表的实现方式
1)垂直(纵向)切分
垂直切分常见有垂直分库和垂直分表两种。垂直分库分表是将不同的业务模块或数据类型分散到不同的数据库实例或表中。
- a) 垂直分库
就是根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,将不同的业务模块分散到不同的数据库实例中。例如:
用户数据库:存储用户信息、用户登录信息等。
订单数据库:存储订单信息、订单详情等。
商品数据库:存储商品信息、商品分类等。
- b) 垂直分表
是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不同的数据类型分散到不同的表中。例如:
用户表:存储用户基本信息。
用户登录表:存储用户登录信息。
用户地址表:存储用户地址信息。
垂直切分的优点:
解决业务系统层面的耦合,业务清晰;
对不同业务的数据进行分级管理、维护、监控、扩展等;
高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈;
垂直切分的缺点:
部分表无法join多表连接,只能通过接口聚合方式解决,提升了开发的复杂度;
分布式事务处理复杂;
依然存在单表数据量过大的问题(需要水平切分);
2)水平(横向)切分
当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。水平切分分为水平分库和水平分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
- a) 水平分库
水平分库是将相同的数据类型分散到不同的数据库实例中。例如:
用户数据库1:存储用户ID为奇数的用户信息
用户数据库2:存储用户ID为偶数的用户信息
- b) 水平分表
水平分表是将相同的数据类型分散到不同的表中。例如:
用户表1:存储用户ID为奇数的用户信息
用户表2:存储用户ID为偶数的用户信息
注意:水平分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。水平切分后同一张表会出现在多个数据库/表中,每个库/表的内容不同。
水平切分的优点:
不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
应用端改造较小,不需要拆分业务模块
水平切分的缺点:
跨分片的事务一致性难以保证
跨库的join关联查询性能较差
数据多次扩展难度和维护量极大
4、分库分表的策略
1)哈希分片(Hash Sharding)
- 哈希分片是将数据按照某个字段的哈希值分散到不同的数据库实例或表中。例如,将用户ID的哈希值对数据库实例或表的数量取模,确定数据存储的位置。
2)范围分片(Range Sharding)
- 范围分片是将数据按照某个字段的范围分散到不同的数据库实例或表中。例如,将用户ID按照范围分散到不同的数据库实例或表中。
3)目录分片(Directory Sharding)
- 目录分片是通过一个中心化的目录服务来管理数据的分片信息,应用程序通过查询目录服务来确定数据存储的位置。
5、分库分表的工具和框架
数据库中间件
数据库中间件用于管理和优化分库分表的访问,提供连接池、负载均衡、读写分离、数据分片等功能。常见的数据库中间件包括:
- MyCat:一个开源的数据库中间件,支持 MySQL 和 MariaDB。
- ShardingSphere:一个开源的分布式数据库中间件,支持 MySQL、PostgreSQL 和 Oracle。
- Vitess:一个开源的数据库中间件,支持 MySQL。
分布式数据库
分布式数据库用于管理和存储分库分表的数据,提供分布式事务、数据一致性、查询优化等功能。常见的分布式数据库包括:
- TiDB:一个开源的分布式数据库,兼容 MySQL 协议。
- CockroachDB:一个开源的分布式数据库,兼容 PostgreSQL 协议。
- MongoDB:一个开源的分布式文档数据库,支持分片集群
二、MyCAT概述
MyCAT 是基于Java的一个开源的分布式数据库中间件,用于管理和优化分库分表的访问。它支持 MySQL 和 MariaDB,提供了连接池、负载均衡、读写分离、数据分片等功能,帮助用户构建高性能、高可用、可扩展的分布式数据库系统,为高并发环境的分布式存储提供解决方案。
MyCAT 支持分库分表,通过将数据分散到多个数据库实例或多个表中,提高系统的性能、可扩展性和可用性。
MyCAT 的主要功能:
连接池:管理数据库连接的创建、分配和释放,减少数据库连接的开销,提高系统的性能。
负载均衡:将客户端的请求分发到多个数据库实例上,均衡负载,提高系统的性能和可扩展性。
读写分离:将读操作和写操作分发到不同的数据库实例上,提高系统的读写性能和可用性。
数据分片:将数据按照某种策略(如哈希分片、范围分片)分散到多个数据库实例或多个表中,减少单个数据库或表的数据量,提高系统的性能和可扩展性。
分布式事务:支持两阶段提交(2PC)和 XA 事务,确保分布式事务的原子性、一致性、隔离性和持久性(ACID)。
高可用性:支持主从复制、故障检测、故障转移、容错机制等,确保系统的高可用性和可靠性。
监控和管理:包括性能监控、日志管理、配置管理等,帮助管理员监控和管理系统的运行状态。
适合数据大量写入的存储需求;支持MySQL、Oracle、Sqlserver、Mongodb等;
1、分片规则(算法):
MyCAT 提供了多种分片规则和算法,包括哈希分片、范围分片、目录分片、复合分片和自定义分片。这些分片规则可以根据业务需求进行配置,以实现数据的高效管理和访问。通过合理的分片规则设计和实现,可以充分发挥 MyCAT 的优势,提高系统的整体性能和可靠性。
- ① 枚举法(sharding-by-intfile)
- ② 固定分片(rule)
- ③ 范围约定(auto-sharding-long)
- ④ 求模法(mod-long)
- ⑤ 日期列分区法(sharding-by-date)
- ⑥ 通配取模(sharding-by-pattern)
- ⑦ ASCII码求模通配(sharding-by-prefixpattern)
- ⑧ 编程指定(sharding-by-substring)
- ⑨ 字符串拆分hash解析(sharding-by-stringhash)
- ⑩ 一致性hash(sharding-by-murmur)
2、工作过程
MyCAT 的工作过程可以分为多个步骤,从解析 SQL 命令到最终返回结果给客户端。以下是 MyCAT 处理 SQL 命令的详细步骤:
步骤1:解析 SQL 命令涉及到的表
当 MyCAT 接收到客户端发送的 SQL 命令时,首先会解析该 SQL 命令,识别出其中涉及到的表。这一步通常包括以下几个子步骤:
语法解析:
- MyCAT 使用 SQL 解析器对 SQL 命令进行语法解析,识别出 SQL 命令的类型(如 SELECT、INSERT、UPDATE、DELETE 等)。
表识别:
- 在解析过程中,MyCAT 会识别出 SQL 命令中涉及到的所有表。例如,对于 SELECT * FROM user WHERE id = 1,MyCAT 会识别出 user 表。
步骤2:查看表的配置,获取分片规则和分片字段
在识别出 SQL 命令涉及的表之后,MyCAT 会查看该表的配置信息,确定是否存在分片规则。如果存在分片规则,MyCAT 会进一步获取 SQL 命令中分片字段的值,并匹配分片函数,获得分片列表。
配置检查:
- MyCAT 会检查 schema.xml 配置文件,查看 user 表是否配置了分片规则。例如,user 表可能配置了按照 id 字段进行哈希分片。
分片字段提取:
- 如果存在分片规则,MyCAT 会从 SQL 命令中提取分片字段的值。例如,对于 SELECT * FROM user WHERE id = 1,MyCAT 会提取 id 字段的值 1。
分片函数匹配:
- MyCAT 会根据分片规则和分片字段的值,匹配相应的分片函数(如哈希函数、范围函数等),计算出数据应该存储在哪个分片(数据库实例或表)中。
分片列表生成:
- 根据分片函数的计算结果,MyCAT 会生成一个分片列表,列出所有需要访问的数据库实例或表。
步骤3:将 SQL 命令发往对应的数据库服务器执行
在获得分片列表之后,MyCAT 会将 SQL 命令发往对应的数据库服务器执行。
路由选择:
- MyCAT 根据分片列表,选择需要访问的数据库实例或表。例如,如果 id = 1 的数据存储在 db1 数据库的 user_0 表中,MyCAT 会将 SQL 命令发往 db1 数据库。
SQL 执行:
- MyCAT 将 SQL 命令发往选定的数据库实例或表,执行相应的操作(如查询、插入、更新、删除等)。
结果收集:
- 数据库实例执行完 SQL 命令后,会将结果返回给 MyCAT。MyCAT 会收集所有分片的结果数据。
步骤4:收集和处理所有分片结果数据,并返回给客户端
在所有分片的结果数据收集完毕后,MyCAT 会对这些结果数据进行处理,并将最终结果返回给客户端。
结果合并:
- 如果 SQL 命令是查询操作(如 SELECT),MyCAT 会将所有分片的结果数据进行合并,生成最终的查询结果。
结果处理:
- MyCAT 可能会对结果数据进行进一步的处理,如排序、过滤、聚合等,以满足 SQL 命令的要求。
结果返回:
- 最终,MyCAT 将处理后的结果数据返回给客户端,完成整个 SQL 命令的处理过程。
部署MyCAT服务示例:
实验网络拓扑:
- 服务器角色:mycat中间件服务器、mysql1、mysql2、mysql3数据库服务器
- ① mysql1:安装MySQL服务,启动服务,设置初始密码为:NSD2021@tedu.cn
- ② mysql2:安装MySQL服务,启动服务,设置初始密码为:NSD2021@tedu.cn
- ③ mysql3:安装MySQL服务,启动服务,设置初始密码为:NSD2021@tedu.cn
- ④ mycat:安装MySQL-client客户端(用来测试连接到3台数据库服务器的账户)
连接Mycat服务配置文件:/usr/local/mycat/conf/server.xml
数据分片配置文件:/usr/local/mycat/conf/schema.xml
分片规则配置文件:/usr/local/mycat/conf/rule.xml
服务日志文件:/usr/local/mycat/logs/mycat.log
Mycat服务端口:8066
步骤1:部署MyCAT服务器(mycat操作)
① 安装MyCAT所需的JAVA环境
bash
[root@mycat ~]# yum -y install java-1.8.0-openjdk
[root@mycat ~]# which java
/usr/bin/java
[root@mycat ~]# java -version
openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)
② 安装MyCAT软件包(参考:/linux-soft/4/mysql/Mycat...-linux.tar.gz)
bash
[root@mycat ~]# ls
anaconda-ks.cfg Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@mycat ~]# tar -xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz //解压
[root@mycat ~]# mv mycat/ /usr/local/
[root@mycat ~]# ls /usr/local/mycat/
③ 设置PATH环境变量脚本
bash
[root@mycat ~]# vim /etc/profile.d/mycat.sh
#!/bin/bash
export PATH=$PATH:/usr/local/mycat/bin/ //设置环境变量
[root@mycat ~]# source /etc/profile.d/mycat.sh //运行脚本
④ 修改配置文件server.xml:设置连接账号及逻辑库(保持默认配置即可)
sql
[root@mycat ~]# vim /usr/local/mycat/conf/server.xml
<user name="root"> //连接mycat服务时使用的用户名
<property name="password">123456</property> //连接mycat的用户密码
<property name="schemas">TESTDB</property> //逻辑库名
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property> //readOnly只读权限
</user>
补充:添加readOnly连接mycat服务后只有读记录的权限,不写则是可读可写
⑤ 修改配置文件schema.xml:配置数据分片
bash
[root@mycat ~]# vim /usr/local/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> //对TESTDB逻辑库下的表做分片存储
<!-- auto sharding by id (long) -->
<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
//解释:对travelrecord表做分片存储,存储在dn1,dn2,dn3三个不同的数据节点,采用规则auto-sharding-long
<!-- global table is auto cloned to all defined data nodes ,so can join
with any table whose sharding node is in the same data node -->
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<!-- random sharding using mod sharind rule -->
<table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
rule="mod-long" />
<!-- <table name="dual" primaryKey="ID" dataNode="dnx,dnoracle2" type="global"
needAddLimit="false"/> <table name="worker" primaryKey="ID" dataNode="jdbc_dn1,jdbc_dn2,jdbc_dn3"
rule="mod-long" /> -->
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" />
<table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile">
<childTable name="orders" primaryKey="ID" joinKey="customer_id"
parentKey="id">
<childTable name="order_items" joinKey="order_id"
parentKey="id" />
</childTable>
<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
parentKey="id" />
</table>
<!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
/> -->
</schema>
<!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
/> --> //定义数据库主机名及存储数据的库
<dataNode name="dn1" dataHost="mysql1" database="db1" />
<dataNode name="dn2" dataHost="mysql2" database="db2" />
<dataNode name="dn3" dataHost="mysql3" database="db3" />
//定义mysql1主机名对应的数据库服务器ip地址
<dataHost name="mysql1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat> //心跳状态查询
<writeHost host="hostM1" url="192.168.2.11:3306" user="mycatadmin"
password="NSD2021@tedu.cn">
</writeHost>
</dataHost>
//定义mysql2主机名对应的数据库服务器ip地址
<dataHost name="mysql2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.2.12:3306" user="mycatadmin"
password="NSD2021@tedu.cn">
</writeHost>
</dataHost>
//定义mysql3主机名对应的数据库服务器ip地址
<dataHost name="mysql3" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM3" url="192.168.2.13:3306" user="mycatadmin"
password="NSD2021@tedu.cn">
</writeHost>
</dataHost>
</mycat:schema>
步骤2:配置数据库服务器(mysql1、mysql2、mysql3操作)
① 为三台数据库服务器创建对应的数据库db1、db2、db3用来存储真实数据;
② 三台服务器需为MyCAT服务器授予mycatadmin用户访问数据库的权限;
sql
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db1 default charset utf8mb4; //创建db1库,授权mycatadmin用户
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db2 default charset utf8mb4; //创建db2库,授权mycatadmin用户
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';
[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db3 default charset utf8mb4; //创建db3库,授权mycatadmin用户
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';
步骤3:启动MyCat服务
① 在MyCat服务器上,通过MySQL测试到3台数据库服务器的连接账户
sql
[root@mycat ~]# yum -y install mysql-community-client.x86_64 //安装MySQL客户端
[root@mycat ~]# mysql -umycatadmin -pNSD2021@tedu.cn -h192.168.2.11
[root@mycat ~]# mysql -umycatadmin -pNSD2021@tedu.cn -h192.168.2.12
[root@mycat ~]# mysql -umycatadmin -pNSD2021@tedu.cn -h192.168.2.13
② 启动MyCAT服务(端口8066)
sql
[root@mycat ~]# mycat start
Starting Mycat-server...
[root@mycat ~]# netstat -nlptu | grep :8066
tcp6 0 0 :::8066 :::* LISTEN 2381/java
③ 客户端连接测试
sql
[root@localhost ~]# mysql -uroot -p123456 -P8066 -h192.168.2.15
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB |
+----------+
1 row in set (0.01 sec)
mysql> use TESTDB; //切换数据库(逻辑库TESTDB)
mysql> show tables; //数据分片配置文件中,TESTDB逻辑库下的逻辑表
+------------------+
| Tables in TESTDB |
+------------------+
| company |
| customer |
| customer_addr |
| employee |
| goods |
| hotnews |
| orders |
| order_items |
| travelrecord |
+------------------+
9 rows in set (0.01 sec)
mysql> desc goods;
ERROR 1146 (42S02): Table 'db1.goods' doesn't exist
补充:在查看表结构时发现逻辑库中的逻辑表尚未存在,若要想访问某个表,应对应例如mysql1的真实db1库的真实表(通过枚举法分片规则配置 )
**常见报错:**检查MySQL服务是否正常启动、防火墙是否关闭等
sql
[root@localhost ~]# mysql -uroot -p123456 -P8066 -h192.168.2.15
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.2.15' (113)
排错思路:查看日志/usr/local/mycat/logs/mycat.log
三、分片规则
1、枚举法概述
-
- 使用"sharding-by-intfile"规则
-
- 决定使用枚举法的表
-
- 找到数据分片字段名
-
- 查看数据分片使用的函数名
-
- 找到函数调用的配置文件
-
- 修改函数配置文件
枚举法规则示例:(sharding-by-intfile)
步骤1:配置分片规则
① 查看配置文件schema.xml,得知使用枚举法规则的表名,并添加dn3 数据节点
bash
[root@mycat ~]# grep -B1 sharding-by-intfile /usr/local/mycat/conf/schema.xml
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" />
<table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile">
结果:使用枚举法规则的表有:employee、customer
② 查看规则文件rule.xml,得知sharding-by-intfile分片规则使用的函数
bash
[root@mycat ~]# vim /usr/local/mycat/conf/rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>sharding_id</columns> //数据分片字段名
<algorithm>hash-int</algorithm> //使用的函数名(算法名)
</rule>
</tableRule>
<function name="hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property> //函数调用的配置文件
</function>
结果:枚举法使用函数为:hash-int,函数调用的配置文件为:partition-hash-int.txt,数据分片字段:sharding_id
③ 修改函数配置文件partition-hash-int.txt,添加dn3 数据节点
bash
[root@mycat ~]# vim /usr/local/mycat/conf/partition-hash-int.txt
10000=0 //当sharding_id字段的值是10000时,数据存储在数据节点dn1里
10010=1 //当sharding_id字段的值是10010时,数据存储在数据节点dn2里
10020=2 //当sharding_id字段的值是10020时,数据存储在数据节点dn3里
④ 修改配置文件后,需重启服务
bash
[root@mycat ~]# mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
补充:sharding_id字段,即rule.xml中sharding_id数据分片字段名
步骤2:客户端连接mycat分片服务器,测试存取数据
① 创建逻辑库的employee表,注意:必须添加sharding_id数据分片字段名
sql
[root@mycat ~]# mysql -uroot -p123456 -P8066 -h192.168.2.15
mysql> use TESTDB; //切换逻辑库
mysql> create table employee(id int primary key,sharding_id int,name varchar(20),birth_date date); //创建employee表(三台服务器同时也创建该表)
Query OK, 0 rows affected (0.01 sec)
mysql> desc employee; //查看表结构
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| sharding_id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| birth_date | date | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
② 存储数据时必须指定字段名列表添加VALUES
sql
mysql> insert into employee //插入语句
-> (id,sharding_id,name,birth_date)
-> values
-> (1,10000,'tom','2000-01-01'),
-> (2,10010,'ben','1998-01-11'),
-> (3,10020,'jim','1112-11-11'),
-> (4,10020,'army','1999-05-20');
Query OK, 4 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from employee; //从逻辑库中查看逻辑表(可查看到所有数据)
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
| 1 | 10000 | tom | 2000-01-01 |
| 2 | 10010 | ben | 1998-01-11 |
| 3 | 10020 | jim | 1112-11-11 |
| 4 | 10020 | army | 1999-05-20 |
+----+-------------+------+------------+
4 rows in set (0.04 sec)
③ 分别到三台MySQL服务器上查看记录
sql
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db1.employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
| 1 | 10000 | tom | 2000-01-01 |
+----+-------------+------+------------+
1 row in set (0.00 sec)
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db2.employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
| 2 | 10010 | ben | 1998-01-11 |
+----+-------------+------+------------+
1 row in set (0.00 sec)
[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db3.employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
| 3 | 10020 | jim | 1112-11-11 |
| 4 | 10020 | army | 1999-05-20 |
+----+-------------+------+------------+
2 rows in set (0.00 sec)
2、求模法概述
-
- 使用"mod-long"规则(求余)
-
- 切分规则根据配置中输入的数值"n"
-
- 分片规则将数据分成n份(通常dn节点也为n),从而将数据均匀的分布于各节点上
-
- 这种策略可以很好的分散数据库写的压力。比较适合于单点查询的情景
求模法规则示例:(mod-long)
步骤1:配置分片规则
① 查看配置文件schema.xml,得知使用求模法规则的表名,并添加dn3 数据节点
注意:要删除 autoIncrement="true" 不然无法存储数据
bash
[root@mycat ~]# vim /usr/local/mycat/conf/schema.xml
...
<table name="hotnews" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="mod-long" />
...
结果:使用枚举法规则的表有:hotnews
② 查看规则文件rule.xml,得知mod-long分片规则使用的函数
bash
[root@mycat ~]# vim /usr/local/mycat/conf/rule.xml
<tableRule name="mod-long">
<rule>
<columns>id</columns> //数据分片字段
<algorithm>mod-long</algorithm> //函数名
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property> //指定求模数字(3个节点)
</function>
结果:求模法使用函数为:mod-long,指定求模数字:3,数据分片字段:id
③ 重启服务
sql
[root@mycat ~]# mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
步骤2:客户端连接mycat分片服务器,测试存取数据
① 创建逻辑库的hotnews表,注意必须添加id数据分片字段名
sql
[root@mycat ~]# mysql -uroot -p123456 -P8066 -h192.168.2.15
mysql> use TESTDB; //切换逻辑库
mysql> create table hotnews(id int primary key,title varchar(50),content text);
Query OK, 0 rows affected (0.00 sec) // 创建hotnews表(三台服务器同时也创建该表)
mysql> desc hotnews; //查看表结构
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| title | varchar(50) | YES | | NULL | |
| content | text | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
② 存储数据时必须指定字段名列表添加VALUES
sql
mysql> insert into hotnews(id,title,content) //插入语句
-> values
-> (1,'Day-01','today is day1'),
-> (2,'Day-02','today is day2'),
-> (3,'Day-03','today is day3'),
-> (4,'Day-04','today is day4');
Query OK, 4 rows affected (0.04 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from hotnews; //从逻辑库中查看逻辑表(可查看到所有数据)
+----+--------+---------------+
| id | title | content |
+----+--------+---------------+
| 3 | Day-03 | today is day3 |
| 1 | Day-01 | today is day1 |
| 4 | Day-04 | today is day4 |
| 2 | Day-02 | today is day2 |
+----+--------+---------------+
4 rows in set (0.04 sec)
③ 分别到三台MySQL服务器上查看记录
sql
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db1.hotnews;
+----+--------+---------------+
| id | title | content |
+----+--------+---------------+
| 3 | Day-03 | today is day3 |
+----+--------+---------------+
1 row in set (0.00 sec)
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db2.hotnews;
+----+--------+---------------+
| id | title | content |
+----+--------+---------------+
| 1 | Day-01 | today is day1 |
| 4 | Day-04 | today is day4 |
+----+--------+---------------+
2 rows in set (0.00 sec)
[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db3.hotnews;
+----+--------+---------------+
| id | title | content |
+----+--------+---------------+
| 2 | Day-02 | today is day2 |
+----+--------+---------------+
1 row in set (0.00 sec)
3、全局表概述
-
- 类型为global的表存储在所有的库中;
求模法规则示例:(global)
步骤1:配置分片规则
① 查看配置文件schema.xml,得知使用全局表的表名,并添加dn3 数据节点
bash
[root@mycat ~]# vim /usr/local/mycat/conf/schema.xml
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
结果:使用枚举法规则的表有:goods
步骤2:客户端连接mycat分片服务器,测试存取数据
① 创建逻辑库的goods表
sql
[root@mycat ~]# mysql -uroot -p123456 -P8066 -h192.168.2.15
mysql> use TESTDB;
mysql> create table goods(id int primary key auto_increment,name varchar(10));
Query OK, 0 rows affected (0.00 sec)
mysql> desc goods;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
② 插入语句测试
sql
mysql> insert into goods(id,name)
-> values
-> (1,'雪碧'),
-> (2,'可乐'),
-> (3,'啤酒'),
-> (4,'炸鸡');
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from goods;
+----+--------+
| id | name |
+----+--------+
| 1 | 雪碧 |
| 2 | 可乐 |
| 3 | 啤酒 |
| 4 | 炸鸡 |
+----+--------+
4 rows in set (0.01 sec)
③ 分别到三台MySQL服务器上查看记录
sql
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db1.goods;
+----+--------+
| id | name |
+----+--------+
| 1 | 雪碧 |
| 2 | 可乐 |
| 3 | 啤酒 |
| 4 | 炸鸡 |
+----+--------+
4 rows in set (0.00 sec)
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db2.goods;
+----+--------+
| id | name |
+----+--------+
| 1 | 雪碧 |
| 2 | 可乐 |
| 3 | 啤酒 |
| 4 | 炸鸡 |
+----+--------+
4 rows in set (0.00 sec)
[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> select * from db3.goods;
+----+--------+
| id | name |
+----+--------+
| 1 | 雪碧 |
| 2 | 可乐 |
| 3 | 啤酒 |
| 4 | 炸鸡 |
+----+--------+
4 rows in set (0.00 sec)
小结:
本篇章节为【第四阶段】RDBMS2-DAY3的学习笔记,这篇笔记可以初步了解到 分库分表概述、Mycat中间件部署、分片规则(枚举法、求模法、全局表)
Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。