当前位置 博文首页 > RemainderTime:框架整合(二)- 使用Apache ShardingSphere实现

    RemainderTime:框架整合(二)- 使用Apache ShardingSphere实现

    作者:[db:作者] 时间:2021-07-12 21:43

    最近公司项目中使用到了订单表,后续如果项目上线了可能订单数据较大,那么就需要对订单表进行分片或者分库操作,正好最近私下学习到了这里,就加以记录,方便以后项目使用。

    解决方案
    • 实现分库分表的的解决方案
    1. Apache ShardingShpere(本博文选择的方案)
    2. Mycat
    具体实现(分表)
    • 创建数据库(ds0)和表t_order_0t_order_1
    CREATE TABLE `t_order_0` (
      `order_id` bigint(20) unsigned NOT NULL,
      `user_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`order_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    CREATE TABLE `t_order_1` (
      `order_id` bigint(20) unsigned NOT NULL,
      `user_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`order_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

    在这里插入图片描述

    注: 分表时注意表的订单表的命名规则(分库同理),具有相同的名称后面的编号不同等

    • 创建springboot项目并结合mybatis-plus

    注:使用mybatis-plus是因为公司项目中使用的这个,方便以后的使用(当然也可使用其他orm框架,实现方法同理)

    • 引入项目依赖 shardingsphere(其他基础依赖略)
    		<dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
                <version>5.0.0-alpha</version>
            </dependency>
    
    • application.properties文件中加入shardingsphere配置

    :可参考官方文档,但官方文档更新可能之后,目前文档是之前版本的,最新5.0版本似乎未及时更新(目前项目配置是本人亲测成功的)

    1. 配置中注释掉的配置是分库的相关配置
    2. 着重注意分片相关配置后面的值设置规则
    3. 当前分表策略(表字段order_id),分表算法配置为取模
    # 配置真实数据源
    spring.shardingsphere.datasource.names=ds0
    
    spring.shardingsphere.datasource.common.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.common.driver-class-name=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.common.username=root
    spring.shardingsphere.datasource.common.password= root
    
    spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ds0?serverTimezone=UTC&useSSL=false
    #spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/ds1?serverTimezone=UTC&useSSL=false
    
    # 配置 t_order 表规则
    spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds0.t_order_$->{0..1}
    
    # 配置分库策略
    #spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
    #spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=database-inline
    
    # 配置分表策略
    spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
    spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=table-inline
    
    # 配置 分片算法
    #spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
    #spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds$->{user_id % 2}
    spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=INLINE
    spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithm-expression=t_order_$->{order_id % 2}
    
    # 分布式序列策略配置
    spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
    spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake
    
    # 分布式序列算法配置
    spring.shardingsphere.rules.sharding.key-generators.snowflake.type =SNOWFLAKE
    spring.shardingsphere.rules.sharding.key-generators.snowflake.props.worker-id =123
    spring.shardingsphere.props.sql-show=true
    
    • 创建order实体类

    :着重实体类表名配置 @TableName(“t_order”) 和数据库没有相同的名称,但名称前缀都一样,只要前面配置和依赖都没有出问题,那么运行时就不会报表不存在的错误(后续xml文件中实现的sql语句也用相同的表名)

    @TableName("t_order")
    @Data
    public class Order {
    
        @TableId(value = "order_id", type = IdType.ID_WORKER)
        private Long orderId;
    
        private Integer userId;
    
    }
    
    1. 使用sql操作分表有许多禁用条件,可查看官方文档进行排查
      点击跳转使用规范页
    测试
    1. 批量插入20条数据
       @Autowired
        private OrderService orderService;
    
        @Test
        public void insert() {
            List<Order> orderList =new ArrayList<Order>();
            for (int i = 0; i < 20; i++) {
                Order orderEntity = new Order();
    //            orderEntity.setOrderId(System.currentTimeMillis());
                orderEntity.setUserId(new Random().nextInt(999));
              orderList.add(orderEntity);
            }
            orderService.saveBatch(orderList);
        }
    
    • 查看数据库,2个表(通过分片配置算法取模)分别插入了数据
      在这里插入图片描述
    1. 查询一条order数据()
        @Autowired
        private OrderMapper orderMapper;
        
        @Test
        public void getOrder(){
            Order orderId = orderMapper.getOrderId(1401545531558088708L);
            System.out.println(orderId);
        }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.xf.mapper.OrderMapper">
    
    
        <select id="getOrderId" resultType="com.xf.entity.Order" parameterType="long">
            select * from t_order where order_id = #{id}
        </select>
    
    </mapper>
    
    
    1. 查看控制台打印的查询sql
      在这里插入图片描述
    2. 查询结果
      在这里插入图片描述

    完成

    cs