ShardingSphere解决不了的分库分表问题, 或许它能…

2024年 1月 18日 80.4k 0

写在前面

诚然 Sharding-shpere 是一款非常优秀的技术产品, 下面介绍的自研的技术产品,在生态和完善度上是无法与之相提并论的。
但是笔者自己开发的这个项目: sharding-mybatis,目前已用于生产环境,且承载TPS超过数万的这个项目, 在某些特殊场景或许更好用一些, 如果您感兴趣, 可以耐心读完以下的文档。
如果您赶时间, 可以看下介绍不必观看使用说明,日后用到再来看。

未标题-1.png

为啥要使用 sharding-mybatis

  • sharding-mybatis 与springboot/mybatis 生态无缝集成,无业务入侵,轻量,够用
  • 如果您的需求只是一些比较常见的分库分表需求,而苦于Sharding-sphere依赖体系比较复杂,或者依赖包比较大
  • sharding-sphere 存在一些不支持的SQL,您的业务必须要使用这种SQL;sharding-mybatis 支持任何对应数据库的SQL语法, 这个是基于AST语法树的ShardingSphere不具备的
  • 如果你有多数据源配置的烦恼,可以用它,配置多数据源,非常的简单。
  • 如果你有不同类型数据库数据源配置的,比如您要同时使用 MySQL、Postgres、Oracle 可以用它, 只要实现了标准的 jdbc 和datasource相关接口都可以使用
  • sharding-mybatis 效率非常高, 整个组件在性能损耗方面可以忽略不计,底层采用内存缓存,经万级别TPS生产环境验证,性能与Sharding-Sphere 无异
  • 附: sharding-sphere 不支持的一些SQL列表

    INSERT INTO tbl_name (col1, col2, …) VALUES(1+2, ?, …)	                VALUES语句不支持运算表达式
    INSERT INTO tbl_name (col1, col2, …) SELECT col1, col2, … FROM tbl_name WHERE col3 = ?	    -- INSERT .. SELECT
    SELECT COUNT(col1) as count_alias FROM tbl_name GROUP BY col1 HAVING count_alias > ?        -- HAVING
    SELECT * FROM tbl_name1 UNION SELECT * FROM tbl_name2	                                    -- UNION
    SELECT * FROM tbl_name1 UNION ALL SELECT * FROM tbl_name2	                                -- UNION ALL
    SELECT * FROM ds.tbl_name1	                                                                --  包含schema
    SELECT SUM(DISTINCT col1), SUM(col1) FROM tbl_name	                                        -- 详见DISTINCT支持情况详细说明
    SELECT * FROM tbl_name WHERE to_date(create_time, ‘yyyy-mm-dd’) = ?	                        -- 会导致全路由
    SELECT SUM(DISTINCT col1), SUM(col1) FROM tbl_name	                                        -- 同时使用普通聚合函数和DISTINCT聚合函数
    

    项目简介:

    项目地址:sharing-mybatis

    注: 本文不是写来收集star的, 当然你觉得项目帮助到了你, 你想给的话,我也不反对

    功能列表

    • 多数据源支持
    • 支持分库分表(仅支持整数类型的sharding Key)
    • 支持只分库、支持只分表、支持不分库分表
    • 支持使用事务 (见下面使用说明)
    • 支持分库分表规则自定义(aviator 表达式引擎)
    • 支持不同数据源混用

    使用说明

    1. 引入依赖, 最好禁用掉spring-boot 的自身datasource装配,因为没用

    
    <dependency>
        <groupId>com.winjeg.spring</groupId>
        <artifactId>sharding-mybatis</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
    

    2. 配置好数据源

    下面是 spring boot 的项目配置,一般可以配置再配置中心,或者直接配置在 application.yaml 中;

    对于非springboot项目,我奉劝一句,升级到Springboot 把

    datasource:
      list:
        - name: demo-1
          driver-class-name: com.mysql.cj.jdbc.Driver
          jdbc-url: jdbc:mysql://10.10.10.10:3306/demo_1?useSSL=false&useUnicode=true&characterEncoding=UTF-8
          username: demo_user
          password: 123456
        - name: demo-2
          driver-class-name: com.mysql.cj.jdbc.Driver
          jdbc-url: jdbc:mysql://10.10.10.10:3306/demo_2?useSSL=false&useUnicode=true&characterEncoding=UTF-8
          username: demo_user
          password: 123456
    
    

    3. 开启分库分表支持的配置

    
    @SpringBootApplication
    @EnableSharding(packages = {"com.winjeg.spring.test.mapper", "com.winjeg.spring.test.dao"})
    public class SpringApplicationDemo {
        public static void main(String[] args) {
            SpringApplication.run(SpringApplicationDemo.class, args);
        }
    }
    

    4. 在mapper上添加注解 & 标记出分表键, 如不需要分库分表, 仅配置datasource 和 mapperLocation

    
    @Sharding(datasource = {"demo-1", "demo-2"},
            mapperLocation = "classpath:mappers/demo/*.xml",
            dbRule = "'demo-' + (id % 16 / 8 + 1)",
            tableRule = "'user_' + (id % 16 % 4)",
            shardingKey = "id")
    public interface ShardingMapper {
    
        int updateUser(@ShardingKey @Param("id") final long id,
                       @Param("name") final String name);
    }
    
    

    样例Mapper

    
    <?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.winjeg.spring.sharding.test.mapper.ShardingMapper">
        <insert id="addUser">
            INSERT INTO ${tableName}
            (id, name) VALUES(#{id}, #{name})
        </insert>
    
        <update id="updateUser">
            UPDATE ${tableName}
            SET name=#{name}
            WHERE id = #{id}
        </update>
    </mapper>
    

    注: 在不分库分表的时候, datasource只能设置一个, 设置多个则无用
    仅分库的时候,只设置 dbRule, 仅分表的时候设置 tableRule

    5. 代码中使用

        @Autowired
    private NormalMapper testMapper;
    
    @Autowired
    private WonderMapper wonderMapper;
    
    @GetMapping("/normal")
    public List<String> noneSharding(@RequestParam(value = "uid", defaultValue = "1") final long userId){
            val tables=testMapper.getTables();
            tables.add(wonderMapper.getUser());
            return tables;
            }
    
    
    

    使用事务

        @GetMapping("/trans")
    public String Sharding(@RequestParam(value = "uid", defaultValue = "1") final long userId,
    @RequestParam(value = "name", defaultValue = "") final String name){
            val manager=transactionManager.getTransactionManager(ShardingMapper.class,userId);
            TransactionStatus status=manager.getTransaction(definition);
            try{
            if(shardingMapper.addUser(userId,name)< 1){
            manager.rollback(status);
            return"add_trans_fail";
            }
            if(shardingMapper.updateUser(userId,name+"updated")< 1){
            manager.rollback(status);
            return"update_trans_fail";
            }
            manager.commit(status);
            return"trans_success";
            }catch(Exception e){
            manager.rollback(status);
            }
            return"trans_fail";
            }
    

    写在最后

    如果有感兴趣而当同学, 可以在本文回复咨询, 或者在github仓库留言咨询,或者 email我

    相关文章

    Oracle如何使用授予和撤销权限的语法和示例
    Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
    下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
    社区版oceanbase安装
    Oracle 导出CSV工具-sqluldr2
    ETL数据集成丨快速将MySQL数据迁移至Doris数据库

    发布评论