• 多维度查询使用es

    问题

  1. join
  2. 事务
  3. 排序

根据UserID查订单

方法一:中间表

  • 中间表可以使用es,根据UserID查OrderID

方法二:id融合

将uid作为tid的一部分,且作为分库的主键
分库分表 - 图1
帖子中心,1亿数据,架构如何设计?

根据店铺ID查订单

一个店铺的订单都是在不同的库中,即使使用中间表,查询效率也低。(用es存订单全量数据不行吗?)

  • 数据冗余
  • 使用canel或双写

image.png

sharding jdbc

image.png

配置数据源

  1. # 打印执行的数据库以及语句
  2. spring.shardingsphere.props.sql.show=true
  3. # 数据源 db0
  4. spring.shardingsphere.datasource.names=ds0,ds1
  5. # 第一个数据库
  6. spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
  7. spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
  8. spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://120.25.217.15:3306/xdclass_shop_order_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
  9. spring.shardingsphere.datasource.ds0.username=root
  10. spring.shardingsphere.datasource.ds0.password=xdclass.net168
  11. # 第二个数据库
  12. spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
  13. spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
  14. spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://120.25.217.15:3306/xdclass_shop_order_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
  15. spring.shardingsphere.datasource.ds1.username=root
  16. spring.shardingsphere.datasource.ds1.password=xdclass.net168

分库分表

  • 虚拟表productorder,分到ds$->{0..1}.product_order$->{0..1},
  • 这个0,1怎么根据什么算出来呢?下面配置 分片键 & 分片算法 ```properties

    配置分库规则

    spring.shardingsphere.sharding.tables.product_order.database-strategy.inline.sharding-column=user_id

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

精准分片-水平分表

指定product_order表的数据分布情况,配置数据节点,在 Spring 环境中建议使用 $->{…}

TableRuleConfiguration

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

spring.shardingsphere.sharding.tables.productorder.actual-data-nodes=ds0.product_order$->{0..1}

指定精准分片算法(水平分库) 根据user_id分库

spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.sharding-column=user_id

spring.shardingsphere.sharding.tables.product_order.database-strategy.standard.precise-algorithm-class-name=net.xdclass.strategy.CustomDBPreciseShardingAlgorithm

指定精准分片算法(水平分表) 根据订单id分表

spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.sharding-column=id

spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.precise-algorithm-class-name=net.xdclass.strategy.CustomTablePreciseShardingAlgorithm

范围分片(水平分表)

spring.shardingsphere.sharding.tables.product_order.table-strategy.standard.range-algorithm-class-name=net.xdclass.strategy.CustomRangeShardingAlgorithm

复合分片算法,order_id,user_id 同时作为分片健

spring.shardingsphere.sharding.tables.product_order.table-strategy.complex.sharding-columns=user_id,id

spring.shardingsphere.sharding.tables.product_order.table-strategy.complex.algorithm-class-name=net.xdclass.strategy.CustomComplexKeysShardingAlgorithm

hit分片

spring.shardingsphere.sharding.tables.product_order.database-strategy.hint.algorithm-class-name=net.xdclass.strategy.CustomDBHintShardingAlgorithm spring.shardingsphere.sharding.tables.product_order.table-strategy.hint.algorithm-class-name=net.xdclass.strategy.CustomTableHintShardingAlgorithm

  1. <a name="zXxMm"></a>
  2. ### 配置默认分库策略
  3. ```properties
  4. #配置【默认分库策略】
  5. #spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
  6. #spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{user_id % 2 }

ShardingAlgorithm

image.png

ShardingAlgorithm和ShardingStrategy关系

image.png

PreciseShardingAlgorithm

  • 包括RangeShardingAlgorithm,都是单分片键

    1. public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    2. /**
    3. *
    4. * @param dataSourceNames 数据源集合
    5. * 在分库时值为所有分片库的集合 databaseNames
    6. * 分表时为对应分片库中所有分片表的集合 tablesNames
    7. *
    8. * @param shardingValue 分片属性,包括
    9. * logicTableName 为逻辑表,
    10. * columnName 分片健(字段),
    11. * value 为从 SQL 中解析出的分片健的值
    12. * @return
    13. */
    14. @Override
    15. public String doSharding(Collection<String> dataSourceNames, PreciseShardingValue<Long> preciseShardingValue) {
    16. for(String datasourceName : dataSourceNames){
    17. String value = preciseShardingValue.getValue() % dataSourceNames.size() + "";
    18. //product_order_0
    19. if(datasourceName.endsWith(value)){
    20. return datasourceName;
    21. }
    22. }
    23. return null;
    24. }
    25. }

    ComplexKeysShardingAlgorithm 支持多分片键

    订单id=xx and userid = yy
    product_order_0_0、product_order_0_1、product_order_1_0、product_order_1_1
    用的少 ```java public class CustomComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm { /*

    • @param dataSourceNames 数据源集合
    • 在分库时值为所有分片库的集合 databaseNames
    • 分表时为对应分片库中所有分片表的集合 tablesNames *
    • @param shardingValue 分片属性,包括
    • logicTableName 为逻辑表,
    • columnName 分片健(字段),
    • value 为从 SQL 中解析出的分片健的值
    • @return */ @Override public Collection doSharding(Collection dataSourceNames, ComplexKeysShardingValue complexKeysShardingValue) {

      // 得到每个分片健对应的值 Collection orderIdValues = this.getShardingValue(complexKeysShardingValue, “id”); Collection userIdValues = this.getShardingValue(complexKeysShardingValue, “user_id”);

      List shardingSuffix = new ArrayList<>(); // 对两个分片健取模的方式 product_order_0_0、product_order_0_1、product_order_1_0、product_order_1_1 for (Long userId : userIdValues) {

      1. for (Long orderId : orderIdValues) {
      2. String suffix = userId % 2 + "_" + orderId % 2;
      3. for (String databaseName : dataSourceNames) {
      4. if (databaseName.endsWith(suffix)) {
      5. shardingSuffix.add(databaseName);
      6. }
      7. }
      8. }

      } return shardingSuffix; }

      /**

    • shardingValue 分片属性,包括
    • logicTableName 为逻辑表,
    • columnNameAndShardingValuesMap 存储多个分片健 包括key-value
    • key:分片key,id和user_id
    • value:分片value,66和99 *
    • @return shardingValues 集合 */ private Collection getShardingValue(ComplexKeysShardingValue shardingValues, final String key) { Collection valueSet = new ArrayList<>(); Map> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();

      if (columnNameAndShardingValuesMap.containsKey(key)) {

      1. valueSet.addAll(columnNameAndShardingValuesMap.get(key));

      } return valueSet; }

}

  1. <a name="lidG7"></a>
  2. #### HintShardingAlgorithm
  3. - 外部指定分片键值->从 **hintManager.addTableShardingValue**("product_order", 1)参数进行指定
  4. ```java
  5. public void testHit(){
  6. //清除历史规则
  7. HintManager.clear();
  8. //获取对应的实例
  9. HintManager hintManager = HintManager.getInstance();
  10. //设置库的分片键值,value是用于库分片取模
  11. hintManager.addDatabaseShardingValue("product_order",3L);
  12. //设置表的分片键值,value是用于表分片取模
  13. hintManager.addTableShardingValue("product_order",8L);
  14. //如果在读写分离数据库中,Hint 可以强制读主库(主从复制存在一定延时,但在业务场景中,可能更需要保证数据的实时性)
  15. //hintManager.setMasterRouteOnly();
  16. //对应的value,只做查询,不做sql解析
  17. productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().eq("id",66L));
  18. }

广播表

每个库都有的表

  1. #配置广播表
  2. spring.shardingsphere.sharding.broadcast-tables=ad_config
  3. spring.shardingsphere.sharding.tables.ad_config.key-generator.column=id
  4. spring.shardingsphere.sharding.tables.ad_config.key-generator.type=SNOWFLAKE

雪花算法id

  • 注意workerId不同(确保机器间id不同)
  • 注意时钟回拨(确保单个机器id不同)

设置workerId

  1. #配置workId
  2. spring.shardingsphere.sharding.tables.product_order.key-generator.props.worker.id=1
  1. #id生成策略
  2. spring.shardingsphere.sharding.tables.product_order.key-generator.column=id
  3. spring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE

配置绑定表(join)

避免笛卡尔积

  1. #配置绑定表
  2. #spring.shardingsphere.sharding.binding‐tables[0] = product_order,product_order_item

image.png

sharding-jdbc 主从读写分离

image.png
默认增删改走主库,查询走从库。

注解强制走主库

image.png

注解走从库

image.png

新老库切换

image.png

  1. 新数据双写
  2. 老数据同步
  3. 全量数据比对