概念
Radon支持传统proxy的分库分表模型,但是又区别于传统的分库分表模式,默认情况下Radon自动帮你完成了分库分表的动作。在正式介绍之前,我们先介绍几个概念
分区表
global表
single表
分区表
分区表即我们传统观念上的分库分表,当单机MySQL无法承载业务压力的情况下,大多数公司都会采用这种方式,将原先的大表进行分表,并将拆分出来的单表均匀地分布在各个不同的物理节点。根据拆分的方式,一般有hash拆分、range拆分、list拆分等,同时也有组合拆分的方式,这里暂不展开各种拆分方式对应到业务是怎样的,我们只要知道把大表拆分成了各个不同的小表就行了。那拆分完成以后,客户端对数据的访问就多了一层路由,中间件会根据对应的拆分规格即元数据对请求进行解析,解析完成以后生成对应的执行计划,然后下发到对应的节点。
例如有一张1000万大小的用户表,我们根据用户id进行hash取模后,拆分成了100个分片,每个分片大约10万数据,当客端户发送一条select id,name,nickname,age from user where id = 100,中间件接收到这个sql以后,会对id=100进行hash计算,计算取模后知道这条数据落在哪个分片上,知道了在哪个分片上以后,那么就可以连接到后端MySQL进行数据查询。后端MySQL进行数据查询以后(同单机模式)将对应的数据发送给中间件,再由中间件返回给客户端。整个链路大概就完成了。
global表
global表顾名思义就是全局表的意思,也就是每个分片节点上都会存一份,数据全局一致,这种表比较适合的场景就是更新不频繁,表比较小的场景,因为更新频繁的话容易造成写放大,集群性能下降。global表一般会用于关联,比如国家代码表这种。
single表
区别于分区表和global表,single表只会在集群中一个节点中存在,类似于单机MySQL。正是由于这个特性,Radon提供了一个真香特性-attach,即可以把现有的数据节点直接挂到Radon上,这个数据节点的表就都以single表的形式存在,这个特性后面会详细介绍,特别适合旧项目改造。
Radon实操
首先看下Radon创建表的语法
CREATE TABLE [IF NOT EXISTS] table_name
(create_definition,...)
ENGINE [=] {InnoDB|TokuDB}
| AUTO_INCREMENT [=] value
| [DEFAULT] {CHARSET | CHARACTER SET} [=] charset_name
| COMMENT [=] 'string'
| {PARTITION BY HASH(shard-key)|SINGLE|GLOBAL|DISTRIBUTED BY (backend-name)}
| PARTITION BY LIST(shard-key)(PARTITION backend VALUES IN (value_list),...)
语法基本同MySQL
支持定义存储引擎为InnoDB或者TokuDB
支持指定自增
支持定义字符集
支持表注释
支持分区、single、global表,支持hash分区、list分区
hash分区支持指定分区键
single表支持落到哪个数据节点
list分区可以指定某些list存储到哪个数据节点
创建hash分区表
xucl@mysqldb 16:31: [zst]> create table p_t1(id bigint primary key,c1 varchar(32));
Query OK, 0 rows affected (0.13 sec)
xucl@mysqldb 16:31: [zst]> show create table p_t1\G
*************************** 1. row ***************************
Table: p_t1
Create Table: CREATE TABLE `p_t1` (
`id` bigint(20) NOT NULL,
`c1` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!50100 PARTITION BY HASH(id) */
1 row in set (0.00 sec)
查看radon元数据信息
{
"name": "p_t1",
"slots-readonly": 4096,
"blocks-readonly": 512,
"shardtype": "HASH",
"shardkey": "id",
"partitions": [
{
"table": "p_t1_0000",
"segment": "0-512",
"backend": "backend1",
"listvalue": ""
},
....
{
"table": "p_t1_0007",
"segment": "3584-4096",
"backend": "backend2",
"listvalue": ""
}
]
}
可以看到p_t1表被分成了8个分区,0~3分区分布在backend1上,5~8分区分布在backend2上。有人可能会疑惑为什么会被分成8个分区呢,这个其实由配置文件router部分的slots-readonly、blocks-readonly决定,我这里slots-readonly为4096,blocks-readonly为512,所以分区数为8。
创建global表
xucl@mysqldb 16:36: [zst]> create table g_t1(id bigint primary key,c1 varchar(32)) global;
Query OK, 0 rows affected (0.03 sec)
xucl@mysqldb 17:14: [zst]> show create table g_t1\G
*************************** 1. row ***************************
Table: g_t1
Create Table: CREATE TABLE `g_t1` (
`id` bigint(20) NOT NULL,
`c1` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!GLOBAL*/
1 row in set (0.00 sec)
查看元数据信息
{
"name": "g_t1",
"slots-readonly": 0,
"blocks-readonly": 0,
"shardtype": "GLOBAL",
"shardkey": "",
"partitions": [
{
"table": "g_t1",
"segment": "",
"backend": "backend1",
"listvalue": ""
},
{
"table": "g_t1",
"segment": "",
"backend": "backend2",
"listvalue": ""
}
]
}
看到确实两个数据节点上都有g_t1表
创建single表
xucl@mysqldb 16:35: [zst]> create table s_t1(id bigint primary key,c1 varchar(32))distributed by (backend1);
Query OK, 0 rows affected (0.02 sec)
xucl@mysqldb 16:36: [zst]> show create table s_t1\G
*************************** 1. row ***************************
Table: s_t1
Create Table: CREATE TABLE `s_t1` (
`id` bigint(20) NOT NULL,
`c1` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!SINGLE*/
1 row in set (0.00 sec)
查看元数据
{
"name": "s_t1",
"slots-readonly": 0,
"blocks-readonly": 0,
"shardtype": "SINGLE",
"shardkey": "",
"partitions": [
{
"table": "s_t1",
"segment": "",
"backend": "backend1",
"listvalue": ""
}
]
}
从元数据信息可以看到s_t1表只落在backend1上,shardtype为SINGLE
总结
本节介绍了RadonDB中的三种表概念,以及创建方式。下一节将会介绍RadonDB对于SQL的处理逻辑以及如何查看执行计划等。
由叶老师主讲的知数堂「MySQL优化课」第17期已发车,我们的课程从第15期就升级成MySQL 8.0版本了,现在上车刚刚好,扫码开启MySQL 8.0的修行之旅吧。
另外,叶老师在腾讯课堂的短课程《MySQL性能优化》已开课,本课程讲解读几个MySQL性能优化的核心要素:合理利用索引,降低锁影响,提高事务并发度。
下面是报名小程序码
点“在看”给我一朵小黄花