聊一聊ShardingSphere的分库分表

当业务的数据量暴增,单个数据库无法承载时,我们就需要扩容,此时就可以使用ShardingSphere的分库分表。

1、垂直拆分

数据库的垂直拆分:比如将业务拆分成多个微服务。
表的垂直拆分:比如将一个订单表里面既有订单信息,又有优惠券信息,我们就可以将它拆分成两个表。

2、水平拆分

简单的来说就是将数据分片存储。

SpringBoot整合ShardingSphere-JDBC实现分库分表

首先我们创建3个数据源:server-user,server-order0,server-order1

docker run -d \
-p 3301:3306 \
-v /yy/mysql/user/conf:/etc/mysql/conf.d \
-v /yy/mysql/user/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-user \
mysql:8.0.29

docker run -d \
-p 3310:3306 \
-v /yy/mysql/order0/conf:/etc/mysql/conf.d \
-v /yy/mysql/order0/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order0 \
mysql:8.0.29

docker run -d \
-p 3311:3306 \
-v /yy/mysql/order1/conf:/etc/mysql/conf.d \
-v /yy/mysql/order1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order1 \
mysql:8.0.29

在server-order0、server-order1的db_order数据库中分别创建两个表:

CREATE TABLE `t_order0` (
	`id` BIGINT(20) UNSIGNED NOT NULL,
	`order_no` VARCHAR(50),
	`user_id` BIGINT(19) ,
	`amount` DECIMAL(20,6) ,
	PRIMARY KEY (`id`) USING BTREE
)
CREATE TABLE `t_order1` (
	`id` BIGINT(20) UNSIGNED NOT NULL,
	`order_no` VARCHAR(50),
	`user_id` BIGINT(19),
	`amount` DECIMAL(20,6),
	PRIMARY KEY (`id`) USING BTREE
)
# 应用名称
spring.application.name=sharding-sph

spring.profiles.active=dev

spring.shardingsphere.mode.type=Memory
spring.shardingsphere.props.sql-show=true
# 配置真实数据源
spring.shardingsphere.datasource.names=server-user,server-order0,server-order1

# 配置第 1 个数据源
spring.shardingsphere.datasource.server-user.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-user.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-user.jdbc-url=jdbc:mysql://IP地址:3301/db_user?serverTimezone=UTC&characterEncoding=UTF-8
spring.shardingsphere.datasource.server-user.username=root
spring.shardingsphere.datasource.server-user.password=123456

# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://IP地址:3310/db_order?serverTimezone=UTC&characterEncoding=UTF-8
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456

# 配置第 3 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://IP地址:3311/db_order?serverTimezone=UTC&characterEncoding=UTF-8
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456

#---------标准分片表配置-----------
spring.shardingsphere.rules.sharding.tables.t_user.actual-data-nodes=server-user.t_user
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}

# 分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 分片算法配置---INLINE算法
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userId.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userId.props.algorithm-expression=server-order$->{user_id%2}

# 分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 分片算法配置---MOD算法
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2

# 分表策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 分片算法配置---hashMod算法
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2

# 分片列名称
##------分库策略
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod

# 分片列名称
##----分表策略
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod


#-----------分布式序列策略配置
# 分布式序列策略配置
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
#算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake

spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE

注:在配置数据节点时,我们为了显示的更加简便易读可以使用行表达式,行表达式标识符可以使用 ${…},或 $->{…},前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{…}

创建Order实体类:

@TableName("t_order")
@Data
public class Order {

//    @TableId(type = IdType.ASSIGN_ID)
    @TableId(type = IdType.AUTO) //配置了shardingSphere的雪花算法分布式序列
    private Long id;
    private String orderNo;
    private Long userId;
    private BigDecimal amount;

}
package com.yy.shardingsph.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yy.shardingsph.entity.Order;
import com.yy.shardingsph.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.List;

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    OrderMapper orderMapper;

    @RequestMapping("insert")
    public void testInsertOrder(){
        for (long i=100;i<109;i++){
            Order order = new Order();
            order.setOrderNo("yygood"+i);
            order.setUserId(1L);
            order.setAmount(new BigDecimal(100));
            orderMapper.insert(order);
        }

    }

    @RequestMapping("select")
    public void testSelectOrder(){

        List<Order> list = orderMapper.selectList(null);
        list.forEach(System.out::println);
    }

    @RequestMapping("selectByUserId")
    public void testSelectOrderByUserId(){
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",1L);
        List<Order> list = orderMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
}

在这里插入图片描述
可以看到插入数据时的逻辑SQL和真实SQL。
在这里插入图片描述
查询数据时的逻辑SQL和真实SQL,我们可以发现真实SQL在查询时会分别对不同库里的order0表和order1表进行联合查询,最后将两次查询的结果合并起来显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值