分库分表策略设计方式及思路梳理

一、什么是分库分表?什么时候要分库分表?   

先将tulingmall-order的jdbc数据源调整到本地,然后在本地数据库中,已经插入了20+W的订单数据,全都是Monkey用户插入的。

调整方法:

1、在启动类上排除掉SpringBootConfiguration.class,这个是ShardingSphere进行分库分表的配置类。@SpringBootApplication(exclude = {SpringBootConfiguration.class})

2、调整配置文件,打开application.yml中的datasource配置。

然后在前端tuling-front用Monkey/123用户登录,进入"我的订单"页面,这个页面可以查询到所有的订单。--页面没有分页,但是能够加载更多的订单。简单分析下这个查询订单的SQL:

       

分库分表策略设计方式及思路梳理_第1张图片

        

查第一页会非常快,只要0.002秒。但是往后翻页时,效率会越来越低。当翻页翻到 10000,10时,执行时间需要3秒多。100000,10时执行时间需要4秒多。

查询会耗时2秒多。而简单执行下面这个SQL语句,会要消耗7秒多。

select * from (

select 1 from oms_order o LEFT JOIN oms_order_item ot on o.id = ot.order_id

) t limit 200000,10

这个时长如果需要响应到页面上,那就已经是无法忍受了。这还只是一个简单的查询,并且返回的数据其实还不多。如果数据更多(比如导出),查询更复杂,并发量更大,那消耗的时间会更长。

单表数据量太大带来的问题还不止是查询变慢,如果数据更多,还很容易造成系统假死。如果我们的订单页面不断的加载订单,那浏览器也会崩溃。

、分库分表的作用   

  • 加大存储,

  • 提升查询效率,

  • 提升数据库的并发能力。

阿里的开发规范中建议预估三年内单表数据量上500W,或者大小上2G,就要考虑分库分表。

三、定制分库分表策略    

定制分库分表策略的注意点:

  • 分库分表一般要在开发之前设计,尽量避免临时设计。只针对最核心的表。

  • 分库分表后,对表的查询必须足够简单,不要有跨表,跨库的复杂查询。

  • 分库和分表尽量同时进行,分库可以分担网络压力。

关于数据分片策略:

  • 分库策略:将核心的订单表和订单物品表从业务库中移出来,单独放到一个库。我们分成两个库。分散网络压力。

  • 分表策略:在每个库分两个表,尽量将数据平均的分配到这四个表中。分散单表查询压力。

考虑的问题:

  • 取模分片能够将数据分配得尽量的平均,但是不利于扩展。

  • 按范围分片便于扩展但是他的数据分布又不够均匀。

  • 是不是可以定制一种分片策略,将这两种分片策略结合起来?比如大尺度上按范围分片,但是在每个数据范围内,使用取模分片。这种分片策略要如何在ShardingSphere中实现?提供思路,留给大家自己实现。

  • 1、回顾下ShardingSphere的几种分片策略实现方式:inline, standard, complex, hint。

  • 2、两个库,四个表。要如何将数据分配均匀?

  • 3、如何定制适合业务场景的数据分片策略?

  • 有哪些常用的数据分片策略?取模分片、按时间范围分片、按业务要素(如地区、前缀等)分片……

主键生成策略:ShardingSphere内置UUID和SNOWFLAKE两种。扩展自定义主键生成策略

# 配置ds0 和ds1两个数据源

spring.shardingsphere.datasource.names=ds,ds0,ds1

#ds1 配置

spring.shardingsphere.datasource.ds.type=com.alibaba.druid.pool.DruidDataSource

spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.cj.jdbc.Driver

spring.shardingsphere.datasource.ds.url=jdbc:mysql://localhost:3306/micromall?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8

#初始连接数

spring.shardingsphere.datasource.ds.initialSize=5

#最小空闲连接数

spring.shardingsphere.datasource.ds.minIdle=10

#最大连接数

spring.shardingsphere.datasource.ds.maxActive=30

spring.shardingsphere.datasource.ds.validationQuery=SELECT 1 FROM DUAL

spring.shardingsphere.datasource.ds.username=root

spring.shardingsphere.datasource.ds.password=root

#ds0 配置

spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource

spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver

spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/micromall_ds_0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8

spring.shardingsphere.datasource.ds0.initialSize=5

spring.shardingsphere.datasource.ds0.minIdle=10

spring.shardingsphere.datasource.ds0.maxActive=30

spring.shardingsphere.datasource.ds0.validationQuery=SELECT 1 FROM DUAL

spring.shardingsphere.datasource.ds0.username=root

spring.shardingsphere.datasource.ds0.password=root

#ds1 配置

spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource

spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver

spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/micromall_ds_1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8

spring.shardingsphere.datasource.ds1.initialSize=5

spring.shardingsphere.datasource.ds1.minIdle=10

spring.shardingsphere.datasource.ds1.maxActive=30

spring.shardingsphere.datasource.ds1.validationQuery=SELECT 1 FROM DUAL

spring.shardingsphere.datasource.ds1.username=root

spring.shardingsphere.datasource.ds1.password=root

# 对于没有做任何业务拆分的表,直接走本默认数据源即可

spring.shardingsphere.sharding.default-data-source-name=ds

spring.shardingsphere.sharding.default-database-strategy.hint.algorithm-class-name=com.tuling.tulingmall.sharding.OrderAllRangeHintAlgorithm

spring.shardingsphere.sharding.default-table-strategy.hint.algorithm-class-name=com.tuling.tulingmall.sharding.OrderAllRangeHintAlgorithm

# oms_order分片策略

# 节点 ds0.oms_order_0,ds0.oms_order_1,ds1.oms_order_0,ds1.oms_order_1

spring.shardingsphere.sharding.tables.oms_order.actual-data-nodes=ds$->{0..1}.oms_order_$->{0..1}

#分库策略

spring.shardingsphere.sharding.tables.oms_order.database-strategy.inline.sharding-column=id

spring.shardingsphere.sharding.tables.oms_order.database-strategy.inline.algorithm-expression=ds$->{id % 2}

# 分表策略

spring.shardingsphere.sharding.tables.oms_order.table-strategy.inline.sharding-column=id

# 注意下,对于除法,groovy会计算出浮点数,而不是整数。即 3/2=1.5,如果需要计算出整数 3.intdiv(2)=1

spring.shardingsphere.sharding.tables.oms_order.table-strategy.inline.algorithm-expression = oms_order_$->{((id+1) % 4).intdiv(2)}

# 复合分片算法

#spring.shardingsphere.sharding.tables.oms_order.table-strategy.complex.sharding-columns=id

#spring.shardingsphere.sharding.tables.oms_order.table-strategy.complex.algorithm-class-name = com.tuling.tulingmall.sharding.OrderComplexShardingAlgorithm

# 使用SNOWFLAKE算法生成主键

spring.shardingsphere.sharding.tables.oms_order.key-generator.column=id

spring.shardingsphere.sharding.tables.oms_order.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.tables.oms_order.key-generator.props.worker.id=123

# 使用自定义主键生成策略

#spring.shardingsphere.sharding.tables.oms_order.key-generator.type=CUSTOM

#spring.shardingsphere.sharding.tables.oms_order.key-generator.props.redis.prefix=order:id:prefix:

# 节点 ds0.oms_order_item_0,ds0.oms_order_item_1,ds1.oms_order_item_0,ds1.oms_order_item_1

spring.shardingsphere.sharding.tables.oms_order_item.actual-data-nodes=ds$->{0..1}.oms_order_item_$->{0..1}

# 分库策略 按order_id分片

spring.shardingsphere.sharding.tables.oms_order_item.database-strategy.inline.sharding-column=order_id

spring.shardingsphere.sharding.tables.oms_order_item.database-strategy.inline.algorithm-expression=ds$->{order_id % 2}

# 分表策略

spring.shardingsphere.sharding.tables.oms_order_item.table-strategy.inline.sharding-column=order_id

spring.shardingsphere.sharding.tables.oms_order_item.table-strategy.inline.algorithm-expression=oms_order_item_$->{((order_id+1) % 4).intdiv(2)}

# 使用SNOWFLAKE算法生成主键

spring.shardingsphere.sharding.tables.oms_order_item.key-generator.column=id

spring.shardingsphere.sharding.tables.oms_order_item.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.tables.oms_order_item.key-generator.props.worker.id=123

# 配置绑定表,防止笛卡尔乘积

spring.shardingsphere.sharding.binding-tables[0]=oms_order,oms_order_item

# 打印SQL语句

spring.shardingsphere.props.sql.show=true

注意:

1、我们配置的分库分表策略是将oms_order和oms_order_item两个表配置分库分表策略,其他的没有配置的表还是会走ds数据库。

2、注意理解下分库分表的策略。如何将记录平均分配到两个库的四个表中?如果分表策略只是oms_order_${order_id % 2},能平均分配吗?

3、为什么要配置绑定表?

 这些问题大家思考一下,如果对以上内容有疑惑的话,可以添加名片大家一起交流探讨,互相进步。

你可能感兴趣的:(java,面试,数据库,mysql,经验分享)