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

相关文章

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

MySQL中优化CPU使用的详细指南

《MySQL中优化CPU使用的详细指南》优化MySQL的CPU使用可以显著提高数据库的性能和响应时间,本文为大家整理了一些优化CPU使用的方法,大家可以根据需要进行选择... 目录一、优化查询和索引1.1 优化查询语句1.2 创建和优化索引1.3 避免全表扫描二、调整mysql配置参数2.1 调整线程数2.

更改linux系统的默认Python版本方式

《更改linux系统的默认Python版本方式》通过删除原Python软链接并创建指向python3.6的新链接,可切换系统默认Python版本,需注意版本冲突、环境混乱及维护问题,建议使用pyenv... 目录更改系统的默认python版本软链接软链接的特点创建软链接的命令使用场景注意事项总结更改系统的默

Linux升级或者切换python版本实现方式

《Linux升级或者切换python版本实现方式》本文介绍在Ubuntu/Debian系统升级Python至3.11或更高版本的方法,通过查看版本列表并选择新版本进行全局修改,需注意自动与手动模式的选... 目录升级系统python版本 (适用于全局修改)对于Ubuntu/Debian系统安装后,验证Pyt

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

MySQL 升级到8.4版本的完整流程及操作方法

《MySQL升级到8.4版本的完整流程及操作方法》本文详细说明了MySQL升级至8.4的完整流程,涵盖升级前准备(备份、兼容性检查)、支持路径(原地、逻辑导出、复制)、关键变更(空间索引、保留关键字... 目录一、升级前准备 (3.1 Before You Begin)二、升级路径 (3.2 Upgrade

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java