一文快速入门分库分表(必修课)

简介: 面试高频题

大家好,我是小富~

之前有不少刚入坑 Java 的粉丝留言,想系统的学习一下分库分表相关技术,可我一直没下定决心搞,眼下赶上公司项目在使用 sharding-jdbc 对现有 MySQL 架构做分库分表的改造,所以借此机会出一系分库分表落地实践的文章,也算是自己对架构学习的一个总结。

我在网上陆陆续续的也看了一些有关于分库分表的文章,可发现网上同质化的资料有点多,而且知识点又都比较零碎,还没有详细的实战案例。为了更深入的学习下,我在某些平台买了点付费课程,看了几节课发现有点经验的人看还可以,但对于新手入门来说,其实学习难度还是蛮大的。

为了让新手也能看得懂,有些知识点我可能会用更多的篇幅加以描述,希望大家不要嫌我啰嗦,等这分库分表系列文章完结后,我会把它做成 PDF 文档开源出去,能帮一个算一个吧!如果发现文中有哪些错误或不严谨之处,欢迎大家交流指正。

具体实践分库分表之前在啰嗦几句,回头复习下分库分表的基础概念。

什么是分库分表

其实 分库分表 是两个概念,只不过通常分库与分表的操作会同时进行,以至于我们习惯性的将它们合在一起叫做分库分表。

分库分表是为了解决由于库、表数据量过大,而导致数据库性能持续下降的问题。按照一定的规则,将原本数据量大的数据库拆分成多个单独的数据库,将原本数据量大的表拆分成若干个数据表,使得单一的库、表性能达到最优的效果(响应速度快),以此提升整体数据库性能。

如何分库分表

分库分表的核心理念就是对数据进行切分(Sharding),以及切分后如何对数据的快速定位与查询结果整合。而分库与分表都可以从:垂直(纵向)和 水平(横向)两种纬度进行切分。

分库分表


下边我们就以订单相关的业务举例,看看如何做库、表的 垂直水平 切分。

垂直切分

垂直切分有 垂直 分库 和 垂直分表。

1、垂直分库

垂直分库相对来说是比较好理解的,核心理念就四个字:专库专用

按业务类型对表进行分类,像订单、支付、优惠券、积分等相应的表放在对应的数据库中。开发者不可以跨库直连别的业务数据库,想要其他业务数据,对应业务方可以提供 API 接口,这就是微服务的初始形态。

垂直分库很大程度上取决于业务的划分,但有时候业务间的划分并不是那么清晰,比如:订单数据的拆分要考虑到与其他业务间的关联关系,并不是说直接把订单相关的表放在一个库里这么简单。

在一定程度上,垂直分库似乎提升了一些数据库性能,可实际上并没有解决由于单表数据量过大导致的性能问题,所以就需要配合水平切分方式来解决。

垂直分库

2、垂直分表

垂直分表是基于数据表的列(字段)为依据切分的,是一种大表拆小表的模式。

例如:一张 order 订单表,将订单金额、订单编号等访问频繁的字段,单独拆成一张表,把 blob 类型这样的大字段或访问不频繁的字段,拆分出来创建一个单独的扩展表 work_extend ,这样每张表只存储原表的一部分字段,再将拆分出来的表分散到不同的库中。

垂直分表

我们知道数据库是以行为单位将数据加载到内存中,这样拆分以后核心表大多是访问频率较高的字段,而且字段长度也都较短,因而可以加载更多数据到内存中,来增加查询的命中率,减少磁盘IO,以此来提升数据库性能。

垂直切分的优点

  • 业务间数据解耦,不同业务的数据进行独立的维护、监控、扩展。
  • 在高并发场景下,一定程度上缓解了数据库的压力。

垂直切分的缺点

  • 提升了开发的复杂度,由于业务的隔离性,很多表无法直接访问,必须通过接口方式聚合数据。
  • 分布式事务管理难度增加。
  • 数据库还是存在单表数据量过大的问题,并未根本上解决,需要配合水平切分。

水平切分

前边说了垂直切分还是会存在单库、表数据量过大的问题,当我们的应用已经无法在细粒度的垂直切分时,
依旧存在单库读写、存储性能瓶颈,这时就要配合水平切分一起了,水平切分能大幅提升数据库性能。

1、水平分库

水平分库是把同一个表按一定规则拆分到不同的数据库中,每个库可以位于不同的服务器上,以此实现水平扩展,是一种常见的提升数据库性能的方式。

这种方案往往能解决单库存储量及性能瓶颈问题,但由于同一个表被分配在不同的数据库中,数据的访问需要额外的路由工作,因此系统的复杂度也被提升了。

例如下图,订单DB_1订单DB_1订单DB_3 三个数据库内有完全相同的表 order,我们在访问某一笔订单时可以通过对订单的订单编号取模的方式 订单编号 mod 3 (数据库实例数) ,指定该订单应该在哪个数据库中操作。

水平分库

2、水平分表

水平分表是在同一个数据库内,把一张大数据量的表按一定规则,切分成多个结构完全相同表,而每个表只存原表的一部分数据。

例如:一张 order 订单表有 900万数据,经过水平拆分出来三个表,order_1order_2order_3,每张表存有数据 300万,以此类推。

水平分表

水平分表尽管拆分了表,但子表都还是在同一个数据库实例中,只是解决了单一表数据量过大的问题,并没有将拆分后的表分散到不同的机器上,还在竞争同一个物理机的CPU、内存、网络IO等。要想进一步提升性能,就需要将拆分后的表分散到不同的数据库中,达到分布式的效果。

分库分表

水平切分的优点:

  • 解决高并发时单库数据量过大的问题,提升系统稳定性和负载能力。
  • 业务系统改造的工作量不是很大。

水平切分的缺点:

  • 跨分片的事务一致性难以保证。
  • 跨库的join关联查询性能较差。
  • 扩容的难度和维护量较大,(拆分成几千张子表想想都恐怖)。

一定规则是什么

我们上边提到过很多次 一定规则 ,这个规则其实是一种路由算法,就是决定一条数据具体应该存在哪个数据库的哪张表里。

常见的有 取模算法范围限定算法

1、取模算法

按字段取模(对hash结果取余数 (hash() mod N),N为数据库实例数或子表数量)是最为常见的一种切分方式。

还拿 order 订单表举例,先对数据库从 0 到 N-1进行编号,对 order 订单表中 work_no 订单编号字段进行取模,得到余数 ii=0存第一个库,i=1存第二个库,i=2存第三个库....以此类推。

这样同一笔订单的数据都会存在同一个库、表里,查询时用相同的规则,用 work_no 订单编号作为查询条件,就能快速的定位到数据。

优点:

  • 数据分片相对比较均匀,不易出现请求都打到一个库上的情况。

缺点:

  • 这种算法存在一些问题,当某一台机器宕机,本应该落在该数据库的请求就无法得到正确的处理,这时宕掉的实例会被踢出集群,此时算法变成hash(userId) mod N-1,用户信息可能就不再在同一个库中了。

2、范围限定算法

按照 时间区间ID区间 来切分,比如:我们切分的是用户表,可以定义每个库的 User 表里只存10000条数据,第一个库只存 userId 从1 ~ 9999的数据,第二个库存 userId 为10000 ~ 20000,第三个库存 userId 为 20001~ 30000......以此类推,按时间范围也是同理。

优点:

  • 单表数据量是可控的
  • 水平扩展简单只需增加节点即可,无需对其他分片的数据进行迁移
  • 能快速定位要查询的数据在哪个库

缺点:

  • 由于连续分片可能存在数据热点,比如按时间字段分片,可能某一段时间内订单骤增,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询。

分库分表的难点

1、分布式事务

由于表分布在不同库中,不可避免会带来跨库事务问题。一般可使用 "三阶段提交 "和 "两阶段提交" 处理,但是这种方式性能较差,代码开发量也比较大。通常做法是做到最终一致性的方案,如果不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,采用事务补偿的方式。

这里我应用阿里的分布式事务框架Seata 来做分布式事务的管理,后边会结合实际案例。

2、分页、排序、跨库联合查询

分页、排序、联合查询是开发中使用频率非常高的功能,但在分库分表后,这些看似普通的操作却是让人非常头疼的问题。将分散在不同库中表的数据查询出来,再将所有结果进行汇总整理后提供给用户。

3、分布式主键

分库分表后数据库的自增主键意义就不大了,因为我们不能依靠单个数据库实例上的自增主键来实现不同数据库之间的全局唯一主键,此时一个能够生成全局唯一ID的系统是非常必要的,那么这个全局唯一ID就叫 分布式ID

4、读写分离

不难发现大部分主流的关系型数据库都提供了主从架构的高可用方案,而我们需要实现 读写分离 + 分库分表,读库与写库都要做分库分表处理,后边会有具体实战案例。

5、数据脱敏

数据脱敏,是指对某些敏感信息通过脱敏规则进行数据转换,从而实现敏感隐私数据的可靠保护,如身份证号、手机号、卡号、账号密码等个人信息,一般这些都需要进行做脱敏处理。

分库分表工具

我还是那句话,尽量不要自己造轮子,因为自己造的轮子可能不那么圆,业界已经有了很多比较成熟的分库分表中间件,我们根据自身的业务需求挑选,将更多的精力放在业务实现上。

  • sharding-jdbc(当当)
  • TSharding(蘑菇街)
  • Atlas(奇虎360)
  • Cobar(阿里巴巴)
  • MyCAT(基于Cobar)
  • Oceanus(58同城)
  • Vitess(谷歌)

为什么选 sharding-jdbc

sharding-jdbc 是一款轻量级 Java 框架,以 jar 包形式提供服务,是属于客户端产品不需要额外部署,它相当于是个增强版的 JDBC 驱动;相比之下像 Mycat 这类需要单独的部署服务的服务端产品,就稍显复杂了。况且我想把更多精力放在实现业务,不想做额外的运维工作。

  • sharding-jdbc的兼容性也非常强大,适用于任何基于 JDBCORM 框架,如:JPAHibernateMybatisSpring JDBC Template 或直接使用的 JDBC
  • 完美兼容任何第三方的数据库连接池,如:DBCPC3P0BoneCPDruidHikariCP 等,几乎对所有关系型数据库都支持。

不难发现确实是比较强大的一款工具,而且它对项目的侵入性很小,几乎不用做任何代码层的修改,也无需修改 SQL 语句,只需配置待分库分表的数据表即可。

总结

简单的回顾一下分库分表的基础知识,接下来的文章会配合实战项目介绍 sharding-jdbc 在分库分表中的各个功能点。

整理了几百本各类技术电子书,送给小伙伴们。关注公号回复【666】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就加入我们吧!

相关文章
|
7月前
|
存储 分布式计算 大数据
HBase分布式数据库关键技术与实战:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入剖析了HBase的核心技术,包括数据模型、分布式架构、访问模式和一致性保证,并探讨了其实战应用,如大规模数据存储、实时数据分析及与Hadoop、Spark集成。同时,分享了面试经验,对比了HBase与其他数据库的差异,提出了应对挑战的解决方案,展望了HBase的未来趋势。通过Java API代码示例,帮助读者巩固理解。全面了解和掌握HBase,能为面试和实际工作中的大数据处理提供坚实基础。
414 3
|
运维 Oracle 关系型数据库
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
原生分布式关系型数据库OceanBase ,具备多租户、高可用、水平扩展、高性能、低成本、兼容 ORACLE 和 MySQL 六大特点,支撑了支付宝和网商银行全部的核心业务,以及外部银行、保险、证券、运营商、央企等多个行业数百家客户的核心业务系统。OceanBase 在 2021年6月份发布了社区版 3.1,更全面有力的推动数据库生态系统建设。
104291 1
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
|
17天前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
35 4
|
7月前
|
架构师 关系型数据库 分布式数据库
实战秘籍 | 《学姐和你一起学PolarDB-X》课程拓展资料(第二讲)
本期课程,由阿里云的开源架构师——黄心雨学姐为大家带来《使用云起实验室体验PolarDB分布式版》,在课后学姐还精心准备了拓展学习资料,供各位开发者们进一步探索和学习,早日成为数据大师!
|
7月前
|
架构师 开发者
实战秘籍 | 《学姐和你一起学PolarDB-X》课程拓展资料(第一讲)
本期课程,由阿里云的开源架构师——王江颖学姐为大家带来《PolarDB-X的架构介绍》,在课后学姐还精心准备了拓展学习资料,供各位开发者们进一步探索和学习,早日成为数据大师!
|
7月前
|
存储 分布式数据库 数据库
【软件设计师—基础精讲笔记3】第三章 数据库系统
【软件设计师—基础精讲笔记3】第三章 数据库系统
99 0
|
7月前
|
存储 数据采集 数据挖掘
【软件设计师备考 专题 】数据仓库和分布式数据库基础知识
【软件设计师备考 专题 】数据仓库和分布式数据库基础知识
264 0
|
运维 自然语言处理 AliSQL
企业运维训练营之数据库原理与实践— AliSQL和读写分离基本原理—Q&A
企业运维训练营之数据库原理与实践— AliSQL和读写分离基本原理—Q&A
119 0
|
弹性计算 Oracle 关系型数据库
我的云上第一课:MySQL数据库系统实战
基于阿里云计算,完成mysql知识系统练习,完成基于mysql数据库的博客项目。
我的云上第一课:MySQL数据库系统实战
|
关系型数据库 MySQL 物联网
第三期:MySQL数据库进阶实战
第三期:MySQL数据库进阶实战
下一篇
无影云桌面