0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

分库分表的21条法则速来码住(下)

jf_78858299 来源:程序员小富 作者:程序员内点事 2023-05-26 17:33 次阅读

SQL 解析

分库分表后在应用层面执行一条 SQL 语句时,通常需要经过以下六个步骤:SQL 解析 -> 执⾏器优化 -> SQL 路由 -> SQL 改写 -> SQL 执⾏ -> 结果归并

图片

在这里插入图片描述

SQL解析过程分为词法解析语法解析两步,比如下边查询用户订单的SQL,先用词法解析将这条SQL拆解成不可再分的原子单元。在根据不同数据库方言所提供的字典,将这些单元归类为关键字,表达式,变量或者操作符等类型。

SELECT order_no FROM t_order where  order_status > 0  and user_id = 10086

接着语法解析会将拆分后的SQL关键字转换为抽象语法树,通过对抽象语法树遍历,提炼出分片所需的上下文,上下文包含查询字段信息Field)、表信息(Table)、查询条件(Condition)、排序信息(Order By)、分组信息(Group By)以及分页信息(Limit)等,并标记出 SQL中有可能需要改写的位置。

图片

抽象语法树

执⾏器优化

执⾏器优化是根据SQL查询特点和执行统计信息,选择最优的查询计划并执行,比如user_id字段有索引,那么会调整两个查询条件的位置,主要是提高SQL的执行效率。

SELECT order_no FROM t_order where user_id = 10086 and order_status > 0

SQL 路由

通过上边的SQL解析得到了分片上下文数据,在匹配用户配置的分片策略和算法,就可以运算生成路由路径,将 SQL 语句路由到相应的数据节点上。

简单点理解就是拿到分片策略中配置的分片键等信息,在从SQL解析结果中找到对应分片键字段的值,计算出 SQL该在哪个库的哪个表中执行,SQL路由又根据有无分片健分为 分片路由广播路由

图片

有分⽚键的路由叫分片路由,细分为直接路由、标准路由和笛卡尔积路由这3种类型。

标准路由

标准路由是最推荐也是最为常⽤的分⽚⽅式,它的适⽤范围是不包含关联查询或仅包含绑定表之间关联查询的SQL。

当 SQL分片健的运算符为 = 时,路由结果将落⼊单库(表),当分⽚运算符是BETWEENIN 等范围时,路由结果则不⼀定落⼊唯⼀的库(表),因此⼀条逻辑SQL最终可能被拆分为多条⽤于执⾏的真实SQL。

SELECT * FROM t_order  where t_order_id in (1,2)

SQL路由处理后

SELECT * FROM t_order_0  where t_order_id in (1,2)
SELECT * FROM t_order_1  where t_order_id in (1,2)

直接路由

直接路由是直接将SQL路由到指定⾄库、表的一种分⽚方式,而且直接路由可以⽤于分⽚键不在SQL中的场景,还可以执⾏包括⼦查询、⾃定义函数等复杂情况的任意SQL。

笛卡尔积路由

笛卡尔路由是由⾮绑定表之间的关联查询产生的,比如订单表t_order 分片键是t_order_id和用户表t_user分片键是t_order_id,两个表的分片键不同,要做联表查询,会执行笛卡尔积路由,查询性能较低尽量避免走此路由模式。

SELECT * FROM t_order_0 t LEFT JOIN t_user_0 u ON u.user_id = t.user_id WHERE t.user_id = 1
SELECT * FROM t_order_0 t LEFT JOIN t_user_1 u ON u.user_id = t.user_id WHERE t.user_id = 1
SELECT * FROM t_order_1 t LEFT JOIN t_user_0 u ON u.user_id = t.user_id WHERE t.user_id = 1
SELECT * FROM t_order_1 t LEFT JOIN t_user_1 u ON u.user_id = t.user_id WHERE t.user_id = 1

无分⽚键的路由又叫做广播路由,可以划分为全库表路由、全库路由、 全实例路由、单播路由和阻断路由这 5种类型。

全库表路由

全库表路由针对的是数据库 DQLDML,以及 DDL等操作,当我们执行一条逻辑表 t_order SQL时,在所有分片库中对应的真实表 t_order_0 ··· t_order_n 内逐一执行。

全库路由

全库路由主要是对数据库层面的操作,比如数据库 SET 类型的数据库管理命令,以及 TCL 这样的事务控制语句。

对逻辑库设置 autocommit 属性后,所有对应的真实库中都执行该命令。

SET autocommit=0;

全实例路由

全实例路由是针对数据库实例的 DCL 操作(设置或更改数据库用户或角色权限),比如:创建一个用户 order ,这个命令将在所有的真实库实例中执行,以此确保 order 用户可以正常访问每一个数据库实例。

CREATE USER order@127.0.0.1 identified BY '程序员小富';

单播路由

单播路由用来获取某一真实表信息,比如获得表的描述信息:

DESCRIBE t_order;

t_order 的真实表是 t_order_0 ···· t_order_n,他们的描述结构相完全同,我们只需在任意的真实表执行一次就可以。

阻断路由

⽤来屏蔽SQL对数据库的操作,例如:

USE order_db;

这个命令不会在真实数据库中执⾏,因为 ShardingSphere 采⽤的是逻辑 Schema(数据库的组织和结构) ⽅式,所以无需将切换数据库的命令发送⾄真实数据库中。

SQL 改写

SQL经过解析、优化、路由后已经明确分片具体的落地执行的位置,接着就要将基于逻辑表开发的SQL改写成可以在真实数据库中可以正确执行的语句。比如查询 t_order 订单表,我们实际开发中 SQL是按逻辑表 t_order 写的。

SELECT * FROM t_order

这时需要将分表配置中的逻辑表名称改写为路由之后所获取的真实表名称。

SELECT * FROM t_order_n

SQL执⾏

将路由和改写后的真实 SQL 安全且高效发送到底层数据源执行。但这个过程并不能将 SQL 一股脑的通过 JDBC 直接发送至数据源执行,需平衡数据源连接创建以及内存占用所产生的消耗,它会自动化的平衡资源控制与执行效率。

结果归并

将从各个数据节点获取的多数据结果集,合并成一个大的结果集并正确的返回至请求客户端,称为结果归并。而我们SQL中的排序、分组、分页和聚合等语法,均是在归并后的结果集上进行操作的。

分布式主键

数据分⽚后,一个逻辑表(t_order)对应诸多的真实表(t_order_n),它们之间由于⽆法互相感知,主键ID都从初始值累加,所以必然会产⽣重复主键ID,此时主键不再唯一那么对于业务来说也就没意义了。

图片

尽管可通过设置表⾃增主键 初始值步⻓ 的⽅式避免ID碰撞,但这样会使维护成本加大,可扩展性差。

这个时候就需要我们手动为一条数据记录,分配一个全局唯一的ID,这个ID被叫做分布式ID,而生产这个ID的系统通常被叫做发号器。

大家可以参考我之前发布的这篇文章 9种分布式ID生成方案

数据脱敏

分库分表数据脱敏是一种有效的数据保护措施,可以确保敏感数据的机密性和安全性,减少数据泄露的风险。

比如,我们在分库分表时可以指定表的哪些字段为脱敏列,并设置对应的脱敏算法,在数据分片时解析到执行SQL中有待脱敏字段,会直接将字段值脱敏后的写入库表内。

对于用户的个人信息,如姓名、地址和电话号码等,可以通过加密、随机化或替换成伪随机数据的方式进行脱敏,以确保用户的隐私得到保护。

大家可以参考我之前发布的这篇文章 大厂也在用的 6种 数据脱敏方案

分布式事务

分布式事务的核心问题是如何实现跨多个数据源的原子性操作。

由于不同的服务通常会使用不同的数据源来存储和管理数据,因此,跨数据源的操作可能会导致数据不一致性或丢失的风险。因此,保证分布式事务的一致性是非常重要的。

以订单系统为例,它需要调用支付系统、库存系统、积分系统等多个系统,而每个系统都维护自己的数据库实例,系统间通过API接口交换数据。

图片

为了保证下单后多个系统同时调用成功,可以使用强一致性事务的XA协议,或者柔性事务的代表工具Seata,来实现分布式事务的一致性。这些工具可以帮助开发人员简化分布式事务的实现,减少错误和漏洞的出现,提高系统的稳定性和可靠性。

经过分库分表之后,问题的难度进一步提升。自身订单服务,也需要处理跨数据源的操作。这样一来,系统的复杂度显著增加。因此,不到万不得已的情况下,最好避免采用分库分表的解决方案。

图片

关于分布式事务详细的介绍,大家可以参考我之前发布的这篇文章 对比 5 种分布式事务方案,还是宠幸了阿里的 Seata(原理 + 实战)

数据迁移

分库分表后还有个让人头疼的问题,那就是数据迁移,为了不影响现有的业务系统,通常会新建数据库集群迁移数据。将数据从旧集群的数据库、表迁移到新集群的分库、分表中。这是一个比较复杂的过程,在迁移过程中需要考虑数据量数据一致性迁移速度等诸多因素。

迁移主要针对 存量数据增量数据 的处理,存量数据指旧数据源中已经存在且有价值的历史数据,增量数据指当下持续增长以及未来产生的业务数据。

存量数据可以采用定时、分批次的迁移,迁移过程可能会持续几天。

增量数据可以采用新、旧数据库集群双写模式。待数据迁移完毕,业务验证了数据一致性,应用直接切换数据源即可。

后续我们会结合三方工具,来演示迁移的过程。

影子库

什么是影子库(Shadow Table)?

影子库是一个与生产环境数据库结构完全相同的实例,它存在的意义是为了在不影响线上系统的情况下,验证数据库迁移或者其他数据库变更操作的正确性,以及全链路压测。影子库中存储的数据是从生产环境中定期复制过来的,但是它不对线上业务产生任何影响,仅用于测试,验证和调试。

图片

在进行数据库升级、版本变更、参数调优等操作前,通过在影子库上模拟这些操作,可以发现潜在的问题,因为测试环境的数据是不可靠的。

在使用影子库时,需要遵循以下几个原则:

  • 与生产环境数据库的结构应该完全一致,包括表结构、索引、约束等;
  • 数据要与生产环境保持一致,可以通过定期同步方式实现;
  • 读写操作不会影响生产环境,一般情况下应该禁止在影子库上执行更新、删除等操作;
  • 由于影子库的数据特点,访问权限应该严格控制,只允许授权人员进行访问和操作;

总结

本文介绍了关于分库分表架构的21个通用概念,有一定的了解之后,接下来我们将进入更深度的内容,包括读写分离数据脱敏分布式主键分布式事务配置中心注册中心Proxy服务等实战案例的讲解和源码分析。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    738

    浏览量

    43462
  • 路由
    +关注

    关注

    0

    文章

    266

    浏览量

    41515
收藏 人收藏

    评论

    相关推荐

    数据库分区、分库和分表

    今天先说说数据库的数据分区,分库以及分表的内容吧! 数据库分区、分库和分表 数据库分区、分库和分表是针对大型数据库系统的优化策略。它们的主要目的是提高数据库的性能和可靠性,以满足不断增长的数据存储
    的头像 发表于 09-30 11:24 844次阅读

    Honeywell QC850条码检测仪

    Honeywell QC850条码检测仪我司是美国霍尼韦尔Honeywell系列条码扫描设备中国地区经销商,部分型号列表:Honeywell 3200条码扫描器、Honeywell 3800g条码
    发表于 12-16 21:55

    PCB设计黄金法则

    本帖最后由 pcbsun 于 2014-8-21 17:37 编辑   本文介绍了电子设计工程师在使用设计软件进行PCB布局设计及商业制造时应牢记并践行的十最有效的设计法则。工程师无需
    发表于 08-21 17:35

    Cadence 16.5 部分库文件不能使用

    各位亲们,安装Cadence 16.5(破解成功)后,OrCAD Capture CIS 库的模型没有,但其它部分库里的模型又完好,怎么回事呀? 麻烦各位能解答吗?
    发表于 07-17 10:39

    最有效的PCB设计黄金法则

    最有效的PCB设计黄金法则 尽管目前半导体集成度越来越高,许多应用也都有随时可用的片上系统,同时许多功能强大且开箱即用的开发板也越来越可轻松获取,但许多使用案例中电子产品的应用仍然需要使用定制
    发表于 08-17 16:18

    谈分布式数据库中间件之分库   

      分库,顾名思义就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个的数据分块存储到多个上。那么关于
    发表于 08-02 20:19

    10PCB设计黄金法则

    时应牢记并践行的十最有效的设计法则。工程师无需按时间先后或相对重要性依次执行这些法则,只需全部遵循便可极大地改变产品设计。  法则一:选择正确的网格 - 设置并始终使用能够匹配最多元
    发表于 09-21 16:46

    富士通是如何在存储领域丛林法则崛起的?

    市场经济每一个技术领域的竞争都是一场丛林法则的生动演绎。随着物联网和大数据等新兴应用的爆发增长,存储器领域的丛林法则年年都在上演“生动”的故事。
    发表于 10-17 06:09

    分库是什么?怎么实现?

    数据库分库、读写分离的原理实现,使用场景
    发表于 10-25 17:24

    结合实践对水平分库做一个系统地剖析

    随着大型互联网应用的发展,海量数据的存储和访问成为系统设计的瓶颈,分布式处理成为不二选择。数据库拆分,特别是水平分库是个高难度的活,涉及一系列技术决策。 本人有幸负责1号店订单水平分库的方案设计
    发表于 10-11 17:46 0次下载
    结合实践对水平<b class='flag-5'>分库</b>做一个系统地剖析

    i7-9700K现身跑分库

    经查,型号识别为i7-9700K的平台出现在了GeekBench 4.2跑分库中。
    发表于 09-04 10:55 1973次阅读

    你们知道为什么要分库分表吗

    在文章开头先抛几个问题: (1)什么时候才需要分库分表呢?我们的评判标准是什么? (2)一张表存储了多少数据的时候,才需要考虑分库分表? (3)数据增长速度很快,每天产生多少数据,才需要考虑做分库
    的头像 发表于 08-16 10:37 1363次阅读

    你是否知道分库分表需要哪些要素?

    分库分表会重新影响数据的分布,无论是全量还是增量,都会涉及到数据迁移,所以Databus是必要的。
    的头像 发表于 10-12 10:39 566次阅读

    什么是分库分表?为什么分库分表?什么情况下会用分库分表呢?

    分库分表是由分库和分表这两个独立概念组成的,只不过通常分库与分表的操作会同时进行,以至于我们习惯性的将它们合在一起叫做分库分表。
    的头像 发表于 11-30 09:37 4490次阅读

    分库分表的21法则速来码住(上)

    还是不着急实战,咱们先介绍下在分库分表架构实施过程中,会接触到的一些通用概念,了解这些概念能够帮助理解市面上其他的分库分表工具,尽管它们的实现方法可能存在差异,但整体思路基本一致。因此,在开始
    的头像 发表于 05-26 17:33 394次阅读
    <b class='flag-5'>分库</b>分表的<b class='flag-5'>21</b>条<b class='flag-5'>法则</b><b class='flag-5'>速来</b>码住(上)