Sharding-JDBC分库分表-自动配置与分片规则加载原理-3

这篇具有很好参考价值的文章主要介绍了Sharding-JDBC分库分表-自动配置与分片规则加载原理-3。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Sharding JDBC自动配置的原理

与所有starter一样,shardingsphere-jdbc-core-spring-boot-starter也是通过SPI自动配置的原理实现分库分表配置加载,spring.factories文件中的自动配置类shardingsphere-jdbc-core-spring-boot-starter功不可没,他主要是自动创建了模式bean、事务类型bean和数据源bean,配置加载的过程可以归纳如下:

其中,创建数据源bean时会根据不同的模式创建不同的bean,本地模式直接从配置文件中加载,配置中心模式就从配置中心加载。ShardingSphereAutoConfiguration的实现如下:

@Configuration
@ComponentScan("org.apache.shardingsphere.spring.boot.converter")
@EnableConfigurationProperties(SpringBootPropertiesConfiguration.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@RequiredArgsConstructor
public class ShardingSphereAutoConfiguration implements EnvironmentAware {
    
    private String databaseName;
    
    private final SpringBootPropertiesConfiguration props;
    
    private final Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
    
    /**
     * 模式配置
     *
     * @return mode configuration
     */
    @Bean
    public ModeConfiguration modeConfiguration() {
        return null == props.getMode() ? null : new YamlModeConfigurationSwapper().swapToObject(props.getMode());
    }
    
    /**
     * 单机模式:从本地配置中加载DataSource
     *
     * @param rules rules configuration
     * @param modeConfig mode configuration
     * @return data source bean
     * @throws SQLException SQL exception
     */
    @Bean
    @Conditional(LocalRulesCondition.class)
    @Autowired(required = false)
    public DataSource shardingSphereDataSource(final ObjectProvider<List<RuleConfiguration>> rules, final ObjectProvider<ModeConfiguration> modeConfig) throws SQLException {
        Collection<RuleConfiguration> ruleConfigs = Optional.ofNullable(rules.getIfAvailable()).orElseGet(Collections::emptyList);
        return ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig.getIfAvailable(), dataSourceMap, ruleConfigs, props.getProps());
    }
    
    /**
     * 集群模式:从配置中心中加载DataSource
     *
     * @param modeConfig mode configuration
     * @return data source bean
     * @throws SQLException SQL exception
     */
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource dataSource(final ModeConfiguration modeConfig) throws SQLException {
        return !dataSourceMap.isEmpty() ? ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig, dataSourceMap, Collections.emptyList(), props.getProps())
                : ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig);
    }
    
    /**
     * 事务类型扫描bean
     *
     * @return transaction type scanner
     */
    @Bean
    public TransactionTypeScanner transactionTypeScanner() {
        return new TransactionTypeScanner();
    }
    
    @Override
    public final void setEnvironment(final Environment environment) {
        dataSourceMap.putAll(DataSourceMapSetter.getDataSourceMap(environment));
        databaseName = DatabaseNameSetter.getDatabaseName(environment);
    }
}

下面以单机模式出发点,理一下加载的过程。

@Bean
@Conditional(LocalRulesCondition.class)
@Autowired(required = false)
public DataSource shardingSphereDataSource(final ObjectProvider<List<RuleConfiguration>> rules, final ObjectProvider<ModeConfiguration> modeConfig) throws SQLException {
    Collection<RuleConfiguration> ruleConfigs = Optional.ofNullable(rules.getIfAvailable()).orElseGet(Collections::emptyList);
    // 通过ShardingSphereDataSourceFactory工厂创建数据源
    return ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig.getIfAvailable(), dataSourceMap, ruleConfigs, props.getProps());
}

通过对源码的跟踪,可以发现,ShardingSphereDataSourceFactory.createDataSource创建数据源经历了如下的过程

分片规则加载原理

分片规则、审计规则、key生成规则都是通过SPI的方式加载,自动配置类ShardingSphereAutoConfiguration中创建ShardingSphereDataSource的时候,会加载配置的分片规则,创建核心配置类ShardingRule,在ShardingRule的创建中会通过SPI的方式加载分片规则。加载的过程如下:

SPI核心实现类ShardingSphereServiceLoader中会将SPI接口进行Map缓存管理,需要时直接获取。如果Map中不存在,就通过反射的方式新建服务实例,具体实现源码如下:文章来源地址https://www.toymoban.com/news/detail-693990.html

public final class ShardingSphereServiceLoader {
    
    // 缓存service实例,
    // 缓存的Key,如:
    //  org.apache.shardingsphere.sharding.spi.ShardingAlgorithm
    //  org.apache.shardingsphere.sharding.spi.KeyGenerateAlgorithm
    //  org.apache.shardingsphere.transaction.spi.ShardingSphereTransactionManager
    private static final Map<Class<?>, Collection<Object>> SERVICES = new ConcurrentHashMap<>();
    
    /**
     * 注册服务实例
     *
     * @param 服务接口
     */
    public static void register(final Class<?> serviceInterface) {
        if (!SERVICES.containsKey(serviceInterface)) {
            SERVICES.put(serviceInterface, load(serviceInterface));
        }
    }
    
    private static <T> Collection<Object> load(final Class<T> serviceInterface) {
        Collection<Object> result = new LinkedList<>();
        for (T each : ServiceLoader.load(serviceInterface)) {
            result.add(each);
        }
        return result;
    }
    
    /**
     * 获取服务实例
     * 
     * @param 服务接口
     * @param <T> 服务类型
     * @return 服务实例
     */
    public static <T> Collection<T> getServiceInstances(final Class<T> serviceInterface) {
        return null == serviceInterface.getAnnotation(SingletonSPI.class) ? createNewServiceInstances(serviceInterface) : getSingletonServiceInstances(serviceInterface);
    }
    
    @SneakyThrows(ReflectiveOperationException.class)
    @SuppressWarnings("unchecked")
    private static <T> Collection<T> createNewServiceInstances(final Class<T> serviceInterface) {
        if (!SERVICES.containsKey(serviceInterface)) {
            return Collections.emptyList();
        }
        Collection<Object> services = SERVICES.get(serviceInterface);
        if (services.isEmpty()) {
            return Collections.emptyList();
        }
        Collection<T> result = new LinkedList<>();
        for (Object each : services) {
            // 通过反射新建实例
            result.add((T) each.getClass().getDeclaredConstructor().newInstance());
        }
        return result;
    }
    
    @SuppressWarnings("unchecked")
    private static <T> Collection<T> getSingletonServiceInstances(final Class<T> serviceInterface) {
        return (Collection<T>) SERVICES.getOrDefault(serviceInterface, Collections.emptyList());
    }
}

到了这里,关于Sharding-JDBC分库分表-自动配置与分片规则加载原理-3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一、Sharding-JDBC系列01:整合SpringBoot实现分库分表,读写分离

    目录 一、概述 二、案例演示-水平分表 (1)、创建springboot工程 (2)、创建数据库和数据表 (3)、application.yaml配置分片规则   (4)、测试数据插入、查询操作 4.1、插入-控制台SQL日志  4.2、查询-控制台SQL日志  三、案例演示-水平分库 (1)、创建数据库和数据表  (2)、application.yaml配置

    2024年02月02日
    浏览(33)
  • Mybatis-Plus集成Sharding-JDBC与Flyway实现多租户分库分表

    公司产品部收到了一些重要客户的需求,他们希望能够依赖独立的数据库存储来支持他们的业务数据。与此同时,仍有许多中小客户,可以继续使用公共库以满足其需求。技术实现方面,此前持久层框架使用的Mybatis-plus,部分业务场景使用到了Sharding-JDBC用于分表,另外,我们

    2024年02月05日
    浏览(25)
  • Sharding-JDBC分库连接数优化

    一、背景 配运平台组的快递订单履约中心(cp-eofc)及物流平台履约中心(jdl-uep-ofc)系统都使用了ShardingSphere生态的sharding-jdbc作为分库分表中间件, 整个集群采用只分库不分表的设计,共16个MYSQL实例,每个实例有32个库,集群共512个库. 当每增加一台客户端主机,一个MYSQl实例最少要增加

    2024年02月14日
    浏览(26)
  • Sharding-JDBC之PreciseShardingAlgorithm(精确分片算法)

      在我之前的文章里,数据的分库分表都是基于行表达式的方式来实现的,看起来也蛮好用,也挺简单的,但是有时会有些复杂的规则,可能使用行表达式策略会很复杂或者实现不了,我们就讲另外一种分片策略,精确分片算法,通常用来处理=或者in条件的情况比较多。

    2024年02月11日
    浏览(36)
  • Sharding-JDBC(十)如何解决根据ID更新时扫描全部分表

    我们在使用 ShardingJDBC 作为分片工具的时候,会在配置中指定分片键,例如根据 create_time 创建时间来按月分片是比较常用的操作。当分片表中需要 根据主键 ID 来进行更新的时候 ,由于不确定数据的 create_time 具体是多少,ShardingJDBC 就会在选择使用分片表的时候,就会默认选

    2024年02月07日
    浏览(35)
  • SpringBoot+Sharding-jdbc+mybatis-plus实现水平分表

    这块我就不演示了

    2024年02月12日
    浏览(23)
  • Sharding JDBC 分库分表(一致性Hash + 虚拟节点)

    一、背景 传统的将数据集中存储至单一数据节点的解决方案,在性能、可用性和运维成本这三方面已经难于满足互联网的海量数据场景。 从 性能 方面来说,由于关系型数据库大多采用B+树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁盘访问的IO次数

    2024年02月10日
    浏览(34)
  • Sharding-JDBC 自定义一致性哈希算法 + 虚拟节点 实现数据库分片策略

    分片操作是分片键 + 分片算法,也就是分片策略。目前Sharding-JDBC 支持多种分片策略: 标准分片策略 对应StandardShardingStrategy。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。 复合分片策略 对应ComplexShardingStrategy。复合分片策略。提供对SQL语句中的=, IN和BETWEEN AND的分片操作

    2024年02月02日
    浏览(41)
  • sharding-jdbc多数据源配置

    通过sharding-jdbc做分表这里就不多做介绍了,需要的可以看上一片文章 当项目中配置了多数据源,并且其中一个数据源需要使用sharding-jdbc分表时,配置如下 导入shardingjdbc依赖 这里使用的是4.0.1的配置,和上篇的3.1.0差别不大,详细配置大伙可以上官网查阅。 多数据源配置类

    2024年02月14日
    浏览(39)
  • Sharding-JDBC(六)5.1.0版本,实现按月分表、自动建表、自动刷新节点

    官网地址: https://shardingsphere.apache.org/ GitHub: https://github.com/apache/shardingsphere 官方示例: https://github.com/apache/shardingsphere/tree/master/examples 中文社区: https://community.sphere-ex.com/ 5.1.0 官方文档: https://shardingsphere.apache.org/document/5.1.0/cn/overview/ 背景: 项目用户数据库表量太大,对

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包