25.【学习心得】学习心得-基于MySQL的分表分库

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: 【学习心得】学习心得-基于MySQL的分表分库

文档参考:书名:《从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战》-王伟杰

image.png

前文如下:


23.【学习心得】学习心得-冷热分离概述

24.【学习心得】学习心得-如何分离冷热数据


1. 基于MySQL的分表分库

分表是将一份大的表数据进行拆分后存放至多个结构一样的拆分表中;分库就是将一个大的数据库拆分成类似于多个结构的小数据库。场景介绍里就举了个简单的例子,这里不再赘述。

1.1 需求

如果使用分表分库,有3个通用技术需求需要实现。


1)SQL组合:因为关联的表名是动态的,所以需要根据逻辑组装动态的SQL。比如,要根据一个订单的ID获取订单的相关数据,Select语句应该针对(From)哪一张表?

2)数据库路由:因为数据库名也是动态的,所以需要通过不同的逻辑使用不同的数据库。比如,如果要根据订单ID获取数据,怎么知道要连接哪一个数据库?

3)执行结果合并:有些需求需要通过多个分库执行后再合并归集起来。假设需要查询的数据分布在多个数据库的多个表中(比如在order1里面的t_order_1,order2里面的t_order_9中),那么需要将针对这些表的查询结果合并成一个数据集。


1.2 实现模式


而目前能解决以上问题的中间件分为两类:Proxy模式、Client模式。


      1)Proxy模式:图3-2所示为ShardingSphere官方文档中的Proxy模式图,重点看中间的Sharding-Proxy层。这种设计模式将SQL组合、数据库路由、执行结果合并等功能全部放在了一个代理服务中,而与分表分库相关的处理逻辑全部放在了其他服务中,其优点是对业务代码无侵入,业务只需要关注自身业务逻辑即可。


网络异常,图片无法展示
|


     2)Client模式:ShardingSphere官方文档中的Client模式如图3-3所示。这种设计模式将分表分库相关逻辑放在客户端,一般客户端的应用会引用一个jar,然后在jar中处理SQL组合、数据库路由、执行结果合并等相关功能。


网络异常,图片无法展示
|


这两种模式的中间件见表3-2。


网络异常,图片无法展示
|


这两种开源中间件的设计模式该如何选择呢?先简单对比一下它们的优缺点,见表3-3。


网络异常,图片无法展示
|


     因为看重“代码灵活可控”这个优势,最终选择了Client模式里的Sharding-JDBC来实现分表分库。

2.分表分库实现思路

技术选型这一难题解决后,具体如何落实分表分库方案呢?需要考虑5个要点。

1)使用什么字段作为分片主键?

2)分片的策略是什么?

3)业务代码如何修改?

4)历史数据如何迁移?

5)未来的扩容方案是什么?

2.1 使用什么字段作为分片主键


先来回顾一下业务场景中的数据库示例,见表3-4。

网络异常,图片无法展示
|


表t_order使用user_ID作为分片主键,为什么呢?当时的思路如下。


在选择分片主键之前,首先要了解系统中的一些常见业务需求。

1)用户需要查询所有订单,订单数据中肯定包含不同的user_ID、order_time。

2)后台需要根据城市查询当地的订单。

3)后台需要统计每个时间段的订单趋势。根据这些常见业务需求,判断一下优先级,用户操作(也就是第一个需求)必须优先满足。此时如果使用user_ID作为订单的分片主键,就能保证每次用户查询数据(第一个需求)时,在一个分库的一个分表里即可获取数据。因此,在方案里,最终还是使用user_ID作为分片主键,这样在分表分库查询时,首先会把user_ID作为参数传过来。


2.2 分片的策略是什么


决定使用user_ID作为订单分片主键后,就要开始考虑使用何种分片策略了. 目前通用的分片策略分为根据范围分片、根据Hash值分片、根据Hash值及范围混合分片这3种。


1)根据范围分片:比如user_ID是自增型数字,把user_ID按照每100万份分为一个库,每10万份分为一个表的形式进行分片,见表3-6。


网络异常,图片无法展示
|


2)根据Hash值分片:指的是根据user_ID的Hash值mod(取模)一个特定的数进行分片(为了方便后续扩展,一般是2n)。



3)根据Hash值及范围混合分片:先按照范围分片,再根据Hash值取模分片。比如,表名=order_#user_ID% 10#_#hash(user_ID)%8,即分成了10×8=80个表,如图3-4所示。


网络异常,图片无法展示
|
因此,根据Hash值分片时,一般建议拆分成2n个表。比如分成8张表,数据迁移时把原来的每张表拆一半出来组成新表,这样数据迁移量就小了。

当初的方案中,就是根据user_ID的Hash值按32取模,把数据分到32个数据库中,每个数据库再分成16张表。简单计算一下,假设每天订单量为1000万,则每个库日增1000万/16=31.25万,每个表日增1000万/32/16=1.95万,3年后每个表的数据量就是2000万左右,仍在可控范围内。


2.3 业务代码如何修改


分片策略确定后,就要考虑业务代码如何修改了。因业务代码修改与业务强关联,所以该项目采用的方案不具备通用性,这里就没有列出来。


1)如果使用微服务,对于特定表的分表分库,其影响面只为该表所在的服务,而如果是一个单体架构的应用做分表分库,那会很麻烦。因为单体架构里面会有很多的跨表关联查询,也就是说,很多地方会直接与订单表一起进行Join查询,这种情况下,要想将订单数据拆分到多个库、多个表中,修改的代码就会非常多。

2)在互联网架构中,基本不使用外键约束。

3)分库分表以后,与订单有关的一些读操作都要考虑对应的数据是在哪个库哪个表。可以的话,尽量避免跨库或跨表查询

4)一般来说,除了业务代码需要修改以外,历史数据的迁移也是一个难点。


2.4 历史数据如何迁移


历史数据的迁移非常耗时,迁移几天几夜都很正常。而在互联网行业中,别说几天几夜,就算停机几分钟,业务都可能无法接受,这就要求给出一个无缝迁移的解决方案。


讲解查询分离时提过一个方案,就是监控数据库变更日志,将数据库变更的事件变成消息,存到消息系统,然后有个消费者订阅消息,再将变动的数据同步到查询数据库,如图3-5所示。


网络异常,图片无法展示
|


历史数据迁移就可以采用类似的方案,如图3-6所示。


网络异常,图片无法展示
|


此数据迁移方案的基本思路为:旧架构继续运行,存量数据直接迁移,增量数据监听binlog,然后通过canal通知迁移程序迁移数据,等到新的数据库拥有全量数据且校验通过后再逐步切换流量到新架构。


数据迁移解决方案的详细步骤如下。


1)上线canal,通过canal触发增量数据的迁移。

2)迁移数据脚本测试通过后,将老数据迁移到新的分表分库中。

3)注意迁移增量数据与迁移老数据的时间差,确保全部数据都被迁移过去,无任何遗漏。

4)此时新的分表分库中已经拥有全量数据了,可以运行数据验证程序,确保所有数据都存放在新数据库中。到这里数据迁移就算完成了,之后就是新版本代码上线,至于是灰度上线还是直接上线,需要根据实际情况决定,回滚方案也是一样。


2.5 未来的扩容方案是什么


随着业务的发展,如果原来的分片设计已经无法满足日益增长的数据量的需求,就需要考虑扩容了。扩容方案主要依赖以下两点。


1)分片策略是否可以让新表数据的迁移源只有一个旧表,而不是多个旧表?这就是前面建议使用2n分表的原因——以后每次扩容都能扩为2倍,都是把原来一张表的数据拆分到两张表中

2)数据迁移。需要把旧分片的数据迁移到新的分片上,这个方案与上面提及的历史数据迁移一样,此处不再赘述。


2.6 该方案一些不足之处。


1)复杂查询慢:很多查询需要跨订单数据库进行,然后再组合结果集,这样的查询比较慢。业界的普遍做法是前面提到的查询分离。第2章讲了单独使用Elasticsearch做查询分离的方案,这里分表分库的二期项目也进行了查询分离,只是查询数据存到了Elasticsearch和HBase中。Elasticsearch存放订单ID、用来查询关键字的字段以及查询页面列表里用到的字段,HBase存放订单的全量数据。 Elasticsearch先根据用户的查询组合返回查询结果到查询页面。用户点击特定的订单,就能根据订单ID去HBase获取订单的全量数据。

2)增量数据迁移的高可用性和一致性:如果是自己编写迁移的代码,那就参考前面冷热分离和查询分离的迁移逻辑;也可以使用开源工具,这个方案在后面数据同步的场景中会单独展开。

3)短时订单量大爆发:分表分库可以解决数据量大的问题,但是如果瞬时流量非常大,数据库撑不住怎么办?这一问题会在后面的缓存和秒杀架构等场景中专门展开。


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
5月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
693 6
|
6月前
|
关系型数据库 MySQL 数据管理
Mysql基础学习day03-作业
本内容包含数据库建表语句及多表查询示例,涵盖内连接、外连接、子查询及聚合统计,适用于员工与部门数据管理场景。
118 1
|
6月前
|
SQL 关系型数据库 MySQL
Mysql基础学习day01
本课程为MySQL基础学习第一天内容,涵盖MySQL概述、安装、SQL简介及其分类(DDL、DML、DQL、DCL)、数据库操作(查询、创建、使用、删除)及表操作(创建、约束、数据类型)。适合初学者入门学习数据库基本概念和操作方法。
236 6
|
6月前
|
SQL 关系型数据库 MySQL
Mysql基础学习day02-作业
本教程介绍了数据库表的创建与管理操作,包括创建员工表、插入测试数据、删除记录、更新数据以及多种查询操作,涵盖了SQL语句的基本使用方法,适合初学者学习数据库操作基础。
142 0
|
6月前
|
SQL 关系型数据库 MySQL
Mysql基础学习day03
本课程为MySQL基础学习第三天内容,主要讲解多表关系与多表查询。内容涵盖物理外键与逻辑外键的区别、一对多、一对一及多对多关系的实现方式,以及内连接、外连接、子查询等多表查询方法,并通过具体案例演示SQL语句的编写与应用。
182 0
|
6月前
|
SQL 关系型数据库 MySQL
Mysql基础学习day01-作业
本教程包含三个数据库表的创建练习:学生表(student)要求具备主键、自增长、非空、默认值及唯一约束;课程表(course)定义主键、非空唯一字段及数值精度限制;员工表(employee)包含自增主键、非空字段、默认值、唯一电话号及日期时间类型字段。每个表的结构设计均附有详细SQL代码示例。
119 0
|
6月前
|
SQL 关系型数据库 MySQL
Mysql基础学习day02
本课程为MySQL基础学习第二天内容,涵盖数据定义语言(DDL)的表查询、修改与删除操作,以及数据操作语言(DML)的增删改查功能。通过具体SQL语句与实例演示,帮助学习者掌握MySQL表结构操作及数据管理技巧。
193 0
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
1247 56
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
741 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
2951 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库

推荐镜像

更多