• SpringBoot+Mybatis-plus+shardingsphere实现分库分表


    SpringBoot+Mybatis-plus+shardingsphere实现分库分表

    介绍

    实现亿级数据量分库分表的项目是一个挑战性很高的任务,下面是一个基于Spring Boot的简单实现方案:

    1. 数据库选择:使用MySQL数据库,因为MySQL在分库分表方面有较成熟的解决方案。

    2. 分库分表策略:可以采用水平分库分表的策略,根据一定的规则将数据分散存储在不同的数据库和表中,例如可以根据用户ID、订单ID等进行分片。

    3. 数据分片策略:可以采用基于雪花算法的分布式ID生成器来生成全局唯一的ID,确保数据在不同数据库和表中的唯一性。

    4. 数据同步:考虑到数据分散存储在不同的数据库和表中,需要实现数据同步机制来保证数据的一致性,可以使用Canal等开源工具来实现MySQL数据的实时同步。

    5. 连接池优化:在处理大量数据时,连接池的配置尤为重要,可以使用Druid等高性能的连接池来提升数据库连接的效率。

    6. 缓存机制:考虑使用Redis等缓存工具来缓存热点数据,减轻数据库的压力,提升系统性能。

    7. 分布式事务:在分库分表的场景下,涉及到跨库事务,可以考虑使用分布式事务框架,如Seata等来保证事务的一致性。

    8. 监控与调优:实时监控数据库的性能指标,及时调整分片策略和数据库配置,保证系统的稳定性和性能。

    引入依赖

    <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.28version>
            dependency>
    
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-boot-starterartifactId>
                <version>3.4.3version>
            dependency>
    
            
            
            <dependency>
                <groupId>org.apache.shardingspheregroupId>
                <artifactId>shardingsphere-jdbc-core-spring-boot-starterartifactId>
                <version>5.2.0version>
            dependency>
    
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <optional>trueoptional>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    yaml配置

    server:
      port: 10086
    
    spring:
      shardingsphere:
        # 数据源配置
        datasource:
          # 数据源名称,多数据源以逗号分隔
          names: db0,db1
          db0:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/ds0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: root
          db1:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/ds1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: root
        # 分片规则配置
        rules:
          sharding:
            # 分片算法配置
            sharding-algorithms:
              database-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式(算法自行定义,此处为方便演示效果)
                  algorithm-expression: db$->{age % 2}
              table-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式
                  algorithm-expression: user_$->{age % 3}
            tables:
              # 逻辑表名称
              user:
                # 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}
                actual-data-nodes: db${0..1}.user_${0..2}
                # 分库策略
                database-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: age
                    # 分片算法名称
                    sharding-algorithm-name: database-inline
                # 分表策略
                table-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: age
                    # 分片算法名称
                    sharding-algorithm-name: table-inline
        # 属性配置
        props:
          # 展示修改以后的sql语句
          sql-show: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    DDL准备

    数据库ds0

    -- ds0.user_0 definition
    
    CREATE TABLE `user_0` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    -- ds0.user_1 definition
    
    CREATE TABLE `user_1` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    -- ds0.user_2 definition
    
    CREATE TABLE `user_2` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    数据库ds1

    -- ds1.user_0 definition
    
    CREATE TABLE `user_0` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    -- ds1.user_1 definition
    
    CREATE TABLE `user_1` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    -- ds1.user_2 definition
    
    CREATE TABLE `user_2` (
      `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(32) NOT NULL COMMENT '姓名',
      `age` int NOT NULL COMMENT '年龄',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    entity

    package com.kang.sharding.entity;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    @Data
    @TableName("user")  
    public class User {
        @TableId(value = "id",type = IdType.AUTO)
        private Long id;
    
        private String name;
    
        private Integer age;
        // getter, setter, toString...  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    cotroller

    package com.kang.sharding.controller;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
    import com.kang.sharding.entity.User;
    import com.kang.sharding.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController  
    @RequestMapping("/user")  
    public class UserController {  
      
        @Autowired  
        private UserService userService;
      
        @PostMapping ("add")
        public boolean createUser(@RequestBody User user) {
            return userService.save(user);  
        }
    
        @PostMapping ("update")
        public boolean updateByAge(@RequestBody User user){
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            // 分片数据不允许更新,否则会报错
            updateWrapper.eq(User::getAge,user.getAge()).set(User::getName,user.getName());
            return userService.update(updateWrapper);
        }
    
        @GetMapping ("delete")
        public boolean deleteUserByAge(@RequestParam("age") Integer age) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getAge,age);
            return userService.remove(queryWrapper);
        }
      
        @GetMapping("/{age}")
        public List<User> getUserByAge(@PathVariable Integer age) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getAge,age);
            return userService.list(queryWrapper);
        }  
      
        // 其他方法...  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    service

    package com.kang.sharding.service;
    
    import com.kang.sharding.entity.User;
    import com.kang.sharding.mapper.UserMapper;
    import org.springframework.stereotype.Service;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
      
    @Service  
    public class UserService extends ServiceImpl<UserMapper, User> {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Mapper

    package com.kang.sharding.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.kang.sharding.entity.User;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    启动类

    package com.kang.sharding;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class ShardingJdbcProjectApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ShardingJdbcProjectApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试

    添加

    在这里插入图片描述
    在这里插入图片描述

    修改

    在这里插入图片描述
    在这里插入图片描述

    查询

    在这里插入图片描述

    在这里插入图片描述

    删除

    在这里插入图片描述

    在这里插入图片描述

    总结

    这只是个简单的入门示例,后续深入研究

  • 相关阅读:
    图片如何转换成PDF格式?教你一招快速转换
    LoadRunner下载与安装
    一文读懂:低代码和无代码的演进历程、应用范围
    1.安装 docker 容器并配置镜像加速器
    LeetCode第 86 场双周赛
    如何在 uniapp 里面使用 pinia 数据持久化 (pinia-plugin-persistedstate)
    HLS学习2:使用ARM核点灯
    任务分配——斜率优化dp——运输小猫
    52_数据结构
    Scratch、Python、C++,谁才是少儿编程的第一选择?
  • 原文地址:https://blog.csdn.net/LuckFairyLuckBaby/article/details/136471380