sharding sphere 4.0.0-RC1版本 按年分表(后续优化)

2024-05-02 10:18

本文主要是介绍sharding sphere 4.0.0-RC1版本 按年分表(后续优化),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. sharding sphere 4.0.0-RC1版本 按年分表(后续优化)

1.1. 概述

关于上一篇中LogShardingAlgorithmtables,我原先是在第一次调用的时候初始化,这样做虽然能实现功能,但每次调用都会走这个if判断,虽然性能损耗不大,但我觉得这不是业务应该走的逻辑顺序,我的理想是在LogShardingAlgorithm被实例化后去自动初始化tables

现在面对的问题是LogShardingAlgorithm的实例化是在Spring初始化中间执行的,且它本身的创建不是通过Spring的@Component等注解生成,而是通过反射实例化。若在实例化刚开始,也就是构造方法执行的时候执行初始化,那时候applicationContext还没有初始化完毕,拿不到环境参数,连Datasource也还没开始初始化

1.2. 解决方法

经过改造后,代码如下,单独拎出一个初始化方法,在类对象实例化后调用

/*** @author: laoliangliang* @description: 日志分片* @create: 2020/1/2 10:19**/
@Slf4j
public class LogShardingAlgorithm implements PreciseShardingAlgorithm, RangeShardingAlgorithm<Integer> {/*** 缓存存在的表*/private List<String> tables;private final String systemLogHead = "system_log_";public void init(){tables = DBUtil.getAllSystemLogTable();}@Overridepublic String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {String target = shardingValue.getValue().toString();String year = target.substring(target.lastIndexOf("_")   1, target.lastIndexOf("_")   5);if (!tables.contains(systemLogHead   year)) {DBUtil.createLogTable(year);tables.add(year);}return shardingValue.getLogicTableName()   "_"   year;}@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Integer> shardingValue) {Collection<String> availables = new ArrayList<>();Range valueRange = shardingValue.getValueRange();for (String target : tables) {Integer shardValue = Integer.parseInt(target.substring(target.lastIndexOf("_")   1, target.lastIndexOf("_")   5));if (valueRange.hasLowerBound()) {String lowerStr = valueRange.lowerEndpoint().toString();Integer start = Integer.parseInt(lowerStr.substring(0, 4));if (start - shardValue > 0) {continue;}}if (valueRange.hasUpperBound()) {String upperStr = valueRange.upperEndpoint().toString();Integer end = Integer.parseInt(upperStr.substring(0, 4));if (end - shardValue < 0) {continue;}}availables.add(target);}return availables;}
}

其中init方法通过另一个类实例化完成后调用,难点在于如何拿到该实例化的LogShardingAlgorithm

import cn.hutool.core.util.ReflectUtil;
import com.google.common.base.Optional;
import com.onegene.platform.system.log.LogShardingAlgorithm;
import org.apache.shardingsphere.core.rule.ShardingRule;
import org.apache.shardingsphere.core.rule.TableRule;
import org.apache.shardingsphere.core.strategy.route.ShardingStrategy;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.ShardingContext;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.sql.DataSource;
/*** @author: laoliangliang* @description:* @create: 2020/1/18 8:29**/
@Component
public class StartupConfig {@Autowiredprivate DataSource dataSource;@PostConstructpublic void init() {this.loadLogInit();}private void loadLogInit() {if (dataSource instanceof ShardingDataSource) {ShardingDataSource sds = (ShardingDataSource) dataSource;ShardingContext shardingContext = sds.getShardingContext();ShardingRule shardingRule = shardingContext.getShardingRule();Optional<TableRule> systemLog = shardingRule.findTableRule("system_log");TableRule tableRule = systemLog.orNull();if (tableRule != null) {ShardingStrategy tableShardingStrategy = tableRule.getTableShardingStrategy();LogShardingAlgorithm preciseShardingAlgorithm = (LogShardingAlgorithm) ReflectUtil.getFieldValue(tableShardingStrategy, "preciseShardingAlgorithm");LogShardingAlgorithm rangeShardingAlgorithm = (LogShardingAlgorithm) ReflectUtil.getFieldValue(tableShardingStrategy, "rangeShardingAlgorithm");preciseShardingAlgorithm.init();rangeShardingAlgorithm.init();}}}
}

1.3. 总结

通过查看源码可以知道,它最后把LogShardingAlgorithm实例化的对象放入了ShardingDataSource,那我们就要从里面把它取出来,若它正常没提供get方法,那我们就用反射硬把它取出来

通过上述代码可以看出,范围分片和精确分片需要实例化两个类,我想是否可以合到一个类,网上也找了一下,发现有的版本使用ComplexKeysShardingAlgorithm算法是可以同时实现范围和精确分片查询的,但经过我实际测试,现在的4.0.0版本不行,原因在于以下代码,此为复杂分片源码

public final class ComplexShardingStrategy implements ShardingStrategy {@Getterprivate final Collection<String> shardingColumns;private final ComplexKeysShardingAlgorithm shardingAlgorithm;public ComplexShardingStrategy(final ComplexShardingStrategyConfiguration complexShardingStrategyConfig) {Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingColumns(), "Sharding columns cannot be null.");Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingAlgorithm(), "Sharding algorithm cannot be null.");shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);shardingColumns.addAll(Splitter.on(",").trimResults().splitToList(complexShardingStrategyConfig.getShardingColumns()));shardingAlgorithm = complexShardingStrategyConfig.getShardingAlgorithm();}@SuppressWarnings("unchecked")@Overridepublic Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues) {Map<String, Collection<Comparable<?>>> columnShardingValues = new HashMap<>(shardingValues.size(), 1);String logicTableName = "";for (RouteValue each : shardingValues) {// 重点这里他把each的值强行转化成了ListRouteValue而范围查询对应的为BetweenRouteValue,所以在源码级别就被卡死了,除非重写策略,否则这个已经不能像以前那样用了columnShardingValues.put(each.getColumnName(), ((ListRouteValue) each).getValues());logicTableName = each.getTableName();}Collection<String> shardingResult = shardingAlgorithm.doSharding(availableTargetNames, new ComplexKeysShardingValue(logicTableName, columnShardingValues));Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);result.addAll(shardingResult);return result;}
}

老梁讲Java

欢迎关注公众号,回复“教学视频”一起学习进步

这篇关于sharding sphere 4.0.0-RC1版本 按年分表(后续优化)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954023

相关文章

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

MyCat分库分表的项目实践

《MyCat分库分表的项目实践》分库分表解决大数据量和高并发性能瓶颈,MyCat作为中间件支持分片、读写分离与事务处理,本文就来介绍一下MyCat分库分表的实践,感兴趣的可以了解一下... 目录一、为什么要分库分表?二、分库分表的常见方案三、MyCat简介四、MyCat分库分表深度解析1. 架构原理2. 分

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

MySQL分库分表的实践示例

《MySQL分库分表的实践示例》MySQL分库分表适用于数据量大或并发压力高的场景,核心技术包括水平/垂直分片和分库,需应对分布式事务、跨库查询等挑战,通过中间件和解决方案实现,最佳实践为合理策略、备... 目录一、分库分表的触发条件1.1 数据量阈值1.2 并发压力二、分库分表的核心技术模块2.1 水平分

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变