首页 > 其他分享 >分库分表

分库分表

时间:2024-04-11 23:46:12浏览次数:20  
标签:分库 int distribute order user 分表 NULL id

分库分表

什么是ShardingSphere

Apache ShardingSphere是一款分布式的数据库生态系统。可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。

详细见官网详解

什么是ShardingSphere-JDBC

ShardingSphere-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。

产品功能

特性 定义
数据分片 数据分片,是应对海量数据存储于计算的有效手段,可水平扩展计算和存储
分布式事务 事务能力,是保证数据库完整。安全的关键技术
读写分离 应对高压力业务访问的手段
数据加密 保证数据安全的基本手段
数据迁移 打通数据生态的关键能力。
.... ....

产品优势

  • 极致性能
  • 生态兼容
  • 业务零侵入
  • 运维低成本
  • 安全稳定
  • ...

ShardingSphere与SpringBoot 集成

  • 引入Maven依赖
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
</dependency>

创建distribute_db.t_order_0和distribute_db.t_order_1

CREATE TABLE `t_order_0` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `status` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表'

CREATE TABLE `t_order_1` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `status` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表'

策略配置

分表策略

spring:
  shardingsphere:
    # 定义数据源名称ds0
    datasource:
      names: ds0
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        jdbcUrl: jdbc:mysql://localhost:3306/distribute_db
        username: root
        password: 123456
    # 定义规则
    rules:
      sharding:
        # 数据分片规则配置
        tables:
          # 逻辑表名称
          t_order:
            # 由数据源名+表明组成(参考inline语法规则):{0..1}表示0~1
            actualDataNodes: ds0.t_order_${0..1}
            # 分表策略
            tableStrategy:
              standard:
                # 分表字段
                shardingColumn: id
                # 分表算法表达式
                shardingAlgorithmName: t_order_inline
            # 分布式id生成策略    
            keyGenerateStrategy:
              column: id
              keyGeneratorName: snowflake
        sharding-algorithms:
          t_order_inline:
            type: inline
            props:
              # 举例,如id%2==0,存储到t_order_0;id%2==1,存储到t_order_1
              algorithm-expression: t_order_${id % 2}
        # 配置分布式主键生成算法,指定为雪花算法
        key-generators:
          snowflake:
            type: SNOWFLAKE
    # 打印sql
    props:
      sql-show: true

验证水平分表

OrderDao

@Mapper
public interface OrderDao {

	@Insert("insert into t_order (user_id, status) values (#{userId}, #{status})")
	void insertOrder(@Param("userId")Integer userId,@Param("status")Integer status);

	@Select("select * from t_order where id = #{id}")
	Map<String,Object> selectOrderById(@Param("id")Long id);
}

测试类

@Test
public void insertOrderOne(){
    orderDao.insertOrder(1,1);
}

如遇报错内容为Cause by:Caused by:java.lang.NoSuchMethodErrarCreate breakpoint :org.apache.shardingsphere,infra.util.yaml.constructor.ShardingSphereYamlConstructor$1.setCodePointLimit(I)V

添加依赖

 <dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.33</version>
</dependency>

再次插入记录,查看输出日志

image-20240411203854137

从日志中,可以看到主键记录为985280812100354048的记录被插入到t_order_0中。

借助for循环插入更多记录

@Test
public void insertOrder() {
    for (int i = 0; i < 10; i++) {
        orderDao.insertOrder(1,1);
    }
}

image-20240411204054947

@Select("select * from t_order where id = #{id}")
Map<String,Object> selectOrderById(@Param("id")Long id);

查看记录插入的记录985282301912940545

@Test
public void testSelectOrder(){
    System.out.println(orderDao.selectOrderById(985282301912940545L));
}

image-20240411205016577

分库策略

水平分表

新建数据库distribute_db2,使用user_id字段取余进行分库判断。user_id % 2==0,存放在distribute_db,否则distribute_db2

创建新的建表语句

create database `distribute_db2`;

use distribute_db2;

CREATE TABLE `t_order_0` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `status` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=985282301912940546 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表';

CREATE TABLE `t_order_1` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `status` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=985282301912940546 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表'

配置规则

spring:
  application:
    name: distribute-db

  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        jdbcUrl: jdbc:mysql://localhost:3306/distribute_db
        username: root
        password: 123456
	  # 添加分库数据源信息
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        jdbcUrl: jdbc:mysql://localhost:3306/distribute_db2
        username: root
        password: 123456

    rules:
      sharding:
        tables:
          t_order:
            actualDataNodes: ds${0..1}.t_order_${0..1}
            tableStrategy:
              standard:
                shardingColumn: id
                shardingAlgorithmName: t_order_inline
            # 添加分库策略    
            database-strategy:
              standard:
                shardingColumn: user_id
                shardingAlgorithmName: t_order_user_inline
            keyGenerateStrategy:
              column: id
              keyGeneratorName: snowflake
        sharding-algorithms:
          t_order_inline:
            type: inline
            props:
              algorithm-expression: t_order_${id % 2}
          # 添加分库策略,按照user_id%2区分ds0,ds1    
          t_order_user_inline:
            type: inline
            props:
              algorithm-expression: ds${user_id % 2}
        key-generators:
          snowflake:
            type: SNOWFLAKE
    props:
      sql-show: true
    

批量插入数据

@Test
public void insertOrder() {
    for (int i = 0; i < 10; i++) {
        orderDao.insertOrder(i,1);
    }
}

观察日志信息,可以看到按照user_id和order_id的差异,放入不同数据源中。

image-20240411231946559

  • 根据user_id查询记录
@Select("select * from t_order where user_id =#{userId}")
Map<String,Object> selectOrderByUserId(@Param("userId")Integer userId);
@Test
public void testSelectOrderByUserId(){
    System.out.println(orderDao.selectOrderByUserId(0));
}

根据user_id为0只能定位到在ds_0数据源中,但无法定位实在t_order_0表还是t_order_1表中,因此执行union all连表查询。

image-20240411232233002

  • 如果根据user_id + order_id组合查询
@Select("select * from t_order where id = #{id} and user_id = #{userId}")
Map<String,Object> selectOrderByIdAndUserId(@Param("id")Long orderId,@Param("userId")Integer userId);
@Test
public void testSelectOrderByIdAndUserId(){
    System.out.println(orderDao.selectOrderByIdAndUserId(985318439167983616L,0));
}

根据user_id和order_id可以唯一定位数据源及表信息,因此无连表查询

image-20240411232638297

垂直分库

标签:分库,int,distribute,order,user,分表,NULL,id
From: https://www.cnblogs.com/shine-rainbow/p/18130264

相关文章

  • 对于开发中分库分表常用规则
    分库分表是一种数据库水平拆分的策略,常用的规则有:1.垂直分库:将不同的业务模块或者功能模块分别放在不同的数据库中,每个数据库负责处理特定的业务逻辑。这样可以降低单一数据库的负载压力,并且提高了系统的稳定性和可维护性。2.水平分表:将同一个表按照一定的规则进行拆分,将......
  • 数据库读写分离(主从复制)和分库分表详解
    数据库读写分离(主从复制)和分库分表在文章开头先抛几个问题:什么是读写分离?解决了什么问题?使用时应该注意什么?会出现什么问题?什么是主从复制?他有什么缺点?我们为什么要分库分表?什么时候才需要分库分表呢?我们的评判标准是什么?这些问题你都搞清楚了吗?相信看完这篇文章你一定......
  • 针对postgresql已经存在数据,对字段进行hash后分表
    PostgreSQL分表方案在实际应用中,我们经常需要对已经存在的数据进行分表处理,以提高查询效率和数据存储的可靠性。本文将介绍如何使用PostgreSQL对已存在的数据进行分表处理。分表方案对于已经存在的数据,我们可以采用hash分表的方案。具体来说,我们可以使用某个字段的hash值......
  • DIY 3 种分库分表分片算法,自己写的轮子才吊!
    大家好,我是小富~前言本文是《ShardingSphere5.x分库分表原理与实战》系列的第六篇,书接上文实现三种自定义分片算法。通过自定义算法,可以根据特定业务需求定制分片策略,以满足不同场景下的性能、扩展性或数据处理需求。同时,可以优化分片算法以提升系统性能,规避数据倾斜等问题。在......
  • 消息队列,缓存,分库分表是高并发解决方案
    消息队列的七种经典应用场景 在笔者心中,消息队列,缓存,分库分表是高并发解决方案三剑客。在职业生涯中,笔者曾经使用过ActiveMQ、RabbitMQ、Kafka、RocketMQ这些知名的消息队列。这篇文章,笔者结合自己的真实经历,和大家分享消息队列的七种经典应用场景。1异步&解耦笔......
  • Spring boot 使用shardingsphere 分表使用
    1、shardingsphere介绍   ApacheShardingSphere是一款分布式SQL事务和查询引擎,可通过数据分片、弹性伸缩、加密等能力对任意数据库进行增强。官方网站地址ApacheShardingSphere2、SpringBoot项目接入2.1、 maven添加依赖<dependency><groupId>org.apach......
  • 一口气搞懂分库分表 12 种分片算法,大厂都在用
    大家好,我是小富~前言本文是《ShardingSphere5.x分库分表原理与实战》系列的第五篇文章,我们一起梳理下ShardingSphere框架中的核心部分分片策略和分片算法,其内部针为我们提供了多种分片策略和分片算法,来应对不同的业务场景,本着拿来即用的原则。这次将详细介绍如何在ShardingSpher......
  • 基因法分库分表
    问题假设我们有一张超大的订单表(N亿),里面有order_id、user_id等字段。能通过order_id快速查找对应订单能通过user_id快速查找该用户具有的订单列表像上面这样的要求改怎样做呢?通过哈希订单ID取模?那如何满足通过用户ID快速查找订单列表呢?什么是基因算法理论:Hemeanttha......
  • 开源一个教学型分库分表示例项目 shardingsphere-jdbc-demo
    在笔者心中,消息队列,缓存,分库分表是高并发解决方案三剑客。分库分表之所以被广泛使用,因为工程相对简单,但分库分表并不仅仅是分片,还是需要考虑如何扩缩容(全量同步、增量同步、数据校验等)。因此笔者做了一个教学型分库分表示例项目,计划将分库分表的技术体系都实际演示一遍。ht......
  • 什么是分库分表?用Java手写一个分库分表组件
    分库分表分库分表路由组件的主要功能是负责处理数据在多个数据库和表之间的分配和路由。在分库分表的场景中,数据会根据一定的策略(如业务逻辑、哈希算法等)被分散到不同的数据库或表中,以提高系统的并发处理能力和扩展性。具体来说,分库分表路由组件需要完成以下任务:数据源的......