Shardingsphere的分库分表+读写分离+分页条件查询

Shardingsphere的分库分表与读写分离

导入依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

创建数据库,前提是两个服务器做好了主从复制

在这里插入图片描述

spring:
  shardingsphere:
    mode:
      type: Memory                                                   # 内存模式,元数据保存在当前进程中
    datasource:
      names: master$->{0..1},slave$->{0..1}
      master0:                                                # 跟上面的数据源对应
        type: com.alibaba.druid.pool.DruidDataSource                 # 连接池
        url: jdbc:mysql://xxxxxx/test0                       # 连接url
        username: root
        password: 123456
      master1:                                                  # 跟上面的数据源对应
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://xxxxxx/test1
        username: root
        password: 123456
      slave0:                                                   # 跟上面的数据源对应
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://xxxxxx/test0
        username: root
        password: 123456
      slave1:                                                   # 跟上面的数据源对应
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://xxxxxx/test1
        username: root
        password: 123456

    rules:                                                           # 配置分库分表以及读写分离的规则
      sharding:                                                      # 配置分库分表规则
        tables:
          user:                                                      # 这个可以随便取,问题不大
            actual-data-nodes: master$->{0..1}.user$->{0..2}    # 实际节点名称,格式为 库名$->{0..n1}.表名$->{0..n2}
              # 其中n1、n2分别为库数量-1和表数量-1
              # 也可以使用${0..n1}的形式,但是会与Spring属性文件占位符冲突
            # 所以使用$->{0..n1}的形式

            database-strategy:                                       # 分库策略
              standard:                                              # 标准分库策略
                sharding-column: age                                 # 分库列名
                sharding-algorithm-name: age-mod                     # 分库算法名字
            table-strategy:                                          # 分表策略
              standard:                                              # 标准分表策略
                sharding-column: id                                  # 分表列名
                sharding-algorithm-name: id-mod                      # 分表算法名字

        sharding-algorithms:                                         # 配置分库和分表的算法
          age-mod:                                                   # 分库算法名字
            type: MOD                                                # 算法类型为取模
            props:                                                   # 算法配置的键名,所有算法配置都需要在props下
              sharding-count: 2                                      # 分片数量
          id-mod:                                                    # 分表算法名字
            type: MOD                                                # 算法类型为取模
            props:                                                   # 算法配置的键名,所有算法配置都需要在props下
              sharding-count: 3                                      # 分片数量

      readwrite-splitting:                                           # 配置读写分离规则
        data-sources:                                                # 数据源
          master0:                                              # 这个可以随便取,带有区分意义即可,比如这里表示的是主库test0的规则
            type: Static                                             # 静态类型
            load-balancer-name: round_robin                          # 负载均衡算法名字
            props:                                                   # 具体读写数据源需要配置在props下
              write-data-source-name: master0                   # 写数据源
              read-data-source-names: slave0                    # 读数据源
          master1:
            type: Static                                             # 静态类型
            load-balancer-name: round_robin                          # 负载均衡算法名字
            props:                                                   # 具体读写数据源需要配置在props下
              write-data-source-name: master1                   # 写数据源
              read-data-source-names: slave1                    # 读数据源
        load-balancers:                                              # 负载均衡配置
          round_robin:                                               # 跟上面负载均衡算法的名字对应
            type: ROUND_ROBIN                                        # 负载均衡算法
    props:
      sql-show: true                                                 # 打印SQL

测试

package com.ycz.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ycz.entity.User;
import com.ycz.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Random;

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserController {
    private final IUserService userService;

    @GetMapping("/insert")
    public boolean insert() {
        User user = new User();
        user.setName("啊实打实的撒");
        user.setAge(new Random().nextInt(100)+1);
        System.out.println(user);
        return userService.save(user);
    }

    @GetMapping("/select")
    public List<User> select() {
        return userService.list();
    }

    @GetMapping("/select/{id}")
    public Object getById(@PathVariable String id){
        return userService.getById(id);
    }

    @GetMapping("/update/{id}")
    public Object update(@PathVariable String id){
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(User::getName , "大萨达十大");
        updateWrapper.eq("id" , id);
        return userService.update(updateWrapper);
    }
}

插入

在这里插入图片描述

可以发现写的是主库 master

在这里插入图片描述

3311

在这里插入图片描述

3312
在这里插入图片描述

查询

在这里插入图片描述

可以发现读的是从库

在这里插入图片描述

分页条件查询

yml

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:com/ycz/**/xml/*Mapper.xml

配置config

package com.ycz.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description:
 * @Author: Alex
 * @Date 2022-06-29-21:58
 * @Version: V1.0
 **/
@Configuration
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

 @GetMapping("/select")
    public Object select(@RequestParam(value = "pageNo" ,required = false , defaultValue = "0")Integer pageNo ,
                         @RequestParam(value ="pageSize" ,required = false , defaultValue = "5")Integer pageSize) {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age");
        Page<User> page = new Page<>(pageNo  , pageSize);

        IPage<User> pageList = userService.page(page ,queryWrapper);

        return pageList;
    }

查询结果:

{
    "records": [
        {
            "id": "1540666225414160385",
            "name": "test1_user0_2",
            "age": 89
        },
        {
            "id": "1540665503343718401",
            "name": "test1_user0_1",
            "age": 85
        },
        {
            "id": "1540666229851734017",
            "name": "test1_user2_2",
            "age": 81
        },
        {
            "id": "1540665515347816450",
            "name": "test0_user1_1",
            "age": 78
        },
        {
            "id": "1540669670086983682",
            "name": "test0_user1_3",
            "age": 78
        }
    ],
    "total": 15,
    "size": 5,
    "current": 1,
    "orders": [],
    "optimizeCountSql": true,
    "hitCount": false,
    "countId": null,
    "maxLimit": null,
    "searchCount": true,
    "pages": 3
}

我们看看其sql语句

sql语句是这样的
slave0 ::: SELECT  id,name,age  FROM user0 ORDER BY age DESC LIMIT ? ::: [5]
slave0 ::: SELECT  id,name,age  FROM user1 ORDER BY age DESC LIMIT ? ::: [5]
slave0 ::: SELECT  id,name,age  FROM user2 ORDER BY age DESC LIMIT ? ::: [5]
slave1 ::: SELECT  id,name,age  FROM user0 ORDER BY age DESC LIMIT ? ::: [5]
slave1 ::: SELECT  id,name,age  FROM user1 ORDER BY age DESC LIMIT ? ::: [5]
slave1 ::: SELECT  id,name,age  FROM user2 ORDER BY age DESC LIMIT ? ::: [5]

sharding JDBC 默认使用limit进行分页,在不指定路由字段时,分页将会全库全表全数据捞取,然后进行排序。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: ShardingSphere是一个开源的分布式数据库中间件,它提供了分库分表读写分离、分布式事务等功能,可以帮助应用程序轻松地实现水平扩展和高可用性。其中,分库分表ShardingSphere的核心功能之一,它可以将一个大型数据库分成多个小型数据库,每个小型数据库只包含部分数据,从而提高数据库的性能和可扩展性。同时,ShardingSphere还提供了多种分片策略,可以根据不同的业务需求选择合适的分片方式。 ### 回答2: shardingsphere是一个开源的分布式数据库中间件,它支持分库分表读写分离、分布式事务等多种分布式场景,并且提供了数据库代理、全局唯一ID生成、数据加密、动态数据源等一系列功能。 其中分库分表shardingsphere的核心功能之一。当数据量增加、访问量增加时,单个数据库的存储和性能可能会受到限制。此时,将数据分散到多个数据库中,可以提高系统的扩展性和性能。分库分表是指将一个大的数据库或数据表拆分为多个小的数据库或数据表,其中每个小的数据库或数据表都包含一个部分数据。这样,可以分散数据存储和查询的压力,同时还可以提高系统的稳定性和可靠性。 shardingsphere实现分库分表的方式是基于SQL解析和路由的方式。在使用shardingsphere时,需要进行以下步骤: 1. 配置数据源和分片规则:需要指定每个数据节点的数据源和分片规则,例如分片键、分片算法等。 2. 修改应用程序:需要将应用程序中的SQL语句修改为符合shardingsphere的语法。例如,在select语句中需要包含分片键,同时需要使用shardingsphere提供的API对SQL进行解析和路由。 3. 安装shardingsphere代理:shardingsphere会作为一个代理存在,作为转发请求和处理分片的中间件。 总的来说,shardingsphere是一个强大的分布式数据库中间件,可以大大提升系统的性能和可扩展性。通过分库分表,可以将数据存储和查询的压力分散到多个数据库中,提高系统的稳定性和可靠性。虽然shardingsphere的配置和使用较为复杂,但是是值得投入和学习的。 ### 回答3: ShardingSphere是一个开源的分布式数据库中间件,支持分库分表读写分离、分布式事务等功能。其最为重要的功能便是分库分表分库分表是为了解决单库存储容量限制、查询性能瓶颈等问题而产生的技术手段。ShardingSphere的分库分表功能是将一个大的数据集按照规则分散到多个数据库实例中,从而提高数据处理效率,实现横向扩展。 在ShardingSphere中,分库分表的设计遵循的是水平分割原则,通过将数据拆分成多个较小的集合,实现分布在不同数据库实例中。具体过程如下: 1. 根据一定的规则(如按照用户ID、订单ID等),将数据集分成多个较小的集合。 2. 每个集合通过Hash算法或取模运算等方式,映射到不同的数据库实例上。 3. 应用程序访问数据时,通过ShardingSphere进行路由和负载均衡,实现对数据集的查询和操作。 ShardingSphere的分库分表具有以下优点: 1. 扩展性强:通过分散数据到多个数据库实例中,实现了系统的横向扩展,能够满足海量数据的存储需求。 2. 高可用性:多个数据库实例之间进行负载均衡,使访问请求得到良好的响应时间,并且不会因为单一数据库实例的宕机而影响整个系统的运行。 3. 性能优越:通过分散数据集,每个数据库实例的查询和更新压力降低,从而提高了查询效率和吞吐量。 总之,ShardingSphere的分库分表是一项非常实用且重要的技术,对于需要处理大数据集合的企业应用来说,具有非常大的价值。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值