zoukankan      html  css  js  c++  java
  • Sharding-JDBC 水平分库

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

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

    问题分析:

    由于查询语句中并没有使用分片键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_id1,根据分片策略m$->{user_id % 2 + 1}计算得出m2,此sharding-jdbcsql路由到m2,见上图日志。 

  • 相关阅读:
    字符串替换
    字符串查找
    字符串比较
    字节与字符串相互转换
    1365. How Many Numbers Are Smaller Than the Current Number
    1486. XOR Operation in an Array
    1431. Kids With the Greatest Number of Candies
    1470. Shuffle the Array
    1480. Running Sum of 1d Array
    【STM32H7教程】第56章 STM32H7的DMA2D应用之刷色块,位图和Alpha混合
  • 原文地址:https://www.cnblogs.com/jwen1994/p/13172091.html
Copyright © 2011-2022 走看看