使用sharding jdbc 分库分表 学习笔记

sharding jdbc 分库分表学习

1、sharding jdbc介绍

Sharding-JDBC是一个开源的Java框架,用于在关系型数据库中实现数据分片和分布式定位的功能。它通过透明地对应用程序进行改造,将数据库的表按照一定的规则分散到多个数据库实例中,从而实现数据的水平切分和分布式存储。

Sharding-JDBC提供了一种简单、易用的方式来实现数据分片。它通过拦截JDBC的数据操作请求,在底层动态路由到正确的数据库实例上执行。对于应用程序来说,使用Sharding-JDBC就像在操作普通的单个数据库一样,对分片的细节是透明的。

Sharding-JDBC支持多种数据分片策略,包括基于范围、基于哈希和基于精确值等。它还提供了事务支持、读写分离、分布式ID生成等功能,以满足不同场景下的需求。

除了数据分片功能,Sharding-JDBC还提供了分布式定位的能力。通过指定分片键的值,可以快速定位到具体的数据库实例,从而实现高效的数据访问。

总结来说,Sharding-JDBC是一个功能强大的数据分片和分布式定位框架,可以帮助应用程序轻松实现数据库的水平切分和分布式存储。它简化了分片操作的复杂性,并提供了丰富的功能和灵活的配置选项,使得开发者能够更加方便地构建可扩展的分布式数据库系统。

2、使用场景

我本次使用的场景是因为数据库压力较大,需要进行分库分表操作。

即:由原本的A库a表->B库a表

实现新旧数据库都可以查询数据,后续新的写操作都放到新库。

3、具体设计

因为我们公司对shardingJDBC做了分装,我们只需要对数据源做区分、做好规则选择及其库表新建,调整Dao依赖注入即可。

但作为学习,我简单阐述一下路由找表的过程吧:

在Sharding-JDBC中,路由找表是指根据给定的SQL语句和相关的分片规则,确定要操作的具体数据库表。下面是Sharding-JDBC进行路由找表的基本步骤:

  1. 解析SQL语句:Sharding-JDBC首先会解析输入的SQL语句,提取其中的表名、条件等信息。
  2. 路由计算:根据配置的分片规则和解析得到的信息,Sharding-JDBC进行路由计算,确定要操作的具体数据库表。路由计算可以基于多种策略,如范围分片、哈希分片或精确值分片。
    • 范围分片:根据范围分片规则,将数据按照某个字段值的大小范围拆分到不同的数据库表中。路由计算时,根据条件判断将查询的数据路由到合适的表。
    • 哈希分片:根据哈希分片规则,通过对某个字段值进行哈希运算,将数据散列到不同的数据库表中。路由计算时,根据哈希结果将查询的数据路由到相应的表。
    • 精确值分片:根据指定的字段值进行精确匹配,将数据路由到对应的数据库表中。路由计算时,根据字段值与分片规则的匹配关系确定查询的表。
  3. 路由结果返回:根据路由计算的结果,Sharding-JDBC将确定要操作的具体数据库表返回给上层调用程序。

需要注意的是,Sharding-JDBC在进行路由找表时,会根据配置的分片规则和数据源信息来决定具体的路由策略。开发者需要合理配置分片规则和数据源,并理解不同分片策略的适用场景,以确保路由找表的准确性和性能优化。

直白点说,就是shardingDao会根据你设置的分片规则,去查对应的物理表,返回真实你需要操作的表,然后对sql进行解析、组装,实现自适应的sql操作。所以我们只要关注分库分表规则是什么,然后直接使用就可以了。当然前提是你把新库新表都要创建好,整体能crud。

很多同学不太清楚这个框架怎么使用,但其实它就是替你做了一层包装,替你去区分库表,你需要做的就是告诉它你的规则是什么,通过规则去路由正确的库表,比如你要根据时间范围去分库分表,比如你要根据ID的奇偶性等等,这些规则是要你自定义的。再就是你需要对sql进行梳理,看看是否你定制的规则符合这些sql操作。

4、demo学习

当使用Sharding JDBC和Spring Boot结合时,可以通过简单的配置实现对分库分表的支持。以下是一个基本的示例:

  1. 添加依赖:在pom.xml文件中添加Sharding JDBC和Spring Boot相关的依赖。
<!-- Sharding JDBC -->
<dependency>
    <groupId>io.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>5.0.0</version>
</dependency>

<!-- Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.3</version>
</dependency>
  1. 配置数据源:在application.yaml中配置数据源信息和Sharding JDBC的相关属性。
spring:
  shardingsphere:
    datasource:
      names: ds0, ds1
      ds0:
        url: jdbc:mysql://localhost:3306/database0?useSSL=false&characterEncoding=utf8
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
      ds1:
        url: jdbc:mysql://localhost:3306/database1?useSSL=false&characterEncoding=utf8
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver

    sharding:
      tables:
        order:
          actualDataNodes: ds$->{
    
    0..1}.order_$->{
    
    0..1}
          tableStrategy:
            inline:
              shardingColumn: order_id
              algorithmExpression: order_$->{
    
    order_id % 2}
          keyGenerator:
            type: SNOWFLAKE
            column: order_id
      props:
        sql.show: true

在上述配置中,我们定义了两个数据源(ds0ds1),以及一个名为order的分片表。actualDataNodes参数定义了实际的数据节点,每个数据节点对应一个数据源和物理表。tableStrategy指定了分库分表的策略,这里使用了内联算法根据order_id进行分片。keyGenerator定义了主键生成策略,这里使用了Snowflake算法。

  1. 编写业务代码:创建相应的Service和Repository类,并在需要使用分片表的方法上添加@Transactional注解。
@Service
public class OrderService {
    
    
    @Autowired
    private OrderRepository orderRepository;

    @Transactional
    public void createOrder(Order order) {
    
    
        // 执行插入订单的操作
        orderRepository.insert(order);
    }

    public List<Order> getOrdersByUserId(Long userId) {
    
    
        // 执行根据用户ID查询订单的操作
        return orderRepository.findByUserId(userId);
    }
}

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    
    
    List<Order> findByUserId(Long userId);
}

在上述示例中,OrderService是订单的服务类,它调用OrderRepository进行数据库操作。我们在createOrder()方法上添加了@Transactional注解,以确保插入订单操作在一个事务中执行。

  1. 启动应用程序:编写Spring Boot的启动类,将应用程序启动起来。
@SpringBootApplication
public class Application {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Application.class, args);
    }
}

以上示例是一个基本的使用Sharding JDBC和Spring Boot进行分库分表的例子。请注意,上述示例仅供参考,请根据实际情况进行适配。

5、个人理解

本次只是分享一次学习心得,我本次根据shardingjdbc操作库表,因为有现成的东西,所以好多细节其实是看不到的,只是做了一些通用的规则设计调整。

在我看来,这个框架的学习成本不高,因为都是springboot项目了,使用内联方式其实可以解决很多人的需求,如果涉及复杂的分库分表规则,那么就得自定义config进行编码了。而且spring很好的继承了shardingjdbc,只需要你对sql进行条件梳理,确定规则即可。所以用起来还是很简单的。

关于规则,其实不是很好解答,因为项目不尽相同,你必须根据自己的项目情况去定制,我上面给的例子其实就是一种很简单的规则,algorithmExpression: order_KaTeX parse error: Expected '}', got 'EOF' at end of input: …Expression: "ds->{order_id % 2}.order_$->{order_id % 2}"

在集成 ShardingJDBC 后,DAO 层的代码不需要特殊处理来进行数据分片。ShardingJDBC 会根据配置的分片规则自动将数据路由到正确的数据源和表中,让你的应用程序无需关心具体的分片逻辑。

在 DAO 层,你可以像平常一样编写针对单个数据库实例的 SQL 或使用 ORM 框架(如 MyBatis、Hibernate 等)进行数据访问操作。ShardingJDBC 会在内部拦截和解析你的 SQL 语句,并根据分片规则自动将其路由到正确的数据库实例和表上。

6、总结

直白点说,就是先分析sql,看你的操作条件是什么,进而确定规则,然后在yml中配置分库分表的规则,创建新库新表,其他的均由shardingJDBC替你做了。

至于如何路由匹配物理库,如何sql调整等这些都需要无需你操心。当然了,如果你想深入了解,还是需要学习内面的源码的。比如我们公司就是把一些通用的规则进行了封装,方便大家使用,你只需要匹配规则序号,不用自己去实现规则,这样更方便了。

猜你喜欢

转载自blog.csdn.net/qq_38653981/article/details/131539991