ShardingSphere实践(2)水平分库

分库概念

分库是指将一个数据库的数据按照某种规则划分为多个独立的子库。每个子库都是一个独立的数据库,具有自己的表结构和数据存储。分库常用于处理大规模数据和高并发访问的场景,以提高系统的可扩展性和性能。

分库的主要目的是实现数据的分片存储和并行处理,从而提高数据库的处理能力和吞吐量。通过将数据分散存储在多个子库中,可以将负载均衡到不同的数据库节点上,减轻单一数据库的压力。同时,分库还可以支持水平扩展,使系统能够处理更大量级的数据和并发请求。

在进行分库时,常用的划分依据包括:

1.垂直分库:按照业务功能将不同的表分布到不同的数据库中,例如将用户相关表放在一个数据库,订单相关表放在另一个数据库。

2.水平分库:按照某个字段或规则将数据行分散到不同的数据库中,例如按照用户ID的哈希值进行分片,将不同用户的数据分布到不同的数据库中。

值得注意的是,分库操作需要考虑数据一致性、事务处理、跨库查询等问题,因此需要仔细设计和实施。同时,分库也增加了系统的复杂性和管理难度,需要综合考虑系统需求和资源成本。

下面我们进行分库实践

步骤基本和上一篇一样,只是配置不同

ShardingSphere实践(1)水平分表-CSDN博客

如果你看了这篇文章,也可以直接在基础上进行修改

一.加入依赖

<properties>
        <mysql.version>5.1.37</mysql.version>
        <mybatis.plus.boot.starter.version>3.4.2</mybatis.plus.boot.starter.version>
        <lombok.version>1.18.24</lombok.version>
        <druid.version>1.1.22</druid.version>
        <shardingsphere.version>4.0.0-RC1</shardingsphere.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <scope>provided</scope>
            <version>${lombok.version}</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis.plus.boot.starter.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
    </dependencies>

二.配置ShardingSphere

application.properties

# 单数据库分表,指定数据源名称
spring.shardingsphere.datasource.names=master0,master1

# 分表时一个实体类对应多张表,设置为true覆盖
spring.main.allow-bean-definition-overriding=true

# 配置第一个数据源,包括连接池、驱动类、数据库地址、用户名、密码
spring.shardingsphere.datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master0.url=jdbc:mysql://localhost:3306/shardingsphere-demo?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.master0.username=root
spring.shardingsphere.datasource.master0.password=123456

# 配置第二个数据源,包括连接池、驱动类、数据库地址、用户名、密码
spring.shardingsphere.datasource.master1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master1.url=jdbc:mysql://localhost:3306/shardingsphere-demo2?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.master1.username=root
spring.shardingsphere.datasource.master1.password=123456

# 指定数据库、数据表分布情况
spring.shardingsphere.sharding.tables.user.actual-data-nodes=master$->{0..1}.user

# 指定表的主键id,生成策略,SNOWFLAKE(雪花算法)
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

# 指定数据库分片策略,tenant_id取余后为0的分配到master0,为1的分配到master1
spring.shardingsphere.sharding.tables.user.database-strategy.inline.sharding-column=tenant_id
spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=master$->{tenant_id % 2}

# 打开sql输出日志
spring.shardingsphere.props.sql.show=true

三.建库建表

建立上面配置的两个数据库,我这里分别是shardingsphere-demo和shardingsphere-demo2

分别在两个数据库下建立user表

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `tenant_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

四.编写业务代码

实体类

@Data
public class User {
    @TableId
    private Long id;
    @TableField(value = "tenant_id")
    private Integer tenantId;
    private String name;
}

UserMapper

public interface UserMapper extends BaseMapper<User> {
}

UserService

public interface UserService extends IService<User> {
}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

五.测试

@SpringBootTest(classes = ShardingsphereDemoApplication.class)
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testUser() {
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setName("user_" + i);
            Integer tenantId = 0;
            if (i > 6) {
                tenantId = 1;
            }
            user.setTenantId(tenantId);
            userService.save(user);
        }
    }
}

shardingsphere-demo数据库下的user表

shardingsphere-demo2数据库下的user表

数据根据tenant_id分别分配到两个数据库的user表中了

再试一下查询,执行下面代码

List<User> list = userService.list();

可以看到,这里分别从两个数据库查询数据,完成分库效果

分库分表

分库实际上是粒度更大的数据分片,通过分库可以把数据库压力分配到多个数据库节点上,提高性能和可扩展性,但有时候对于单表数据过多的情况,跨多个库性能并不理想,或者我们并没有那么多数据库资源来增加数据库节点,那么,我们可以对每一个数据库再进行分表,尽可能达到最高的数据库利用率

下面进行分库、分表实践

在ShardingSphere中非常简单,只需增加几行配置

# 指定数据库分布情况,数据库里面表分布情况,如下user表,对应user_1,user_2两张表,数据库有master0、master1
spring.shardingsphere.sharding.tables.user.actual-data-nodes=master$->{0..1}.user_$->{1..2}

# 指定表分片策略,分片列为id字段,根据id字段的值进行分片,分片策略为id的值 % 2,余数为0的放入user_0表,为1的放入user_1表,为2的放入user_2表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id % 2 + 1}

建表,分别在两个数据库建立user_1和user_2

CREATE TABLE `user_1` (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `tenant_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user_2` (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `tenant_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

执行Test

@SpringBootTest(classes = ShardingsphereDemoApplication.class)
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testUser() {
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setName("user_" + i);
            Integer tenantId = 0;
            if (i > 6) {
                tenantId = 1;
            }
            user.setTenantId(tenantId);
            userService.save(user);
        }
    }
}

完成后,查看shardingsphere-demo数据库下两张表的数据 

shardingsphere-demo2下的表数据

数据tenant_id为0的被分配到shardingsphere-demo数据库中,同时,根据id的余数再分配到两张表中,实现分库分表的效果

执行以下查询语句,测试结果是否正确

List<User> list = userService.list();

 ShardingSphere分别从2个库4张表中查询数据

公共表(广播表)

公共表即每个数据库需要单独冗余一份完整数据的表,例如字典表

下面建一个dict字典表进行测试

建表语句

CREATE TABLE `dict` (
  `id` bigint(20) NOT NULL,
  `dict_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

实体类

@Data
public class Dict {
    @TableId
    private Long id;
    private String dictName;
}

 其他的Service、Mapper请参照上面User表建立

增加配置

# 配置公共表
spring.shardingsphere.sharding.broadcast-tables=dict
spring.shardingsphere.sharding.tables.dict.key-generator.column=id
spring.shardingsphere.sharding.tables.dict.key-generator.type=SNOWFLAKE

 测试

@SpringBootTest(classes = ShardingsphereDemoApplication.class)
public class UserServiceTest {

    @Autowired
    private DictService dictService;

    @Test
    public void testUser() {
        Dict dict = new Dict();
        dict.setDictName("字典值1");
        dictService.save(dict);
    }
}

 

查看数据库,可以看到两个库的dict表都插入了一条数据

水平分库的优缺点

优点

分库的优点有很多,例如提高系统性能和扩展性,使系统能够处理更大规模的数据和并发请求。数据库操作可以在多个节点上并行执行,从而加快数据处理速度。有助于提高系统的响应性和处理能力,特别是在大数据量和高并发的场景下。增强数据安全性、简化数据库管理、地理位置灵活性(可以根据实际需求将数据存储在不同的地理位置,以满足法律法规或业务需求)等

缺点

分库时需要考虑数据一致性、事务处理、跨库查询等问题,因此需要仔细设计和实施。同时,分库也增加了系统的复杂性和管理难度,需要综合考虑系统需求和资源成本,如果系统规模不大时,没必要进行分库,跨库操作具有包括网络开销在内的损耗,小数据量的情况下反而性能不如单库操作

  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值