ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Sharding-JDBC 水平分库

2020-06-21 14:53:37  阅读:242  来源: 互联网

标签:分库 spring shardingsphere id JDBC user 分片 Sharding order


前面已经介绍过,水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。接下来看一下如何使用Sharding-JDBC实现水平分库,咱们继续对快速入门中的例子进行完善。

(1)将原有order_db库拆分为order_db_1、order_db_2 

 

(2)分片规则修改

由于数据库拆分了两个,这里需要配置两个数据源。

分库需要配置分库的策略,和分表策略的意义类似,通过分库策略实现数据操作针对分库的数据库进行操作。 

spring.main.allow-bean-definition-overriding=true
mybatis.configuration.map-underscore-to-camel-case=true

#sharding-jdbc分片规则配置
#数据源
spring.shardingsphere.datasource.names=m1,m2

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/order_db_1?useUnicode=true
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456

spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456

# 分库策略,以user_id为分片键,分片策略为user_id % 2 + 1,user_id为偶数操作m1数据源,否则操作m2。
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

# 指定t_order表的数据分布情况,配置数据节点 m1.t_order_1,m1.t_order_2
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=m1.t_order_$->{1..2}

# 指定t_order表的主键生成策略为SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

# 指定t_order表的分片策略,分片策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2 + 1}

# 打开sql输出日志
spring.shardingsphere.props.sql.show=true

分库策略定义方式如下:

#分库策略,如何将一个逻辑表映射到多个数据源
spring.shardingsphere.sharding.tables.<逻辑表名称>.database‐strategy.<分片策略>.<分片策略属性名>= #分片策略属性值
#分表策略,如何将一个逻辑表映射为多个实际表
spring.shardingsphere.sharding.tables.<逻辑表名称>.table‐strategy.<分片策略>.<分片策略属性名>= #分片策略属性值

Sharding-JDBC支持以下几种分片策略:

不管理分库还是分表,策略基本一样。

  • standard:标准分片策略,对应StandardShardingStrategy。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理。
  • complex:符合分片策略,对应ComplexShardingStrategy。复合分片策略。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。
  • inline:行表达式分片策略,对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: t_user_$->{u_id % 8} 表示t_user表根据u_id模8,而分成8张表,表名称为 t_user_0 到t_user_7 。
  • hint:Hint分片策略,对应HintShardingStrategy。通过Hint而非SQL解析的方式分片的策略。对于分片字段非SQL决定,而由其他外置条件决定的场景,可使用SQL Hint灵活的注入分片字段。例:内部系统,按照员工登录主键分库,而数据库中并无此字段。SQL Hint支持通过Java API和SQL注释(待实现)两种方式使用。
  • none:不分片策略,对应NoneShardingStrategy。不分片的策略。 

目前例子中都使用inline分片策略,若对其他分片策略细节若感兴趣,请查阅官方文档:https://shardingsphere.apache.org 

(3)插入测试

修改testInsertOrder方法,插入数据中包含不同的user_id

@Test
public void testInsertOrder(){
    for (int i = 0 ; i<10; i++){
        orderDao.insertOrder(new BigDecimal((i+1)*5),1L,"WAIT_PAY");
    }
    for (int i = 0 ; i<10; i++){
        orderDao.insertOrder(new BigDecimal((i+1)*10),2L,"WAIT_PAY");
    }
}

执行testInsertOrder:

通过日志可以看出,根据user_id的奇偶不同,数据分别落在了不同数据源,达到目标。 

(4)查询测试

调用快速入门的查询接口进行测试:

List<Map> selectOrderbyIds(@Param("orderIds")List<Long> orderIds);

通过日志发现,sharding-jdbc将sql路由到m1和m2:

问题分析:

由于查询语句中并没有使用分片键user_id,所以sharding-jdbc将广播路由到每个数据结点。

下边我们在sql中添加分片键进行查询。

在OrderDao中定义接口:

@Select({"<script>",
  " select",
  " * ",
  " from t_order t ",
  "where t.order_id in",
  "<foreach collection='orderIds' item='id' open='(' separator=',' close=')'>",
  "#{id}",
  "</foreach>",
  " and t.user_id = #{userId} ",
  "</script>"
})
List<Map> selectOrderbyUserAndIds(@Param("userId") Integer userId, @Param("orderIds")List<Long> orderIds);

编写测试方法

@Test
public void testSelectOrderbyUserAndIds(){
  List<Long> orderIds = new ArrayList<>();
  orderIds.add(373422416644276224L);
  orderIds.add(373422415830581248L);
  //查询条件中包括分库的键user_id
  int user_id = 1;
  List<Map> orders = orderDao.selectOrderbyUserAndIds(user_id,orderIds);
  JSONArray jsonOrders = new JSONArray(orders);
  System.out.println(jsonOrders);
}

执行testSelectOrderbyUserAndIds:

查询条件user_id为1,根据分片策略m$->{user_id % 2 + 1}计算得出m2,此sharding-jdbc将sql路由到m2,见上图日志。 

 

标签:分库,spring,shardingsphere,id,JDBC,user,分片,Sharding,order
来源: https://www.cnblogs.com/jwen1994/p/13172091.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有