Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用Radon构建MySQL统一数据访问层

使用Radon构建MySQL统一数据访问层

作者头像
田帅萌
发布于 2020-04-02 07:37:35
发布于 2020-04-02 07:37:35
1.3K00
代码可运行
举报
文章被收录于专栏:「3306 Pai」社区「3306 Pai」社区
运行总次数:0
代码可运行

这篇也可以说是:RadonDB使用最佳建议,从原理上了解RadonDB的拆分后数据访问逻辑。Radon中整理架构如下:

在Radon的架构中可以利用“表名”唯一,同时利用global table, 拆分表, single table 特性实现table在RadonDB集群中分布。

为什么要使用Radon构建数据统一访问层呢?主要有以下原因:

  • 原生高可用实现
  • 配置自动化,不需要对每个表定义拆分规则
  • 基于golang开发,轻量,易部署,易管理

在上面这个架构中所有用户请求的SQL需要经过Radon,在Radon中解析并改写分发给后面的MySQL节点运算,结果返回到Radon进行合并或是汇聚返回给前端。下面我们从Radon的配置,SQL在Radon中改写情况,全面了解一下如何最佳的使用Radon。

先了解Radon配置项

config

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
 
"max-connections": 支持前端应用最多少个连接连到Radon上,       [required]
 
"max-result-size": 返回结果,最大支持多少byte,               [required]
 
"max-join-rows":   在join运算中,最多有多少行可以参与.        [required]
 
"ddl-timeout":     DDL超时的时间,                          [required]
 
"query-timeout":   Radon中DML含select运行超时间(in millisecond),     [required]
 
"twopc-enable":    是否使用Radon分布式事务提交,如果需要显式使用begin,commit需要开启,     [required]
 
"allowip":         ["allow-ip-1", "allow-ip-2"],         [required]
 
"audit-mode":      开启审计日志, "N": disabled, "R": read enabled, "W": write enabled, "A": read/write enabled,  [required]
 
}
 

更改参数参考:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

curl -i -H 'Content-Type: application/json'-X PUT -d '{"max-connections":1024, \
 
"max-result-size":1073741824, "max-join-rows":65535, \
 
"ddl-timeout":3600000, "query-timeout":60000, \
 
"twopc-enable":true,,"audit-mode":"A"}' http://127.0.0.1:8080/v1/radon/config
 

更改完配置后,配置会自动写入radon.json中。

对于Radon配置方面更详细的API: https://github.com/radondb/radon/blob/master/docs/api.md

Tips:在配置方面,如果你计划把Radon用在OLAP环境,需要注意下面,这三个参数:

  • max-result-size 返回结果,最大支持多少byte
  • max-join-rows 在join运算中,最多有多少行可以参与
  • query-timeout Radon中DML含select运行超时间(in millisecond)

Radon支持表类型:

  • single 表
  • global 表
  • 拆分表
  • 可以指定拆分数量的拆分表

single表:默认只会存在第一个节点。这是因为在Radon中很多show语句请求是默认转发到第一个节点,所以对于single表也默认存在第一个节点上,也可以通过distributed by指定存储的后端节点。对于写入读取Radon可以透明传输,性能也是最高的。

创建方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    create table tb_single(id ..
 
...
 
)engine =Innodb single  distributed by(backend1);
 

对业务不明的情况下,可以考虑所有表建成single table通过distributed by指定single表在分端节点的分布,将来数据量大了,利用Radon的Reshard功能重新拆分即可。

global表: RadonDB后面各个分组上都会存在, 对于写入Radon使用分布式事务,所有的节点都会写一份数据,适合在写少读多的场景的表。例如,全国地理位置信息等。创建语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    create table tb_global(id ..
 
...
 
)engine =Innodb global;
 

分区表: 也可以说是Radon中的拆分表,每个表默认按64个小表进行拆分,默认按该表的主键运行hash的方式拆分,而该hash,只能对单个字段运行,所以不能出现联合索引的主键。创建语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    create table tb_part(id ..
 
...
 
)engine =Innodb;
 

动态指定拆分的表: 你如果你觉的原生的分库分表功能约定太死,可以看看一下: *: support specify the number of hash partition tables #587 #588 https://github.com/radondb/radon/pull/588 可以动态的指定每个分表的数量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE zst_bt (
 
    id INT notnull,
 
    c1 varchar(32) notnull 
 
    store_id INT
 
)
 
PARTITION BY HASH(id)
 
PARTITIONS 4;
 

创建表时可以利用parttions 指定拆分的数量。目前该功能还没合并到主分支中,利用开发分支测试,功能都没问题。估计下一个版本中就会出现了,如果你觉得这个功能是你想要的,你也可以去 https://github.com/radondb/radon/pull/588 点个赞吧。

Radon中SQL执行流程

在RadonDB中,Radon担任着SQL解析和结果汇聚类的运算。针对该架构,SQL在Radon中执行,大致分为5大类:

  1. 单表(拆分表)查询中where条件有拆分键,对于global table, single table都是tcp转发,行为简单就不在列举
  2. 单表(拆分表)查询中where条件不包含拆分键
  3. single table和拆分的join操作
  4. global table和拆分的join操作
  5. 两个拆分的表做join操作

第一类 拆分表where条件中包含主键的等值查询

对于拆分表带有明确的拆分运算的语句,可以直接精确的投递到后面的节点,运算后直接返给前端。例如:select k from sbtest1 where ID=10; 其中id是拆分键。还有一类, 例如select k from sbtest1 where ID in (1,2,3,4,5); Radon也可以明确算出来以上数据在那个子表,明确给计算出来。

第二类 单表(拆分表)查询中where条件不包含拆分键

查询中不包含拆分键,同样表是拆分表的情况下,该sql会发向所有后面的节点上该表的拆分表,进行运算,然后在Radon上进行结果集的排序合并处理,返回给前端。例如:select id, k from sbtest1 where k=499 limit 10; 这类SQL中比较复杂,实质上是走的Radon对SQL分布,然后在中间件汇聚结果,最终展示(这个过程有点类似于google开源的Vitess)。

第三类 single table和拆分的join操作

对于非分表: single table(只在后面某一个节点上存储,一般是第一个节点)和拆分表做join ,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  CREATE TABLE clv2 (
  CountryCode char(3) NOT NULL DEFAULT '',
  ...,
  PRIMARY KEY (CountryCode,Language),
  KEY CountryCode (CountryCode)
) single;

SQL语句:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select a.Name, a.Population , b.Language, b.IsOfficial \
from city a, clv2 b where a.CountryCode =b.CountryCode \
limit 10

转化为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 {
"Query": "select a.Name, a.Population, a.CountryCode from \
          zst.city_0000 as a order by a.CountryCode asc",
"Backend": "`backend1`",
"Range": "[0-64)"
},
...
{
"Query": "select a.Name, a.Population, a.CountryCode from \
           zst.city_0063 as a order by a.CountryCode asc",
"Backend": "`backend2`",
"Range": "[4032-4096)"
},
{
"Query": "select b.language, b.IsOfficial, b.CountryCode from \
          zst.clv2 as b order by b.CountryCode asc",
"Backend": "`backend1`",
"Range": ""
}
"Join": {
        "Type": "INNER JOIN",
        "Strategy": "Sort Merge Join"
},
"Limit": {
        "Offset": 0,
        "Limit": 10
}

从上面可以看出来对于分区表和single的join被拆分成两步,第一步 分别在backend1,backend2上操作 SQL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select a.Name, a.Population, a.CountryCode \
from zst.city_XXXX as a order by a.CountryCode asc ;

第二步执行:select b.language, b.IsOfficial, b.CountryCode \ from zst.clv2 as b order by b.CountryCode asc ;

最终在Radon上按流式合并返回。如果需要顺序返回则后面需要添加order by ,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select a.Name, a.Population , b.Language, b.IsOfficial \
from city a, clv2 b where a.CountryCode =b.CountryCode \
order by Name limit 10;

在执行计划中会根据排序字段排序返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"GatherMerge": [
        "Name"
],

第四类 global table和拆分的join操作

global table(后端每个节点上都存在)该类表的查询行为可以明确约定,对global表的单表操作不用做SQL改写,目前读操作按轮询的机制发向后端节点进行处理。对于join操作,对分区表改写,global表不动直接下发. 如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE countrylanguage (
  CountryCode char(3) NOT NULL DEFAULT '',
  Language char(30) NOT NULL DEFAULT '',
  ...
  PRIMARY KEY (CountryCode,Language),
  KEY CountryCode (CountryCode)
) global;

测试SQL语句:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select a.Name, a.Population , b.Language, b.IsOfficial \
from city a, countrylanguage b where \
a.CountryCode =b.CountryCode limit 10;

拆分为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"Query": "select a.Name, a.Population, b.language, b.IsOfficial \
          from zst.city_0000 as a, zst.countrylanguage as b where \
          a.CountryCode = b.CountryCode limit 10",
"Backend": "`backend1`",
"Range": "[0-64)"
},
...
{
"Query": "select a.Name, a.Population, b.language, b.IsOfficial from \
         zst.city_0063 as a,zst.countrylanguage as b where \
         a.CountryCode = b.CountryCode limit 10",
"Backend": "`backend2`",
"Range": "[4032-4096)"
}
],
"Limit": {
"Offset": 0,
"Limit": 10
}

从执行计划上可以看出来对于global表的join操作,相当于把分区表,表名改写后进行下推运算,如果没有排序,直接流式返回,如果有排序,则需要全部数据执行完毕后排序返回给前段。

第五类 两个分区表join操作

两个分区表join操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select a.Name, a.District, a.Population, b.Name from city a ,\
 country b where a.CountryCode=b.Code  \
 and b.name='China' order by a.Population desc limit 10;

对于该类SQL Radon也会给转为表的请求,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
 "Query": "select a.Name, a.District, a.Population, a.CountryCode \
             from `zst.city_0000` as a order by a.CountryCode asc",
 "Backend": "backend1",
 "Range": "[0-64)"
},
 ...
{
  "Query": "select b.Name, b.Code from `zst.country_0063` as b\
            where b.name = 'China' order by b.Code asc",
  "Backend": "backend2",
  "Range": "[4032-4096)"
}
...
"Join": {
  "Type": "INNER JOIN",
  "Strategy": "Sort Merge Join"
},
"GatherMerge": [
        "a.Population"
],
"Limit": {
        "Offset": 0,
        "Limit": 10
}

从上面可以看出来,一个join语句也被拆分成两个单个SQL执行,最终在Radon上做结果的合并,返回给前端。

基于RadonDB Schema实现及最佳建议

因为以上的设计,为了在Radon中获取最佳的性能,建议遵循以下规则

  1. 对于数据量较小的表,有频繁更新读的表,建议使用single表,即可。
  2. 对于写量少,但读取量大,或是经常需要和其它表进行关联查询的,可以使用global表。
  3. 对于数据量大,写入量也大,且有高并发写入的业务,可以使用分区表。对于高速数据写入RadonDB表现比较好。对于分区表,实质上最需要注意的是分区键选择。默认官方建议是使用id bigint auto_increment 做分为分区键,而且Radon中代码写入,对于是Id的列名(不论大小写),全部要使用bigint定义。但实际使用,减少业务中读放大的问题,建议使用业务中的主键做为分区键,例如:UserId ,OrderId,MsgId, ImageId等等有意义的字段,该字段需要定义成为主键或是唯一索引。对于分表数量,建议从物理表大小,子表单表10G以内,子表总行数来考虑1500万以内,避免拆分过多的问题。
  4. 在SQL编上,尽量减少读放大的问题。对于多表join在Radon上限制有两个限制配置:总共行数不能超过< max-join-rows: 32768 ,结果集大小不能超过< max-result-size:1073741824
  5. 对于single table, global table建议物理大小不超过5G,单表行数在1千万以下。
  6. 从拆分的角度理解MySQL最佳实践中表的总数量,例如,我们约定一个MySQL实例上可以放500个表,Radon默认分区64个,如果只有一个Backend的情况下,建议该节点最多可以放8个分区表,需要在多的分区表时,建议扩展新的backend。

RadonDB SQL限制:

目前RadonDB中,为性能和安全,约束还比较多。在本次测试中遇到的,限制如下:

  1. Radon中SQL区分大小写,如 select * from tb1 where id=XX 和select * from tb1 where ID=XX 和后面表的结构定义的字段非常敏感。如果后面表tb1的字段定义成:ID,则 id=XX 会拆分成和后端分表数量一致的多条SQL执行, 而ID=XX,可以明确计算出来属于那张表进行计算。这个从Radon好修复,大概了解就可以。
  2. 分区表不支持外键 (点赞)
  3. 分区表不支持联合主键
  4. 不支持lock table/unlock table操作
  5. join查询不能使用 select * ,需要明确字段,和官方交流后,该功能已经修复。
  6. 不支持insert into c1(id, c1, c2) select id,c1,c2 from c limit 10;
  7. delete 和update必须带where条件
  8. Radon对MySQL的一些函数支持不够友好
  9. ... 估计使用还会遇到,欢迎总结 :)

总结

Radon从开发和设计上都比较轻量,从整体使用上考,Radon在设计上对于安全和性能,准确性要求比较高。这个可能和青云把RadonDB定位在金融环境的中间件有关系。大家有兴趣可以去尝试使用,如果遇到问题,也可以第一时间在 https://github.com/radondb/radon/issues 提交问题,Radon开发团队目前响应比较快,欢迎尝试。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 3306pai 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL分库分表中间件-RadonDB性能测试
了解一个产品,从性能测试下手是最好的方法,这里就是针对金融级MySQL解决方案RadonDB中的核心组件Radon进行一次性能测试。
田帅萌
2020/04/02
1.2K0
MySQL分库分表中间件-RadonDB性能测试
快速实现wordpress迁移到RadonDB上
最近发现RadonDB在特性中引入一个新特性:Single table 到分区表快速转换,另外还引进了一个优秀的特性,把现有的MySQL库直接attach到Radon下面。看到这两个特性真是太赞了。可以非常方便用户实现原来的单表,快速变成拆分表,一条命令搞定。具体的issue参考:https://github.com/radondb/radon/issues/436 而且这个特性会在1.0.8这个版本发布。下面我们一块来体验一下吧。该文档可以用于先看看整体思想上有一个认识后再行动。
田帅萌
2020/03/19
6420
Spider 引擎分布式数据库解决方案(最全的 spider 教程)
飞鸿无痕
2017/05/27
7.1K1
Spider 引擎分布式数据库解决方案(最全的 spider 教程)
利用RadonDB实现MySQL分库分表
在环境安装环节,大致可以分为:radon和 xenon(包含:MySQL, xtrabackup)的安装部署。
田帅萌
2020/03/10
2K0
利用RadonDB实现MySQL分库分表
第四章· MySQL客户端工具及SQL讲解
字符集:是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
DriverZeng
2022/09/26
7110
第四章· MySQL客户端工具及SQL讲解
MySQL-Select语句高级应用
本文介绍了MySQL数据库的一些基本概念和常用命令,包括创建数据库、创建表、插入数据、查询数据、更新数据和删除数据等。同时,还介绍了MySQL中的各种约束,如主键约束、外键约束和唯一约束等。此外,还介绍了MySQL的事务和锁定机制,以及如何使用MySQL进行多用户并发操作。最后,还介绍了MySQL的性能调优和故障恢复等方面的知识。
惨绿少年
2017/12/27
3.9K0
MySQL-Select语句高级应用
技术分享 | MySQL SHELL 是如何操作关系表的?
资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。
爱可生开源社区
2021/04/23
2.2K0
SQL,何必在忆之一(基础篇)
还记得那是在2018年的十月的某个日子,虽早已入秋,但夏日的炎热却丝毫不减退散。那时的我正捧着一本SQL Server程序设计的白蓝皮书与九栋315的狗子们,匆匆的走向j1-402进行了我们人生中第一次SQL数据库的学习,时光总是戏人,现实总是玩笑。当初的几个伙伴都走向了各行各业,而唯有我编程课,问啥啥不会,写啥啥就废的我进入了IT行业。说来实在嘲讽,缅怀那些我错过的编程课,致那些年说过无数次“让我学SQL,根本不可能”,我承认我打脸了。正如此章的title一般,“SQL语句, 何必在忆?”
PayneWu
2021/01/25
7410
RadonDB架构解析
RadonDB在DTCC大会主会场宣布开源了, 一个期待已久的产品终于走进了开源社区。 感谢青云领导层的对技术贡献的情怀。
田帅萌
2018/09/14
1.8K0
RadonDB架构解析
MySQL的EXPLAIN
MySQL的EXPALIN是优化查询语句必不可少的工具,用户通过它可以获得查询计划的相关信息,查看优化器的选择。
MySQLSE
2023/12/19
1890
MySQL的EXPLAIN
MySQL8.0 优化器介绍(一)
线上,遇到一些sql性能问题,需要手术刀级别的调优。optimizer_trace是一个极好的工具,已经有很多资料介绍optimizer_trace怎么使用与阅读。有必要再介绍一下我们平时不太能注意到,但是又对sql性能起着绝对作用的优化器。
GreatSQL社区
2023/08/10
3880
MySQL8.0 优化器介绍(一)
第六章· MySQL索引管理及执行计划
生产中,mysql在使用全表扫描时的性能是极其差的,所以MySQL尽量避免出现全表扫描
DriverZeng
2022/09/26
3390
第六章· MySQL索引管理及执行计划
mysql架构sql基础2
select 配合 from使用 相当于linux的cat查询一个表的数据不加别的条件
萧晚歌
2021/12/19
4040
【笔记】Mysql 数据库操作规范
【FAQ-1-01】 库名、表名、字段名必须使⽤小写字母,并采⽤下划线分割。 a)MySQL 有配置参数 lower_case_table_names,不可动态更改,linux 系统默认为 0,即库表名以实际情况存储,⼤小写敏感。如果是 1,以⼩写存储,⼤小写不敏感。如果是 2,以实际情况存储,但以小写⽐较。 b) 如果⼤小写混合使用,可能存在 abc,Abc,ABC 等多个表共存,容易导致混乱。 c) 字段名显⽰区分⼤⼩写,但实际使用不区分,即不可以建立两个名字⼀样但大小写不一样的字段。 d) 为了统⼀规范,库名、表名、字段名使⽤⼩写字母。
redszhao
2021/08/09
1.5K0
【笔记】Mysql 数据库操作规范
MySQL8 中文参考(八十三)
一个组最多可以由 9 台服务器组成。尝试向具有 9 个成员的组添加另一台服务器会导致加入请求被拒绝。这个限制是通过测试和基准测试确定的,是一个安全边界,在稳定的本地区域网络上组表现可靠。
ApacheCN_飞龙
2024/06/26
1640
MySQL数据库设计规范
MySQL数据库与 Oracle、 SQL Server 等数据库相比,有其内核上的优势与劣势。我们在使用MySQL数据库的时候需要遵循一定规范,扬长避短。本规范旨在帮助或指导RD、QA、OP等技术人员做出适合线上业务的数据库设计。在数据库变更和处理流程、数据库表设计、SQL编写等方面予以规范,从而为公司业务系统稳定、健康地运行提供保障。
物流IT圈
2019/07/16
2.2K0
MySQL数据库设计规范
2020最新版MySQL数据库面试题(三)
select r.*,s.* from r full join s on r.c=s.c
码农编程进阶笔记
2021/07/20
6660
2020最新版MySQL数据库面试题(三)
MySQL8.0 优化器介绍(二)
join在MySQL 是一个如此重要的章节,毫不夸张的说,everything is a join。
GreatSQL社区
2023/08/10
2410
MySQL8.0 优化器介绍(二)
hive基础总结(面试常用)
hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。 Metastore (hive元数据) Hive将元数据存储在数据库中,比如mysql ,derby.Hive中的元数据包括表的名称,表的列和分区及其属性,表的数据所在的目录 Hive数据存储在HDFS,大部分的查询、计算由mapreduce完成 Hive数据仓库于数据库的异同 (1)由于Hive采用了SQL的查询语言HQL,因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语言, 再无类似之处。 (2)数据存储位置。 hdfs raw local fs (3)数据格式。 分隔符 (4)数据更新。hive读多写少。Hive中不支持对数据的改写和添加,所有的数据都是在加载的时候中确定好的。 INSERT INTO … VALUES添加数据,使用UPDATE … SET修改数据 不支持的 HDFS 一次写入多次读取 (5) 执行。hive通过MapReduce来实现的 而数据库通常有自己的执行引擎。 (6)执行延迟。由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致Hive执行延迟高的因素是MapReduce框架 (7)可扩展性 (8)数据规模。 hive几种基本表类型:内部表、外部表、分区表、桶表 内部表(管理表)和外部表的区别: 创建表 外部表创建表的时候,不会移动数到数据仓库目录中(/user/hive/warehouse),只会记录表数据存放的路径 内部表会把数据复制或剪切到表的目录下 删除表 外部表在删除表的时候只会删除表的元数据信息不会删除表数据 内部表删除时会将元数据信息和表数据同时删除 表类型一、管理表或内部表Table Type: MANAGED_TABLE
用户1217611
2019/05/25
7800
深入探讨 GBase 数据库性能优化的最佳实践
随着企业级数据库系统的广泛应用,性能优化成为数据库管理中至关重要的一环。GBase 数据库作为一款高性能关系型数据库,支持分布式存储、强大的事务处理能力以及复杂的查询优化技术。然而,实际应用中,如何最大化地发挥 GBase8a、GBase8s 和 GBase8c 的性能潜力,是每位开发者和运维人员必须面对的挑战。
用户11381600
2024/12/03
1280
相关推荐
MySQL分库分表中间件-RadonDB性能测试
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验