从零到一学习中间件之Sharding-JDBC
Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。
ShardingSphere 源码地址:https://github.com/apache/shardingsphere
ShardingSphere 官方网站:https://shardingsphere.apache.org
文章描述 ShardingSphere 相关概念和知识,如无特别声明,均是 Apache ShardingSphere 5.3.2 版本。
🔥 SpringBoot Ladder:从零到一学习 SpringBoot 各种组件框架实战的项目,让 Demo 变得简单。咱们文章中的 ShardingSphere 示例也在这个项目。
分库分表背景
传统的将数据集中存储至单一节点的解决方案,在性能、可用性和运维成本这三方面已经难于满足海量数据的场景。
从性能方面来说,由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁盘访问的 IO 次数增加,进而导致查询性能的下降; 同时,高并发访问请求也使得集中式数据库成为系统的最大瓶颈。
从可用性的方面来讲,服务化的无状态性,能够达到较小成本的随意扩容,这必然导致系统的最终压力都落在数据库之上。 而单一的数据节点,或者简单的主从架构,已经越来越难以承担。数据库的可用性,已成为整个系统的关键。
从运维成本方面考虑,当一个数据库实例中的数据达到阈值以上,对于 DBA 的运维压力就会增大。 数据备份和恢复的时间成本都将随着数据量的大小而愈发不可控。一般来讲,单一数据库实例的数据的阈值在 1TB 之内,是比较合理的范围。
在传统的关系型数据库无法满足互联网场景需要的情况下,将数据存储至原生支持分布式的 NoSQL 的尝试越来越多。 但 NoSQL 对 SQL 的不兼容性以及生态圈的不完善,使得它们在与关系型数据库的博弈中始终无法完成致命一击,而关系型数据库的地位却依然不可撼动。
数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据 库或表中以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行分库和分表。分库和分表均可以有效的避免由数据量超过可承受阈值而产生的查询瓶颈。 除此之外,分库还能够用于有效的分散对数据库单点的访问量;分表虽然无法缓解数据库压力,但却能够提供尽量将分布式事务转化为本地事务的可能,一旦涉及到跨库的更新操作,分布式事务往往会使问题变得复杂。 使用多主多从的分片方式,可以有效的避免数据单点,从而提升数据架构的可用性。
通过分库和分表进行数据的拆分来使得各个表的数据量保持在阈值以下,以及对流量进行疏导应对高访问量,是应对高并发和海量数据系统的有效手段。 数据分片的拆分方式又分为垂直分片和水平分片。
分库分表介绍
1. 什么是分库分表?
分库分表是一种数据库分片技术,用于解决大规模应用中单一数据库容量不足以支持高并发和大数据量的问题。它将一个大型的数据库拆分成多个小型数据库,每个小型数据库称为一个分片。每个分片存储部分数据,从而降低了单个数据库的负担。
简单来说,分库是将原本的单库拆分为多个库,分表是将原来的单表拆分为多个表。
很多情况下,分库分表并不是从系统设计开始就存在的,而是系统运行过程中,出现数据量庞大或者查 询性能慢等问题延伸而来。
如果你在业务功能开发时,已经预知业务数据库量,应提前进行分库或者分表,做好分片规范,避免系统运行时拆分。
1.1 什么是分库?
1)垂直分片
比如:电商库 mall_db,业务拆分后就是 user_db、order_db、pay_db...
按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。
优点:
- 可以针对不同业务场景优化数据库,提高性能。
- 提高了数据库的并发能力。
缺点:
- 需要处理分布式事务的问题。
- 增加了系统的复杂度。
2)水平分片
比如:用户库 user_db,分片库后就是 user_db_0、user_db_1、user_db_xx。
水平分片又称为横向拆分。 相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。 例如:根据主键分片,偶数主键的记录放入 0 库(或表),奇数主键的记录放入 1 库(或表),如下图所示。
优点:
- 提高了单库的读写性能,降低了单库数据量。
- 可以将库存储在不同的物理服务器上,提高了查询效率。
缺点:
- 需要处理跨库查询的问题。
- 对分库规则的设计需要谨慎,避免热点数据集中在某个库中。
1.2 什么是分表?
1)垂直分片
比如:订单表 order_table,拆分后就是 order_table 以及 order_ext_table。
同分库的概念,只不过将数据库维度降低为数据库表维度。
优点:
- 拆分后每个表的数据量变小,查询时涉及的磁盘 I/O 次数相对减少,提高了查询效率。
- 每个小表的并发写入操作相对较少,减少了数据库锁的竞争,提高了并发能力。
缺点:
- 需要在应用层面处理跨表查询的逻辑,增加了开发的复杂性。
- 如果一个事务涉及多个小表,可能需要在应用层面进行事务管理,增加了代码的复杂性。
- 需要额外的措施来保证拆分后的小表之间的数据一致性。
2)水平分片
比如:订单表 order_table,拆分后就是 order_table_0、 order_table_1、order_table_xxx。
同分库的概念,只不过将数据库维度降低为数据库表维度。
优点:
-
可以根据数据量的增长动态地增加分表,从而扩展数据库的存储能力。
-
每个小表的数据量减少,可以提高查询速度,尤其是在频繁查询的场景下。
-
拆分后,每个小表的并发写入操作相对减少,降低了数据库锁的竞争,提高了并发性能。
缺点:
- 对业务存在一定限制,如果没有按照分片键查询,会造成读扩散问题。
- 对分表规则的设计需要谨慎,避免热点数据集中在某个表中。
2. 分库分表场景
2.1 什么场景分表?
数据量过大或者数据库表对应的磁盘文件过大。
Q:多少数据量进行分表?
A:单表 1000w 是否要分表?回答不够标准。假设一个表里 15 个字段,没有特别大的值(不包含 text 或其它超长度的列)数据量超过 5000 万了,依然很丝滑,因为走索引。
真正需要考虑的是:业务的增长量以及历史数量。
Q:物理文件过大,会有什么问题?
A:会影响公司对数据库表的一个备份。数据库表文件过大,也间接证明表数据过大,增加或删除字段导致锁表的时间过长。
2.2 什么场景分库?
当数据库的连接不够客户端使用时,可以考虑分库或读写分离。
如果说当数据库的 QPS 越来越高以及数据量越来越大的时候,就需要考虑分库分表。
Q:为什么说连接不够用?
A:假设 MySQL Server 能支持 4000 个数据库连接。我们有 10 个服务,40 个节点,一个节点呢数据库连接池最多 10 个。这样就把一个 MySQL Server 的连接数压榨干净了。
当 MySQL 连接不够用时,可能会报错 "Too many connections" 或者类似的错误。这是因为 MySQL 服务器同时可以处理的连接数量是有限制的,当连接数达到这个限制时,服务器就会拒绝新的连接请求,并返回这个错误消息。
2.3 什么场景分库分表?
- 高并发写入场景:当应用面临高并发的写入请求时,单一数据库可能无法满足写入压力,此时可以将数据按照一定规则拆分到多个数据库中,每个数据库处理部分数据的写入请求,从而提高写入性能。
- 数据量巨大场景:随着数据量的不断增加,单一数据库的存储和查询性能可能逐渐下降。此时,可以将数据按照一定的规则拆分到多个表中,每个表存储部分数据,从而分散数据的存储压力,提高查询性能。
什么是 ShardingSphere
Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。
Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的标准和生态。 它关注如何充分合理地利用数据库的计算和存储能力,而并非实现一个全新的数据库。 它站在数据库的上层视角,关注它们之间的协作多于数据库自身。
ShardingSphere 有两个产品在企业中广泛使用,分别是 ShardingSphere-JDBC 以及 ShardingSphere-Proxy。
1. ShardingSphere-JDBC
ShardingSphere-JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 Jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
- 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC;
- 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;
- 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库。
2. ShardingSphere-Proxy
ShardingSphere-Proxy 定位为透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持。 目前提供 MySQL 和 PostgreSQL 协议,透明化数据库操作,对 DBA 更加友好。
- 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用;
- 兼容 MariaDB 等基于 MySQL 协议的数据库,以及 openGauss 等基于 PostgreSQL 协议的数据库;
- 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端,如:MySQL Command Client, MySQL Workbench, Navicat 等。
3. 混合部署
ShardingSphere-JDBC 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用; ShardingSphere-Proxy 提供静态入口以及异构语言的支持,独立于应用程序部署,适用于 OLAP 应用以及对分片数据库进行管理和运维的场景。
Apache ShardingSphere 是多接入端共同组成的生态圈。 通过混合使用 ShardingSphere-JDBC 和 ShardingSphere-Proxy,并采用同一注册中心统一配置分片策略,能够灵活的搭建适用于各种场景的应用系统,使得架构师更加自由地调整适合于当前业务的最佳系统架构。
4. 产品功能
这里给大家列一些经常使用且入门门槛较低的功能,更多的功能大家可以去 ShardingSphere 官网发掘。
特性 | 定义 |
---|---|
数据分片 | 数据分片,是应对海量数据存储与计算的有效手段。ShardingSphere 基于底层数据库提供分布式数据库解决方案,可以水平扩展计算和存储。 |
读写分离 | 读写分离,是应对高压力业务访问的手段。基于对 SQL 语义理解及对底层数据库拓扑感知能力,ShardingSphere 提供灵活的读写流量拆分和读流量负载均衡。 |