白菜Java自习室 涵盖核心知识
分库分表难题(一) 分表分页/跨库分页 难玩却不代表没有玩法
分库分表难题(二) 跨库/跨实例 Join 连接 不是非得依赖中间件
1. 数据垂直切分
某电商公司原先将会员、订单、商品等数据都存放在一个数据库实例中,但业务发展迅猛,访问量极速增长,导致数据库容量及性能遭遇瓶颈,因此 用户决定对架构进行垂直拆分,将会员、商品、订单数据垂直拆分至三个数据库实例中。此时业务上需要展示某个品类商品的售卖订单量,原本在同一数据库里的查询,要变成跨两个数据库实例的查询。业务上要怎么进行关联查询?
跨库 Join 需求
用户首先想到的方法是,对现有业务代码进行重构,分别从两个数据库查询数据,然后在业务代码中进行 join 关联。那么问题来了,如果采用这个解决方案,业务上那么多查询改造起来,拆分难度极大,操作起来过于复杂。跨库 join 操作又没有非常高效的办法,需要从各个业务库迭代查询,查询效率也会有一定影响。
当方案被否决后,用户再次想到的方法是,要不 使用 Mycat,Sharding-jdbc 等数据库中间件来实现,当然这本身是一个可行的方案,而且也是不错的解决方案。但是如果公司系统情况复杂,改变架构困难,代码腐化严重,短时间内根本无法解决这个问题,脱离这些数据库中间件是不是就束手无策了呢?
2. MySQL FEDERATED 引擎原理
如图,FEDERATED 引擎的原理为:
- 远程服务器开启 FEDERATED 引擎支持;
- 本地服务器查询 FEDERATED 引擎表时,会发送查询语句到远程服务器;
- 远程服务器通过传过来的查询语句,查询出结果,返回给本地调用服务器;
3. MySQL 开启 FEDERATED 引擎
MySQL 的前置安装过程这里就省略了,版本是推荐 MySQL5.7。
Docker 方式安装过程可参考作者文章: Canal 解决 MySQL 和 Redis 数据同步问题
2.1. 执行命令:SHOW ENGINES;
查看 mysql 数据库中 Federated 引擎是否开启。下图所示,为未开启。
SHOW ENGINES;
2.2 修改 MySQL 配置文件,重启服务
修改 mysql 文件夹根目录的 my.ini 文件(Linux 系统修改 my.cnf 文件):新添加一行,内容为 federated,如下图所示:(Docker 方式安装只需要修改外置配置文件后重启容器即可,阿里云、华为云 DMS 可自行寻找修改配置方式,甚至于自带跨库Link功能)
federated
docker restart (容器ID)
2.3. 再次执行命令:SHOW ENGINES;
检查 mysql 数据库中 Federated 引擎是否开启,现在我们发现已经是开启状态了。
SHOW ENGINES;
2.4. 新建两个测试用的数据库,数据库表
这里读者自行去建数据库,自由发挥:
然后 在两个数据库里分别新建两张表 prd_sku(SKU信息表)和 prd_sku_stock(SKU库存表):
CREATE TABLE `prd_sku` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(180) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'SKU名称',
`code` varchar(180) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'SKU编码',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
CREATE TABLE `prd_sku_stock` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`sku_id` int(11) NOT NULL DEFAULT 0 COMMENT 'SKU的ID',
`stock` int(11) NOT NULL DEFAULT 0 COMMENT 'SKU的库存',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
我们先在表里边添加点数据进去:
INSERT INTO `prd_sku` VALUES (1, '黄色S码', 'Y00S00');
INSERT INTO `prd_sku` VALUES (2, '红色M码', 'R00M00');
INSERT INTO `prd_sku_stock` VALUES (1, 1, 96);
INSERT INTO `prd_sku_stock` VALUES (2, 2, 98);
2.5. 在数据库 A 中建立远程表连接数据库 B
CREATE TABLE `mycat_db1`.`prd_sku_stock` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`sku_id` int(0) NOT NULL,
`stock` int(0) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = FEDERATED CONNECTION = 'mysql://root:88021120@localhost:3306/mycat_db2/prd_sku_stock';
- root:88021120 远程数据库的账号和密码
- localhost:3306 远程数据库的ip和端口
- mycat_db2 远程数据库的名称
- prd_sku_stock 远程数据库的表名称
这里有几个特别需要注意的点:
- 连接表的字段必须和真实表一致,允许是子集;
- 真实表数据更新连接表自动会更新,反之亦然;
- 真实表结构改动,连接表不会跟着改动;
- 删除连接表,是真实表不会被跟着删除;
- 连接表无法用 ALTER 语句改结构,所以如果想同步需求可以删除重新建;
2.6. 在数据库 A 中执行 join 查询,查看结果
SELECT * FROM prd_sku t1, prd_sku_stock t2 WHERE t1.id=t2.sku_id;
3. 阿里云 DMS 跨实例查询服务
阿里云 DMS(数据管理)跨实例查询服务,不仅覆盖了异构数据源关联查询的场景,还解决了跨 region、跨云的数据库关联查询的难题。不仅如此,还对查询性能进行了大幅优化,使得大部分查询能在毫秒级完成。用户无需通过数据汇集,即可通过标准的 SQL 实现跨实例的交叉查询。
DBLink
熟悉 Oracle 的人应该知道,我们可以在当前登录的 Oracle 上,建立一个 DBLink 指向另一个远程的Oracle 数据库表。在跨实例查询服务中,重新定义了 DBLink 的概念,它是一个指向用户的任意数据库实例的虚拟连接,是数据库实例的别名。例如,对于 MySQL 来说,DBLink 和 ip/port 一一对应。借助 DBLink,即可实现对任意数据源的 SQL 访问。
兼容标准 SQL
通过标准的 SQL 语句,即可实现跨实例查询。同时跨实例查询服务高度兼容 MySQL,支持 MySQL 协议,以及各种常用函数和语法。您可通过 JDBC/ODBC 驱动连接到跨实例查询服务;也可以使用各种 MySQL GUI 工具来管理各种数据源。
Serverless 架构
跨实例查询是无服务器化的在线数据库关联查询服务。用户无需预购计算资源、无需维护资源、没有运维和升级成本,随时随地使用。
高性能低延迟
跨实例查询服务底层基于强大的 MPP 计算引擎,持续不断地对 SQL 查询进行优化,包括 pushdown、join 算法、执行计划缓存、Meta 缓存、本地调度、连接池等技术。目前单表查询以及跨实例的多表关联查询,都能在毫秒级完成。
支持多种关系型数据库
目前已支持 MySQL、SQLServer、PostgreSQL 等多种关系型数据库。
支持 SQL 方式访问 NoSQL
除了关系型数据库之外,跨实例查询还支持以 SQL 方式访问 Redis 等 NoSQL 数据库。由于支持了 SQL 语法,也可以实现 RDBMS 和 NoSQL 之间关联查询。是的,你没看错,一条 SQL 就能实现 MySQL 和 Redis 之间的关联查询。
支持跨地域以及混合云查询
企业发展到一定阶段,用户量、业务量不断攀升,原来的单机房容量已经不能满足业务发展的需求,再结合容灾、高可用等因素,通常会选择跨 region 部署,也叫单元化部署。同时,不少企业也需要将业务拓展到海外,通过本地就近部署,为国外用户提供更好的体验。类似这种水平拆分带来的问题就是,如何对全局的业务数据进行统一的汇总关联查询。
借助 DMS 跨实例查询服务,无论您的数据库实例部署在阿里云的哪个 region,无需跨 region 的数据迁移,即可实现所有 region 数据的统一查询。除了阿里云 RDS,也支持用户部署在阿里云 ECS 上的各种数据库。不仅如此,如果您的数据库部署在本地 IDC 机房,甚至其他云厂商,都可以通过跨实例查询服务,实现这些混合云场景的跨实例关联查询。
分库分表难题(一) 分表分页/跨库分页 难玩却不代表没有玩法
分库分表难题(二) 跨库/跨实例 Join 连接 不是非得依赖中间件