一:分库分表介绍
1.1什么是分库分表?
分库分表本质上就是为了解决由于库表数据量过大而导致数据库性能降低的问题; 核心操作:
- 将原来独立的数据库拆分成若干数据库组成;
- 将原来的大表(存储近千万数据的表)拆分成若干个小表;
目的:使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的;
1.2数据库访问变慢原因分析
- 在系统应用中关系型数据库本身比较容易成为系统瓶颈(I/O),比如:单机存储容量、数据库连接数、处理能力等都有上限;
- 当单表的数据量达到1000W或100G以后(大表),即使做了优化索引等操作,查询性能仍会下降严重,更不要说复杂的多表关联查询了;
- 对于商家模块来说,当数据量过大是,会存在大表关联查询,导致查询性能急剧下降!尽量避免大表的关联查询-查询优化-反三大范式
1.3数据库优化
优化数据库要从硬件和软件层面优化:
- 硬件层面
- 提升服务器硬件能力来提高数据处理能力,比如增加存储容量 、CPU等;
- 提升硬件配置相对成本较高,且如果瓶颈在MySQL本身那么提高硬件带来的性能提升也是有限的;
- 软件层面
- 把大量数据分散在不同的数据库中,使得单一数据库的数据量变小来缓解单一数据库的性能问题;
- 把大表拆分成若干小表,解决单张大表查询性能问题;
- 对于关系型数据库来说,磁盘I/O会成为其瓶颈,通过缓存热点数据,在一定程度来可提升系统性能;
二:分库分表方式
分库分表包括分库和分表两个部分,在生产中通常包括:垂直分库、水平分库、垂直分表、水平分表四种方式;
2.1垂直分表
2.1.1垂直分表定义
- 垂直分表就是在同一数据库内将一张表按照指定字段分成若干表,每张表仅存储其中一部分字段;
- 垂直分表拆解了原有的表结构,拆分的表之间一般是一对一的关系;
2.1.2垂直分表优势
- 充分提高了热点数据的操作效率,商品信息的操作的高效率不会被商品描述的低效率所拖累(冷热数据分离);
- 避免了IO过度争抢并减少锁表的几率,查看商品详情的用户与商品信息浏览互不影响;
2.1.3垂直分表原则
- 把不常用的字段单独放在一张表;(因为数据库加载数据时,会将表整整行的信息加载)
- 把text(大文本存储),blob(图片、视频类存储)等大字段拆分出来放在附表中(阿里开发手册严禁使用text等大字段);
- 经常组合查询的列放在一张表中,避免多表联查,性能最高;
2.2垂直分库
2.2.1垂直分库定义
垂直分库是指按照业务将表进行归类,然后把不同类的表分布到不同的数据库上面,而每个库又可以放在不同的服务器上,它的核心理念是-专库专用;
2.2.2垂直分库优势
- 通过不同表的业务聚合(聚合为库),使得数据库维护更加清晰;
- 能对不同业务的数据进行分级管理、维护、监控、扩展等;
- 高并发场景下,垂直分库在一定程度上提高了磁盘IO和数据库连接数,并改善了单机硬件资源的瓶颈问题;
2.3水平分表
2.3.1水平分表定义
- 水平分表就是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中,表的结构没有变化;
- 水平分表解决单表数据量大的问题
2.3.2水平分表优势
水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中,它带来的提升是:
- 优化单一表数据量过大而产生的性能问题;
- 避免IO争抢并减少锁表的几率;
整体看,水平分表仅仅解决了单表数据量过大的问题,但是没有解决单库数据量过大的问题;
2.4水平分库
2.4.1水平分库定义
- 水平分库可以看做是水平分表的进一步拆分,是把同一个表的数据按一定规则拆到不同的数据库中,每个库又可以部署到不同的服务器上;
- 水平分库解决了单库数据量大的问题,突破了服务器物理存储的瓶颈;
2.4.2水平分库优势
水平分库带来的提升是:
- 解决了单库大数据,高并发的性能瓶颈问题;
- 提高了系统的稳定性及可用性;
总之,当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平分库了,经过水平切分的优化,往往能==解决单库存储量及性能瓶颈==。但由于同一个表被分配在不同的数据库,需要额外进行数据操作的路由工作,因此大大提升了系统复杂度。
虽然分库分表能有效的缓解了单机和单库带来的性能瓶颈和压力,突破网络IO、硬件资源、连接数的瓶颈,同时也带来了一些问题。
分布式事务一致性问题
跨节点关联查询
跨节点分页、排序函数
主键避重
公共表(小数据量的表且经常使用,可能存在联查的情况)
显然如果我们自己去解决上述问题,开发工作量较大,所以我们就有必要学习一种支持分库分表特性的技术:sharding-jdbc、mycat等;
三:sharding-JDBC入门
3.1ShardingSphere
Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,核心由: JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成;
功能特性:它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。
官方网站:Apache ShardingSphere
文档地址:概览 :: ShardingSphere
本教程主要介绍:Sharding-JDBC;
Sharding-jdbc是ShardingSphere的其中一个模块,定位为==轻量级Java框架==,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
- 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
- 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
- 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
Sharding-JDBC的核心功能为数据分片和读写分离,通过Sharding-JDBC,应用可以透明的使用jdbc访问已经分库分表、读写分离的多个数据源,而不用关心数据源的数量以及数据如何分布。
3.2sharding-jdbc相关名词解释
参考官网-核心概念
- 逻辑表(LogicTable):进行水平拆分的时候同一类型(逻辑、数据结构相同)的表的总称。例:用户数据根据主键尾数拆分为2张表,分别是tab_user_0到tab_user_1,他们的逻辑表名为tab_user。
- 真实表(ActualTable):在分片的数据库中真实存在的物理表。即上个示例中的tab_user_0到tab_user_1。
- 数据节点(DataNode):数据分片的最小单元。由数据源名称和数据表组成,例:spring-boot_0.tab_user_0,spring-boot_0.tab_user_1,spring-boot_1.tab_user_0,spring-boot_1.tab_user_1。说白了,具体到指定库下的指定表就是一个数据节点;
- 动态表(DynamicTable):逻辑表和物理表不一定需要在配置规则中静态配置。如,按照日期分片的场景,物理表的名称随着时间的推移会产生变化(股票流水)。
- 广播表(公共表):指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。
- 分片键(ShardingColumn):分片字段用于将数据库(表)水平拆分的字段,支持单字段及多字段分片。例如上例中的order_id。一般在业务中经常查询使用的字段会作为分片键;
3.3 sharding-jdbc的执行原理
3.4sharding-jdbc分片方式
3.4.1inline模式
- 使用最简单,开发成本比较低;
- 只能使用单个字段作为分片键;
- 基于行表达式定义分片规则;
通过groovy表达式来表示分库分表的策略;
db0
├── t_order0
└── t_order1
db1
├── t_order0
└── t_order1
表达式:db${0..1}.t_order${0..1}
t_order${orderId % 2}
3.4.2standard标准分片模式
- 用户可通过代码自定义复杂的分片策略;
- 同样只能使用单个字段作为分片键;
3.4.3complex复合分片模式
- 用于多分片键的复合分片策略(多片键)
3.4..4Hint强制分片模式
- 不指定片键,通过代码动态指定路由规则
- 强制分片策略(强制路由)
四:总结
分库分表方式:垂直分表、垂直分库、水平分库和水平分表
垂直分表:可以把一个宽表的字段按访问频次、是否是大字段的原则拆分为多个表,这样既能使业务清晰,还能提升部分性能。拆分后,尽量从业务角度避免联查,否则性能方面将得不偿失【同一库中将单张表按照字段拆分成若干表,拆分后表的记录行数不变】。
垂直分库:可以把多个表按业务耦合松紧归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同时能提高整体架构的业务清晰度,不同的业务库可根据自身情况定制优化方案。但是它需要解决跨库带来的所有复杂问题。 【根据业务将表分组形成不同的库,这些库又可以部署到不同的数据库中-专库专用】
水平分表:可以把一个表的数据(按数据行)分到多个同一个数据库的多张表中,每个表只有这个表的部分数据,这样做能小幅提升性能,它仅仅作为水平分库的一个补充优化。【同一数据库中将大表拆分成若干小表,每张表的结构一致,但保存的数据不同】
水平分库:可以把表的数据(按数据行)分 到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能。它不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(数据路由问题后边介绍)。
最佳实践:
一般来说,在系统设计阶段就应该根据业务耦合松紧来确定垂直分库,垂直分表方案。当然在数据量及访问压力不是特别大的情况,首先考虑缓存、读写分离、索引技术等方案。若数据量极大,且持续增长,再考虑水平分库水平分表方案。
总之,基于开发和维护成本比考虑,非必须,不要对数据库做分库分表处理!