spring-boot集成Apache ShardingSphere 5.0.0 初识


文章目录

  • spring-boot集成Apache ShardingSphere 5.0.0 初识
  • 一、前言
  • 二、与spring-boot集成实现(分库、分表)
  • 1.建表语句
  • 2.pom.xml
  • 3.application.yml
  • 4.CURD


一、前言

官方文档

Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。


Apache ShardingSphere 旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。 关系型数据库当今依然占有巨大市场份额,是企业核心系统的基石,未来也难于撼动,我们更加注重在原有基础上提供增量,而非颠覆。


Apache ShardingSphere 5.x 版本开始致力于可插拔架构,项目的功能组件能够灵活的以可插拔的方式进行扩展。 目前,数据分片、读写分离、数据加密、影子库压测等功能,以及 MySQL、PostgreSQL、SQLServer、Oracle 等 SQL 与协议的支持,均通过插件的方式织入项目。 开发者能够像使用积木一样定制属于自己的独特系统。Apache ShardingSphere 目前已提供数十个 SPI 作为系统的扩展点,仍在不断增加中。


ShardingSphere 已于2020年4月16日成为 Apache 软件基金会的顶级项目。

二、与spring-boot集成实现(分库、分表)

1.建表语句

CREATE TABLE `t_order0` (
                            `order_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `user_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `order_name` varchar(100) COLLATE utf8_bin NOT NULL,
                            PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `t_order1` (
                            `order_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `user_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `order_name` varchar(100) COLLATE utf8_bin NOT NULL,
                            PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `t_order2` (
                            `order_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `user_id` varchar(36) COLLATE utf8_bin NOT NULL,
                            `order_name` varchar(100) COLLATE utf8_bin NOT NULL,
                            PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

2.pom.xml

<properties>
        <java.version>1.8</java.version>
        <mybatis-plus.version>3.4.1</mybatis-plus.version>
        <shardingsphere.version>5.0.0</shardingsphere.version>
    </properties>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
  • 避坑指南

不建议直接引入druid-spring-boot-starter,避免由于数据源加载顺序导致的项目无法正常启动。
org.apache.shardingsphere.spring.boot.ShardingSphereAutoConfigurationcom.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

3.application.yml

spring:
  shardingsphere:
    props:
      sql-show: true
    datasource:
      ds0:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      ds1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      names: ds0,ds1
    rules:
      sharding:
        sharding-algorithms:
          custom-db-inline:
            props:
              algorithm-expression: ds$->{Math.abs(user_id.hashCode()%2)}
            type: INLINE
          custom-table-inline:
            props:
              algorithm-expression: t_order$->{Math.abs(order_id.hashCode()%3)}
            type: INLINE
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order$->{0..2}
            database-strategy:
              standard:
                sharding-algorithm-name: custom-db-inline
                sharding-column: user_id
            table-strategy:
              standard:
                sharding-algorithm-name: custom-table-inline
                sharding-column: order_id
mybatis-plus:
  global-config:
    db-config:
      id-type: assign_id
  • 避坑指南

sharding-algorithm-name禁止使用下划线_推荐使用短横线-),原因org.springframework.boot.context.properties.source.ConfigurationPropertyName#elementsOf(java.lang.CharSequence, boolean, int),你也别管什么 松散绑定 了,全用短横线-得了。


java.lang.Math.abs(int)当传参为Integer#MIN_VALUE,返回Integer#MIN_VALUE即负值。因此将t_order$->{Math.abs(order_id.hashCode())%3}改为t_order$->{Math.abs(order_id.hashCode()%3)}

4.CURD

  • OrderController.java
package com.example.demo.controller;

import com.example.demo.entity.Order;
import com.example.demo.service.OrderService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author ouruyi
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private OrderService orderService;

    @GetMapping("/{id}")
    public Order getById(@PathVariable String id) {
        return this.orderService.getById(id);
    }

    @GetMapping("")
    public List<Order> list() {
        return this.orderService.list();
    }

    @GetMapping("/count")
    public Integer count() {
        return this.orderService.count();
    }

    @GetMapping("/mock")
    public String mock() {
        for (int i = 0; i < 12; i++) {
            final Order order = new Order();
            final String index = String.valueOf(i + 1);
            order.setUserId(index);
            order.setOrderName(index);
            this.orderService.save(order);
        }
        return "SUCCESS";
    }

}
  • OrderService.java
package com.example.demo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.Order;

/**
 * (Order)表服务接口
 *
 * @author 
 * @since 2021-12-14 10:53:05
 */
public interface OrderService extends IService<Order> {

}
  • OrderServiceImpl.java
package com.example.demo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.dao.OrderDao;
import com.example.demo.entity.Order;
import com.example.demo.service.OrderService;
import org.springframework.stereotype.Service;

/**
 * (Order)表服务实现类
 *
 * @author 
 * @since 2021-12-14 10:53:06
 */
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, Order> implements OrderService {

}
  • OrderDao.java
package com.example.demo.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Order;

/**
 * (Order)表数据库访问层
 *
 * @author 
 * @since 2021-12-14 10:53:00
 */
public interface OrderDao extends BaseMapper<Order> {

}
  • Order.java
package com.example.demo.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.io.Serializable;

/**
 * (Order)表实体类
 *
 * @author 
 * @since 2021-12-14 10:53:04
 */
@SuppressWarnings("serial")
@TableName("t_order")
public class Order extends Model<Order> {

    @TableId
    private String orderId;
    
    private String userId;
    
    private String orderName;


    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    /**
     * 获取主键值
     *
     * @return 主键值
     */
    @Override
    protected Serializable pkVal() {
        return this.orderId;
    }
    }