目录
面临问题:
我们的海量数据存储在数据库中,随着表中数据的增多,也会衍生出各种相关问题。其中包括性能瓶颈、存储限制、难以水平扩展、维护难度、查询性能下降以及数据安全等方面。为了在海量数据和高并发环境下提升性能,可以采用分库分表的数据库架构。
分库分表的概念:
分库分表见名知意,就是将一个较大的数据库或者数据库表进行划分成若干个较小的数据库和数据库表。在本项目中使用的是水平分表,将一张较大的表分成若干个小型表,提高了数据库的可扩展性,同时降低了单一数据库的负担。这有助于改善系统的读写性能,提高并发处理能力,并更好地适应系统的快速发展。
分库分表的两种模式:
分库和分表有两种模式,垂直和水平。
分库:
垂直分库:将一个数据库中的表进行区分成多个小型存储单一的数据库,比如一个电商数据库,拆分为用户、订单、商品、交易等数据库。
水平分库:将一个数据库中的数据进行水平划分,拆分成多个相同结构的数据库进行存储。
分表:
垂直分表:将数据库表按照业务维度进行拆分,将不常用的信息放到一个扩展表
水平分表:将用户表水平拆分,拆分成n个结构相同的表。
逻辑表:相同结构的水平拆分数据库(表)的逻辑名称,是 SQL 中表的逻辑标识。(就是总表---我们在使用的时候都是使用逻辑表,它自动会为我们计算真实表号)
真实表:在水平拆分的数据库中真实存在的物理表。(数据库中的表)
如何选择分库和分表?
分表的核心触发条件是:
单表数据量 / 磁盘文件大小达到数据库性能阈值(如千万级行、GB 级文件),导致查询 / 写入延迟显著升高;
采取分库的核心是:
解决数据库连接数不足问题(如多服务节点占用连接超出 MySQL Server 承载上限),突破连接资源限制;
采用分库分表是:
为了适配高并发读写或数据量极致庞大的场景,可同时解决连接不足与单表性能差的双重问题。
分库分表框架:
Apache ShardingSphere 有两款产品,分别是 ShardingSphere-JDBC 和 ShardingSphere-Proxy 两款产品,分别对应上述两种使用方式。MyCat 对应第二种方式。在本项目中使用的是第一种ShardingSphere-JDBC进行分表
如何实现:
1、引入依赖:
java
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.3.2</version>
</dependency>
2、配置文件路径:
application.yml文件:
java
spring:
datasource:
# ShardingSphere 对 Driver 自定义,实现分库分表等隐藏逻辑
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
# ShardingSphere 配置文件路径
url: jdbc:shardingsphere:classpath:shardingsphere-config-${database.env:dev}.yaml
3、配置分片规则:
shardingsphere-config.yaml
java
# 数据源集合
dataSources:
ds_0:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://127.0.0.1:3306/link?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: root
rules:
- !SHARDING
tables:
t_user:
# 真实数据节点,比如数据库源以及数据库在数据库中真实存在的
actualDataNodes: ds_0.t_user_${0..15}
# 分表策略
tableStrategy:
# 用于单分片键的标准分片场景
standard:
# 分片键
shardingColumn: username
# 分片算法,对应 rules[0].shardingAlgorithms
shardingAlgorithmName: user_table_hash_mod
# 分片算法
shardingAlgorithms:
# 数据表分片算法
user_table_hash_mod:
# 根据分片键 Hash 分片
type: HASH_MOD
# 分片数量
props:
sharding-count: 16
# 展现逻辑 SQL & 真实 SQL
props:
sql-show: true
上述分表规则是每一个分表进行一次配置,分片键的选择是是重中之重。
分片键的选择:
分片键的选择是重中之重,因为是根据分片键的值 进行选择那个分表,分片键的选择要从业务出发,比如短链接项目中的short_link表,选择的分片键就是gid作为分片键,为什么选择gid作为分片键?因为在我们的业务中短链接全部是放在分组下边的,每一个短链接都会绑定一个gid的。有人会问我们为什么不直接选择完整短链接 作为分片键,那么进行分组查询的时候就需要遍历全表以及查找短链接对应的原始链接进行跳转,也会出现读扩散 问题。(分组查询在业务中是经常需要使用的,因为短链接全部是挂在分组下边,所以经常需要分组查询)。但是我们使用gid作为分片键,我们在需要修改短链接相关信息的时候(不一定是在修改短链接本身,可能是在修改监控信息--访问即修改)只有一个短链接是是无法直接定位到该短链接的信息是在哪一个分表下,所以就需要创建一个路由表,建立起来短链接和gid的映射关系。因为路由表的存储的数据量和short_link表的数据量是一样的,所以路由表也要进行分表,但是它的分片键就要是完整短链接,因为我们要快速通过短链接找到对应的gid,所以要使用完整短链接作为分片键。实现查找逻辑:通过短链接查找路由表,通过路由表找到对应的gid,再通过gid去查找short_link表。
短链接项目可以存储多少数据?
在项目中链接表我们是分表为了16张表,假设一张表可以存储2000万条数据,16张表我们就可以存储3 亿两千万条数据。