赞
踩
去年开发一个项目的时候,因为系统的核心数据是定时从外界发送过来的,数据量比较大,后来很快单表就达到了千万级别,这就需要分库分表,最后选择了ShardingSphere,原因就是比较容易上手。
官网地址:https://shardingsphere.apache.org/
如上图所示,当前版本是4.x,并且官网支持中文阅读。点击文档下拉4.x版本:
简介如下:
定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
这两部分的介绍可以阅读官网,这里就不介绍了。
本项目基于SpringBoot 2.1.5使用ShardingSphere和Mybatis-Plus实现分库分表。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.shardingsphere</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>基于 Spring Boot 2.1.15 使用sharding-sphere + Mybatis-Plus 实现分库分表</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
ds0
├── user_0
└── user_1
ds1
├── user_0
└── user_1
既然是分库分表 库结构与表结构一定是一致的。
数据库: ds0
CREATE DATABASE IF NOT EXISTS `ds0`/*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */; USE `ds0`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user_0 -- ---------------------------- DROP TABLE IF EXISTS `user_0`; CREATE TABLE `user_0`( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `age` INT(11) DEFAULT NULL, PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT charset=utf8mb4; -- ---------------------------- -- Table structure for user_1 -- ---------------------------- DROP TABLE IF EXISTS `user_1`; CREATE TABLE `user_1`( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `age` INT(11) DEFAULT NULL, PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT charset=utf8mb4; SET FOREIGN_KEY_CHECKS = 1;
数据库:ds1
CREATE DATABASE IF NOT EXISTS `ds1`/*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */; USE `ds1`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user_0 -- ---------------------------- DROP TABLE IF EXISTS `user_0`; CREATE TABLE `user_0`( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `age` INT(11) DEFAULT NULL, PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT charset=utf8mb4; -- ---------------------------- -- Table structure for user_1 -- ---------------------------- DROP TABLE IF EXISTS `user_1`; CREATE TABLE `user_1`( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `age` INT(11) DEFAULT NULL, PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT charset=utf8mb4; SET FOREIGN_KEY_CHECKS = 1;
# 数据源 ds0,ds1 sharding: jdbc: datasource: names: ds0,ds1 # 第一个数据库 ds0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://192.168.67.1:3306/ds0?characterEncoding=utf-8 username: root password: 123 # 第二个数据库 ds1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://192.168.67.1:3306/ds1?characterEncoding=utf-8 username: root password: 123 # 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略 config: sharding: # 分库策略 default-database-strategy: inline: sharding-column: id algorithm-expression: ds$->{id % 2} # 分表策略 其中user为逻辑表 分表主要取决于age行 tables: user: actual-data-nodes: ds$->{0..1}.user_$->{0..1} table-strategy: inline: sharding-column: age # 分片算法表达式 algorithm-expression: user_$->{age % 2} # 主键 UUID 18位数 如果是分布式还要进行一个设置 防止主键重复 # key-generator-column-name: id # 打印执行的数据库 props: sql: show: true # 打印执行的sql语句 spring: main: allow-bean-definition-overriding: true
使用配置文件方式实现分库以及分表,配置说明:
实体类:
package com.shardingsphere.demo.entity; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; import lombok.Data; @Data @TableName("user") public class User extends Model<User> { /** * 主键id */ private int id; /** * 名称 */ private String name; /** * 年龄 */ private int age; }
mapper(记得在启动类上添加mapper扫描路径@MapperScan(“com.shardingsphere.demo.dao”)):
package com.shardingsphere.demo.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shardingsphere.demo.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
service:
package com.shardingsphere.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shardingsphere.demo.entity.User;
public interface UserService extends IService<User> {
}
serviceImpl:
package com.shardingsphere.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shardingsphere.demo.dao.UserMapper;
import com.shardingsphere.demo.entity.User;
import com.shardingsphere.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
controller:
package com.shardingsphere.demo.controller; import com.shardingsphere.demo.entity.User; import com.shardingsphere.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/select") public List<User> select(){ return userService.list(); } @GetMapping("/insert") public Boolean insert(User user){ return userService.save(user); } }
启动项目,然后打开浏览器分别访问:
http://localhost:8080/insert?id=1&name=1hd&age=12
http://localhost:8080/insert?id=2&name=1hd&age=13
http://localhost:8080/insert?id=3&name=1hd&age=14
http://localhost:8080/insert?id=4&name=1hd&age=15
然后查看控制台日志:
根据分片算法和分片策略,不同的id以及age取模后添加到不同库的不同表里,这就达到了分库分表的结果。
查询测试,访问http://localhost:8080/select,查看控制台日志:
分别从ds0数据库两张表和ds1两张表查询结果 然后汇总结果返回。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。