Springboot + Mybatis-Plus + Sharding-JDBC


Springboot + Mybatis-Plus + Sharding-JDBC

現在開源的分庫分表方案中, 常用的就是MyCat和Sharding-JDBC, MyCat需要有專門的服務器, 通常要的配置也比較高, 公司之前就是專門部署了兩台64G的MyCat服務器, 后面為了節省資源, 逐步切換成Sharding-JDBC

這里主要介紹Springboot, Mybatis-Plus, Sharding-JDBC的整合, 基於Springboot的yml配置文件配置分庫分表策略, 使用snowflake雪花算法生成分布式主鍵, 分片策略是哈希取模

  1. pom文件

    <dependencies>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    
        <dependency>
            <groupId>com.eric</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    
        <dependency>
            <groupId>com.eric</groupId>
            <artifactId>cache</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    
        <!--dozer依賴開始-->
        <dependency>
            <groupId>net.sf.dozer</groupId>
            <artifactId>dozer</artifactId>
            <version>5.5.1</version>
            <exclusions>
                <!--目前項目中使用的是apache自帶的log4j-->
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <!--<exclusion>
                   <groupId>log4j</groupId>
                   <artifactId>log4j</artifactId>
                </exclusion>-->
            </exclusions>
        </dependency>
        <dependency>
            <groupId>net.sf.dozer</groupId>
            <artifactId>dozer-spring</artifactId>
            <version>5.5.1</version>
        </dependency>
        <!--dozer依賴結束-->
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>
    
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.6</version>
        </dependency>
    
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.32</version>
        </dependency>
    
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    
        <!-- mybatis的分頁插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.7</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
            <version>1.18.2</version>
        </dependency>
    
        <!--sharding-jdbc依賴開始-->
        <!-- for spring boot -->
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>${sharding-sphere.version}</version>
        </dependency>
    
        <!-- for spring namespace -->
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>${sharding-sphere.version}</version>
        </dependency>
        <!--sharding-jdbc依賴結束-->
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- 資源文件拷貝插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
  2. yml配置文件 需要創建兩個數據庫實例ds0和ds1, 每個數據實例要創建ordermaster0和ordermaster1兩個表

    server:
      port: 12890
      undertow:
        io-threads: 16
        worker-threads: 256
        buffer-size: 1024
        buffers-per-region: 1024
        direct-buffers: true
        accesslog:
          dir: my-undertow
          enabled: true
          pattern: '%t %a "%r" %s (%D ms)'
    
    # sharding-jdbc分庫分表的配置
    sharding:
      jdbc:
        datasource:
          ds0:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://localhost:3306/ds0
            username: root
            password: 123456
          ds1:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://localhost:3306/ds1
            username: root
            password: 123456
          names: ds0,ds1
        config:
          sharding:
            tables: # 分表策略
              order_master:
                table-strategy:
                  inline:
                    sharding-column: order_id
                    algorithm-expression: order_master$->{order_id % 2}
                key-generator-column-name: order_id
                actual-data-nodes: ds$->{0..1}.order_master$->{0..1}
            default-database-strategy: # 分庫策略
              inline:
                sharding-column: user_id
                algorithm-expression: ds$->{user_id % 2}
    
    mybatis-plus:
      datasource: dataSource
      mapper-locations: classpath:/mapper/*.xml
      #實體掃描,多個package用逗號或者分號分隔
      typeAliasesPackage: com.eric.shardingjdbc.bean
      global-config:
        #主鍵類型  0:"數據庫ID自增", 1:"用戶輸入ID",2:"全局唯一ID (數字類型唯一ID)", 3:"全局唯一ID UUID";
        id-type: 1
        #字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷"
        field-strategy: 2
        #駝峰下划線轉換
        db-column-underline: true
        #刷新mapper 調試神器
        refresh-mapper: true
        #數據庫大寫下划線轉換
        #capital-mode: true
        #序列接口實現類配置
        #key-generator: com.baomidou.springboot.xxx
        #邏輯刪除配置
        logic-delete-value: 0
        logic-not-delete-value: 1
        #自定義填充策略接口實現
        #meta-object-handler: com.baomidou.springboot.xxx
        #自定義SQL注入器
        #sql-injector: com.baomidou.springboot.xxx
      configuration:
        map-underscore-to-camel-case: true
        cache-enabled: false
    
    snowflake:
      datacenter: 1 # 數據中心的id
      bizType: sharding_order_id_ # 業務類型
    
  3. bean對象

    @Data
    @Accessors(chain = true)
    public class OrderMaster implements Serializable {
        /**
         * 訂單ID
         */
        @TableId
        private Long orderId;
    
        /**
         * 訂單編號
         */
        private String orderSn;
    
        /**
         * 下單人ID
         */
        private Long userId;
    
        private static final long serialVersionUID = 1L;
    
    }
    
  4. mapper(mapper.xml可以生成空的xml)

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.eric.shardingjdbc.bean.OrderMaster;
    
    /**
     * @author wang.js on 2019/1/24.
     * @version 1.0
     */
    public interface OrderMasterMapper extends BaseMapper<OrderMaster> {
    
    }
    
  5. service層

    /**
     * 主訂單
     *
     * @author wang.js on 2019/3/12.
     * @version 1.0
     */
    public interface OrderMasterService {
    
        /**
         * 保存訂單
         *
         * @param t 訂單
         * @return boolean
         */
        boolean insert(OrderMaster t);
    
        /**
         * 查詢訂單
         * @param i
         * @return
         */
        OrderMaster findById(int i);
    }
    
    
    /**
     * @author wang.js on 2019/3/12.
     * @version 1.0
     */
    @Service
    public class OrderMasterServiceImpl extends ServiceImpl<OrderMasterMapper, OrderMaster> implements OrderMasterService {
    
        @Override
        public boolean insert(OrderMaster t) {
            return this.baseMapper.insert(t) > 0;
        }
    
        @Override
        public OrderMaster findById(int i) {
            return this.baseMapper.selectById(i);
        }
    
    }
    
  6. sql腳本(在ds0和ds1中分別執行)

    DROP TABLE IF EXISTS `order_master0`;
    CREATE TABLE `order_master0` (
      `order_id` varchar(40) DEFAULT NULL COMMENT '訂單ID',
      `order_sn` varchar(40) DEFAULT NULL COMMENT '訂單編號',
      `user_id` varchar(40) DEFAULT NULL COMMENT '下單人ID',
      `shipping_user` varchar(40) DEFAULT NULL COMMENT '收貨人姓名',
      `payment_method` varchar(1) DEFAULT NULL COMMENT '支付方式',
      `order_money` int(11) DEFAULT NULL COMMENT '訂單金額',
      `district_money` int(11) DEFAULT NULL COMMENT '優惠金額(不包含優惠券)',
      `shipping_money` int(11) DEFAULT NULL COMMENT '運費金額',
      `payment_money` int(11) DEFAULT NULL COMMENT '支付金額',
      `shipping_sn` varchar(40) DEFAULT NULL COMMENT '快遞單號',
      `create_time` datetime DEFAULT NULL COMMENT '下單時間',
      `shipping_time` datetime DEFAULT NULL COMMENT '發貨時間',
      `pay_time` datetime DEFAULT NULL COMMENT '支付時間',
      `receive_time` datetime DEFAULT NULL COMMENT '收貨時間',
      `order_status` varchar(1) DEFAULT NULL COMMENT '訂單狀態',
      `order_point` int(11) DEFAULT NULL COMMENT '訂單積分',
      `update_time` datetime DEFAULT NULL COMMENT '更新時間',
      `coupon_discount` int(11) DEFAULT NULL COMMENT '優惠券金額'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Table structure for order_master1
    -- ----------------------------
    DROP TABLE IF EXISTS `order_master1`;
    CREATE TABLE `order_master1` (
      `order_id` varchar(40) DEFAULT NULL COMMENT '訂單ID',
      `order_sn` varchar(40) DEFAULT NULL COMMENT '訂單編號',
      `user_id` varchar(40) DEFAULT NULL COMMENT '下單人ID',
      `shipping_user` varchar(40) DEFAULT NULL COMMENT '收貨人姓名',
      `payment_method` varchar(1) DEFAULT NULL COMMENT '支付方式',
      `order_money` int(11) DEFAULT NULL COMMENT '訂單金額',
      `district_money` int(11) DEFAULT NULL COMMENT '優惠金額(不包含優惠券)',
      `shipping_money` int(11) DEFAULT NULL COMMENT '運費金額',
      `payment_money` int(11) DEFAULT NULL COMMENT '支付金額',
      `shipping_sn` varchar(40) DEFAULT NULL COMMENT '快遞單號',
      `create_time` datetime DEFAULT NULL COMMENT '下單時間',
      `shipping_time` datetime DEFAULT NULL COMMENT '發貨時間',
      `pay_time` datetime DEFAULT NULL COMMENT '支付時間',
      `receive_time` datetime DEFAULT NULL COMMENT '收貨時間',
      `order_status` varchar(1) DEFAULT NULL COMMENT '訂單狀態',
      `order_point` int(11) DEFAULT NULL COMMENT '訂單積分',
      `update_time` datetime DEFAULT NULL COMMENT '更新時間',
      `coupon_discount` int(11) DEFAULT NULL COMMENT '優惠券金額'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  7. 測試類

    @Test
    public void t2() {
        Random random = new Random();
        for (long i = 1; i < 100L; i++) {
            OrderMaster t = new OrderMaster().setOrderId(defaultKeyGenerator.generateKey().longValue()).setUserId((long) (random.nextInt(100) + 1));
            orderMasterService.insert(t);
        }
    }
    

ps: 如果並發度不高的情況下, defaultKeyGenerator.generateKey()生成的id很大幾率會是偶數

 

 項目已經上傳到gitee和github

gitee: https://gitee.com/ericwo/second-kill

github: https://github.com/wangjisong1993/second-kill


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM