1、什么时候要进行分库分表
引用《阿里巴巴Java开发手册》
2、分库分表概念
2.1 垂直分库:
垂直拆分的原则一般是按照业务类型来拆分,核心思想是专库专用,将业务耦合度比较高的表拆分到单独的库中。举个形象的例子就是在整理衣服的时候,将羽绒服、毛衣、T 恤分别放在不同的格子里。这样可以解决我在开篇提到的第三个问题:把不同的业务的数据分拆到不同的数据库节点上,这样一旦数据库发生故障时只会影响到某一个模块的功能,不会影响到整体功能,从而实现了数据层面的故障隔离。
2.2 水平分库:
水平分库主要是解决库中数据量过大造成效率低下的问题,例如某个商城系统,通过垂直分库后,拆分为用户库,订单库,商品库等等。 随着业务增长,订单库的数据暴增,此时就要对订单库进行水平拆分,将订单库拆分为多个。
2.3 垂直分表:
对于字段过多的表,例如商品表,拆分为商品基础信息表和商品详细信息表。
2.4 水平分表:
与水平分库类似,解决单表数据量过大的问题。
3、水平拆分方法
3.1 取模法
例如订单表拆分为10份,分别为 t_order0、t_order1 … t_order9
根据订单ID对10取模后结果,拆分。此时订单ID就是分区键
当查询中包含分区键时,例如select * from t_order WHERE order_id = xxxxx。可以确定数据到底时再哪个表中。
当查询中不包含分区键时候,例如查询某个用户的订单列表。 select * from t_order WHERE user_id = xxxxx 此时无法确定数据在哪个表中,所以要进行全表搜索,然后再将数据汇总。
3.2 范围法
将订单表按照订单创捷时间所在月份拆分为 t_order202001 t_order202002 t_order202003 等等
4、实现方式
4.1 客户端实现
客户端对sql解析后,根据配置好的规则,将sql进行改写后转发到不同的数据库
例如 SELECT * from t_order WHERE order_id = 1232345431234
客户端流程大致如下
1、路由:根据配置规则,确定order_id = 1232345431234 这条数据在 1号库的 t_order9 中
2、执行,如果路由后确定不了具体在哪个库或表,请求会在所有库或表中查询
3、汇总返回结果
实现方案:sharding-jdbc 等
4.2 数据库中间件
客户端代码无需改变,将数据源配置为数据库中间件即可,由中间件路由执行后返回结果
实现方案 mycat 等
5、sharding-jdbc 示例
pom , 注意druid不要引用为druid-spring-boot-starter。 因为数据源配置在shardingsphere的配置中,druid-spring-boot-starter初始化时找不到数据源配置会报错
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
spring:
shardingsphere:
# 数据源配置
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.01:3306/sharding1?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
ds1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.01:3306/sharding2?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
sharding:
# 绑定表配置,如果一组表分区键相同,则互为绑定表,每组表用,分割
binding-tables:
- t_order
# 广播表,所有数据源中都有的表,修改删除请求会广播,查询请求随意选择某个数据源
broadcast-tables: t_config
# 默认数据源
default-data-source-name: ds0
# 分表规则
tables:
# t_order表分表规则
t_order:
# 数据节点配置
actual-data-nodes: ds$->{0..1}.t_order$->{0..3}
table-strategy:
# 自定义分表逻辑
#standard:
#sharding-column: orderno
#preciseAlgorithmClassName: com.zql.sharding.shardingdemo.OrderTableStrategy
# inline表达式配置分表逻辑
inline:
# 按照orderno取模分表
sharding-column: orderno
algorithm-expression: t_order$->{orderno % 4}
# 分库规则
database-strategy:
inline:
# 按照user_id取模分库
sharding-column: user_id
algorithm-expression: ds$->{user_id % 2}
# 主键生成策略
#key-generator:
#column: orderno
#type: SNOWFLAKE
props:
sql:
show: true