当前位置:Gxlcms > 数据库问题 > Sharding-JDBC 快速入门(水平分表)

Sharding-JDBC 快速入门(水平分表)

时间:2021-07-01 10:21:17 帮助过:5人阅读

DATABASE `order_db` CHARACTER SET utf8mb4;
USE order_db;

DROP TABLE IF EXISTS `t_order_1` ;

CREATE TABLE `t_order_1` (
  `order_id` BIGINT (20) NOT NULL COMMENT 订单id,
  `price` DECIMAL (10, 2) NOT NULL COMMENT 订单价格,
  `user_id` BIGINT (20) NOT NULL COMMENT 下单用户id,
  `status` VARCHAR (50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 订单状态,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC ;

DROP TABLE IF EXISTS `t_order_2` ;

CREATE TABLE `t_order_2` (
  `order_id` BIGINT (20) NOT NULL COMMENT 订单id,
  `price` DECIMAL (10, 2) NOT NULL COMMENT 订单价格,
  `user_id` BIGINT (20) NOT NULL COMMENT 下单用户id,
  `status` VARCHAR (50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 订单状态,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC ;

  3.创建springboot工程,引入maven依赖

<!-- sharding-jdbc和SpringBoot整合的Jar包 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC1</version>
</dependency>

    具体spring boot相关依赖及配置省略.......

  4.分片规则配置

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

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?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root

# 指定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表的分片策略,分片策略包括分片键和分片算法  {order_id % 2 + 1}:计算出的值要么为1,要么为2,根据结果选择使用哪张表
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

    1. 首先定义数据源m1,并对m1进行实际的参数配置。
    2.指定t_order表的数据分布情况,他分布在 m1.t_order_1,m1.t_order_2
    3.指定t_order表的主键生成策略为SNOWFLAKE,SNOWFLAKE是一种分布式自增算法,保证id全局唯一
    4.定义t_order分片策略,order_id为偶数的数据落在t_order_1,为奇数的落在t_order_2,分表策略的表达式为 t_order_$->{order_id % 2 + 1}

  5.持久层

@Mapper
public interface OrderDao {

    /**
     * 插入订单
     * @param price
     * @param userId
     * @param status
     * @return
     */
    @Insert("insert into t_order(price, user_id, status) values(#{price}, #{userId}, #{status})")
    int insertOrder(BigDecimal price, Long userId, String status);

    /**
     * 根据id列表查询订单
     * @param orderIds
     * @return
     */
    @Select("<script>" +
            "select" +
            " * " +
            " from t_order o " +
            " where o.order_id in " +
            " <foreach collection=‘orderIds‘ open=‘(‘ separator=‘,‘ close=‘)‘ item=‘id‘>" +
            " #{id} " +
            " </foreach>" +
            "</script>")
    List<Map> selectOrderbyIds(@Param("orderIds") List<Long> orderIds);
}

  6.测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleBootstrap.class})
public class OrderDaoTest {

    @Autowired
    OrderDao orderDao;

    @Test
    public void testInsertOrder() {
        // for (int i = 1; i <= 20; i++) {
            orderDao.insertOrder(new BigDecimal(21), 1L, "SUCCESS");
        // }
    }

    @Test
    public void testSelectOrderbyIds() {
        List<Long> ids = new ArrayList<>();
        ids.add(463369285373263872L);
        ids.add(463369285301960704L);

        List<Map> maps = orderDao.selectOrderbyIds(ids);
        System.out.println(maps);
    }
}

执行流程:

  查看日志,Sharding-JDBC在拿到用户要执行的sql之后干了哪些事儿:
    (1)解析sql,获取片键值,在本例中是order_id
    (2)Sharding-JDBC通过规则配置 t_order_$->{order_id % 2 + 1},知道了当order_id为偶数时,应该往t_order_1表插数据,为奇数时,往t_order_2插数据。
    (3)于是Sharding-JDBC根据order_id的值改写sql语句,改写后的SQL语句是真实所要执行的SQL语句。
    (4)执行改写后的真实sql语句
    (5)将所有真正执行sql的结果进行汇总合并,返回。

Java配置类的方式配置分片规则:

@Configuration
public class ShardingJdbcConfig {

    // 配置分片规则
    // 定义数据源
    Map<String, DataSource> createDataSourceMap() {
        DruidDataSource dataSource1 = new DruidDataSource();
        dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource1.setUrl("jdbc:mysql://localhost:3306/order_db?useUnicode=true");
        dataSource1.setUsername("root");
        dataSource1.setPassword("root");
        Map<String, DataSource> result = new HashMap<>();
        result.put("m1", dataSource1);
        return result;
    }

    // 定义主键生成策略
    private static KeyGeneratorConfiguration getKeyGeneratorConfiguration() {
        KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE", "order_id");
        return result;
    }

    // 定义t_order表的分片策略
    TableRuleConfiguration getOrderTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration("t_order", "m1.t_order_$->{1..2}");
        result.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_$->{order_id % 2 + 1}"));
        result.setKeyGeneratorConfig(getKeyGeneratorConfiguration());

        return result;
    }

    // 定义sharding-Jdbc数据源
    @Bean
    DataSource getShardingDataSource() throws SQLException {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
        //spring.shardingsphere.props.sql.show = true
        Properties properties = new Properties();
        properties.put("sql.show", "true");
        return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, properties);
    }
}

  由于采用了配置类所以需要屏蔽原来 application.properties 文件中spring.shardingsphere开头的配置信息。
  需要在SpringBoot启动类中屏蔽使用spring.shardingsphere配置项的类:@SpringBootApplication(exclude = SpringBootConfiguration.class)

 

Sharding-JDBC 快速入门(水平分表)

标签:postgresq   shm   utf8mb4   如何   template   表达式   otc   tables   code   

人气教程排行