上一章分享了 Sharding-JDBC 搭建读写分离,本章将用sharding-jdbc实现分库分表功能

1.为什么要分库分表?

举个栗子:当单表数据量超过1000万后,查询的速度将会慢下来,利用索引,读写分离等优化,如果当数据量超过5000万时,一些常见的优化方法将失去作用,此时把单表水平划分到多库多表中,提升查询速度,而sharding-jdbc可以帮你完成水平拆分,而我们只需添加一些配置即可

2.官方文档

基本上是参照中文帮助文档进行配置
GitHub的地址:https://github.com/apache/incubator-shardingsphere
shardingsphere:https://github.com/apache/incubator-shardingsphere-example
中文文档地址:https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/usage/read-write-splitting/

3.代码实现(mybatis)
  • 1.有3张表 t_member、t_order、t_order_item,拆分到2个数据库中,每个数据库2份,相当于每张表拆成了4张,需要注意的是每个表的主键Id尽量设置成 bigint (我开始设置为varchar,结果分表时报错),结构如下:
    Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表
  • 2.新建SpringBoot项目,引入依赖:
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.shardingsphere</groupId>
	<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
	<version>4.0.0-RC1</version>
</dependency>
<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>2.0.0</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.16</version>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.47</version>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
  • 3.引入mybatis generator 自动生成代码插件,生成实体类与mybatis xml文件,怎么生成
<plugin>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-maven-plugin</artifactId>
	<version>1.3.6</version>
	<configuration>
		<configurationFile>${basedir}/src/main/resources/generator/config.xml</configurationFile>
		<overwrite>true</overwrite>
		<verbose>true</verbose>
	</configuration>
</plugin>
  • 4.添加配置文件,这点很重要,否则无法实现分库分表,ds$->{0..1}.t_member$->{0..1},表达式相当于:ds0.t_member0、ds0.t_member1、ds1.t_member0、ds1.t_member1,在配置中配置了 key-generator.column,所以新增该表数据时,不需要给主键id赋值,sharding-jdbc会调用内置的SNOWFLAKE算法生成分布式id,请往下看
server.port=8071

# mybatis 配置
mybatis.mapper-locations=classpath:mapping/*.xml
mybatis.type-aliases-package=com.zypcy.sharding.sublibrarytable.entity

spring.shardingsphere.datasource.names=ds0,ds1

spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/ds0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=15000&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456

spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/ds1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=15000&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=123456

# 分库配置 , 根据member_id分库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=member_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{member_id % 2}

# 分表配置,根据member_id分表
spring.shardingsphere.sharding.tables.t_member.actual-data-nodes=ds$->{0..1}.t_member$->{0..1}
spring.shardingsphere.sharding.tables.t_member.table-strategy.inline.sharding-column=member_id
spring.shardingsphere.sharding.tables.t_member.table-strategy.inline.algorithm-expression=t_member$->{member_id % 2}
spring.shardingsphere.sharding.tables.t_member.key-generator.column=member_id
spring.shardingsphere.sharding.tables.t_member.key-generator.type=SNOWFLAKE
# 分表配置,根据order_id分表
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order$->{0..1}
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order$->{order_id % 2}
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 分表配置,根据order_id分表
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item$->{0..1}
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item$->{order_id % 2}
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE

spring.shardingsphere.props.sql.show=true
  • 5.添加MemberService服务接口与实现
public interface IMemberService {

    int insert(Member record);

    Member selectByPrimaryKey(Long memberId);

    int deleteByPrimaryKey(Long memberId);
}

@Service
public class MemberServiceImpl implements IMemberService {

    @Autowired private MemberMapper memberMapper;

    @Override
    public int insert(Member record) {
        return memberMapper.insertSelective(record);
    }

    @Override
    public Member selectByPrimaryKey(Long memberId) {
        return memberMapper.selectByPrimaryKey(memberId);
    }

    @Override
    public int deleteByPrimaryKey(Long memberId) {
        return memberMapper.deleteByPrimaryKey(memberId);
    }
}

@Mapper
public interface MemberMapper {
    int deleteByPrimaryKey(Long memberId);

    int insert(Member record);

    int insertSelective(Member record);

    Member selectByPrimaryKey(Long memberId);

    int updateByPrimaryKeySelective(Member record);

    int updateByPrimaryKey(Member record);
}
  • 6.添加MemberController
@RequestMapping("/member")
@RestController
public class MemberController {

    @Autowired
    private IMemberService memberService;

    @RequestMapping("/add")
    public Member add(){
        Member member = new Member();
        //member.setMemberId(IdWorker.getLongId()); 不用手动设置主键id,新增时,sharding-jdbc会自动赋值,因为在配置文件中配置了该列使用SNOWFLAKE算法生成值
        member.setMemberName("张三");
        member.setNickName("闪耀的瞬间");
        member.setAccountNo(member.getMemberId()+"");
        member.setPassword("123465");
        member.setAge(27);
        member.setBirthDate(new Date());
        member.setEblFlag("1");
        member.setDelFlag("0");
        member.setDescription("xxx");
        member.setCreateTime(new Date());
        member.setUpdateTime(new Date());
        memberService.insert(member);
        return member;
    }

    @RequestMapping("/findById")
    public Member findById(Long memberId){
        return memberService.selectByPrimaryKey(memberId);
    }

    @RequestMapping("/delete")
    public String delete(Long memberId){
        memberService.deleteByPrimaryKey(memberId);
        return "success";
    }
}
  • 7.启动项目,访问新增接口 http://localhost:8071/member/add ,可以看到页面返回了新增后的数据
    Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表
    同时查看Intellij IDEA控制台,可以看到数据插入到 ds1 库的 t_member1 表了 Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表
    再查看ds1数据库的t_member1 表,有memberId:331930875505672193的记录,前面的是我多次调用add方法新增的
    Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表

  • 8.访问查询接口 http://localhost:8071/member/findById?memberId=331930875505672193
    Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表
    同时查看控制台,sql自动路由到 ds1 库去查询数据了
    Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表

实体类与mapper xm文件没有列出来,请参照上面的mybatis generator 自动生成代码插件或源码

好了,更多的应用需要朋友们自行研究,还弄了个jpa版本的,都在源码中,已上传了,查看源码

Sharding-Sphere:SpringBoot和Sharding-JDBC分库分表

相关文章: