spring boot 八、 sharding-jdbc 分库分表 按月分表
在项目resources目录下新建com.jianmu.config.sharding.DateShardingAlgorithm 文件
新增yaml配置 数据源
spring:shardingsphere:props:sql:#是否在日志中打印 SQLshow: true#打印简单风格的 SQLsimple: truedatasource:names: pingxuanlogpingxuanlog:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_jianmu_pingxuan_log?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8username: rootpassword: root#最大连接池数量max-active: 10#最小连接池数量min-idle: 5#初始化时建立物理连接的个数initial-size: 5#获取连接时最大等待时间,单位毫秒max-wait: 3000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒time-between-eviction-runs-millis: 60000#配置一个连接在池中最小生存的时间,单位是毫秒min-evictable-idle-time-millis: 100000#用来检测连接是否有效的sql,要求是一个查询语句validation-query: SELECT 1 FROM DUAL#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-while-idle: true
新增yaml配置 sharding 分表规则
spring:shardingsphere:sharding:tables:t_act_vt_log:#配置数据节点,这里是按月分表,时间范围设置在202201 ~ 210012actual-data-nodes: pingxuanlog.t_act_vt_log_$->{202201..203012}table-strategy:standard:#使用标准分片策略,配置分片字段sharding-column: add_time# 精确匹配规则(自定义类)precise-algorithm-class-name: com.jianmu.config.sharding.DateShardingAlgorithm# 范围匹配规则(自定义类)range-algorithm-class-name: com.jianmu.config.sharding.DateShardingAlgorithmt_act_access_log:#配置数据节点,这里是按月分表,时间范围设置在202201 ~ 210012actual-data-nodes: pingxuanlog.t_act_access_log_$->{202201..203012}table-strategy:standard:#使用标准分片策略,配置分片字段sharding-column: add_time# 精确匹配规则(自定义类)precise-algorithm-class-name: com.jianmu.config.sharding.DateShardingAlgorithm# 范围匹配规则(自定义类)range-algorithm-class-name: com.jianmu.config.sharding.DateShardingAlgorithm
DataSourceConfiguration
package com.jianmu.config.sharding;import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;
import java.util.Map;/*** 动态数据源配置:* <p>* 使用{@link com.baomidou.dynamic.datasource.annotation.DS}注解,切换数据源** <code>@DS(DataSourceConfiguration.SHARDING_DATA_SOURCE_NAME)</code>**/
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfiguration {/*** 分表数据源名称*/public static final String SHARDING_DATA_SOURCE_NAME = "sharding";/*** 动态数据源配置项*/private final DynamicDataSourceProperties dynamicDataSourceProperties;private final ShardingDataSource shardingDataSource;@Autowiredpublic DataSourceConfiguration(DynamicDataSourceProperties dynamicDataSourceProperties, @Lazy ShardingDataSource shardingDataSource) {this.dynamicDataSourceProperties = dynamicDataSourceProperties;this.shardingDataSource = shardingDataSource;}/*** 将shardingDataSource放到了多数据源(dataSourceMap)中**/@Beanpublic DynamicDataSourceProvider dynamicDataSourceProvider() {Map<String, DataSourceProperty> datasourceMap = dynamicDataSourceProperties.getDatasource();return new AbstractDataSourceProvider() {@Overridepublic Map<String, DataSource> loadDataSources() {Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);// 将 sharding jdbc 管理的数据源也交给动态数据源管理dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);return dataSourceMap;}};}/*** 将动态数据源设置为首选的* 当spring存在多个数据源时, 自动注入的是首选的对象* 设置为主要的数据源之后,就可以支持sharding jdbc原生的配置方式*/@Primary@Beanpublic DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();dataSource.setPrimary(dynamicDataSourceProperties.getPrimary());dataSource.setStrict(dynamicDataSourceProperties.getStrict());dataSource.setStrategy(dynamicDataSourceProperties.getStrategy());dataSource.setProvider(dynamicDataSourceProvider);dataSource.setP6spy(dynamicDataSourceProperties.getP6spy());dataSource.setSeata(dynamicDataSourceProperties.getSeata());return dataSource;}
}
package com.jianmu.config.sharding;import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;import javax.sql.DataSource;
import java.util.Map;/*** @author kong*/
@Configuration
public class DataSourceHealthConfig extends DataSourceHealthContributorAutoConfiguration {@Value("${spring.datasource.dbcp2.validation-query:select 1}")private String defaultQuery;public DataSourceHealthConfig(Map<String, DataSource> dataSources, ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders) {super(dataSources, metadataProviders);}@Overrideprotected AbstractHealthIndicator createIndicator(DataSource source) {DataSourceHealthIndicator indicator = (DataSourceHealthIndicator) super.createIndicator(source);if (!StringUtils.hasText(indicator.getQuery())) {indicator.setQuery(defaultQuery);}return indicator;}
}
package com.jianmu.config.sharding;import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.jianmu.tools.ApplicationContextTools;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;/**sharding 分库分表策略配置:按照年月 如t_act_vt_log_202208**/
@Slf4j
public class DateShardingAlgorithm implements PreciseShardingAlgorithm<LocalDateTime>, RangeShardingAlgorithm<LocalDateTime> {private final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMM");@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<LocalDateTime> psv) {final String table = psv.getLogicTableName();final String prefix = table + "_";if (log.isDebugEnabled()) {log.debug("分表更新");}TableService tableService = (TableService) ApplicationContextTools.getBean(TableService.class);//添加日期final String logicTable = prefix + psv.getValue().format(this.format);boolean exist = tableService.exist(logicTable);if (log.isDebugEnabled()) {log.debug("更新: {} 存在:{}", logicTable, exist);}//匹配到了if (exist) {return logicTable;}//未匹配到if (log.isDebugEnabled()) {log.debug("sharding 未匹配到表,需要创建");}//创建这张表tableService.copy(logicTable, table);return logicTable;}/*** 范围匹配*/@SneakyThrows@Overridepublic Collection<String> doSharding(Collection<String> collection, RangeShardingValue<LocalDateTime> rsv) {final String table = rsv.getLogicTableName();final String prefix = table + "_";if (log.isDebugEnabled()) {log.debug("分表查询 表:{}", table);}TableService tableService = (TableService) ApplicationContextTools.getBean(TableService.class);List<String> tables = tableService.tables();Range<LocalDateTime> range = rsv.getValueRange();//计算出时间范围内的所有日期final int upper = range.hasUpperBound() ? Integer.parseInt(range.upperEndpoint().toLocalDate().format(this.format)) : 0;final int lower = range.hasLowerBound() ? Integer.parseInt(range.lowerEndpoint().toLocalDate().format(this.format)) : 0;List<String> validTables = this.validTables(prefix, tables, upper, lower);if (log.isDebugEnabled()) {log.debug("查询表:{}", JSON.toJSONString(validTables));}if (CollectionUtils.isEmpty(validTables)) {if (log.isDebugEnabled()) {log.debug("查询表不存在 改查原始表");}return Lists.newArrayList(table);}return validTables;}private List<String> validTables(String prefix, List<String> tables, int upper, int lower) {if (log.isDebugEnabled()) {log.debug("上界:{},下界:{}", upper, lower);}return tables.parallelStream().filter(i -> {if (i.contains(prefix)) {final String date = i.replace(prefix, "");if (date.matches("[0-9]*")) {final int mouth = Integer.parseInt(date);if (upper > 0 && lower > 0) {return mouth <= upper && mouth >= lower;} else {if (upper > 0) {return mouth <= upper;}if (lower > 0) {return mouth >= lower;}}}}return false;}).collect(Collectors.toList());}}
package com.jianmu.config.sharding;public class ShardingConstant {public static final String ORIGINAL_DATABASE = "db_jianmu_pingxuan_log";
}
package com.jianmu.config.sharding;import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ExecutionException;public interface TableService {/*** 返回所有表*/List<String> tables() throws ExecutionException, SQLException;boolean exist(String table);/*** 精确删除表*/boolean drop(String table);/*** 旧表复制为新表*/boolean copy(String newTable, String usedTable);
}
package com.jianmu.config.sharding;import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.jianmu.constant.SysRedisConstant;
import com.jianmu.mapper.system.TableMapper;
import com.jianmu.tools.JdbcTools;
import com.jianmu.tools.log.LogTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;import java.sql.SQLException;
import java.util.List;@Slf4j
@Service
@DS("sharding")
public class TableServiceImpl implements TableService {private final TableMapper tableMapper;private final RedisTemplate<String, Object> redis;private final ValueOperations<String, Object> redisValue;private final DynamicRoutingDataSource dynamicRoutingDataSource;@Autowiredpublic TableServiceImpl(TableMapper tableMapper, RedisTemplate<String, Object> redis, DynamicRoutingDataSource dynamicRoutingDataSource) {this.tableMapper = tableMapper;this.redis = redis;this.redisValue = redis.opsForValue();this.dynamicRoutingDataSource = dynamicRoutingDataSource;}@Overridepublic List<String> tables() throws SQLException {List<String> tables = (List<String>) this.redisValue.get(SysRedisConstant.TABLES);if (tables == null) {List<String> list = JdbcTools.tables(this.dynamicRoutingDataSource.getDataSource(DataSourceConfiguration.SHARDING_DATA_SOURCE_NAME).getConnection(), ShardingConstant.ORIGINAL_DATABASE);//每24小时更新一次this.redisValue.set(SysRedisConstant.TABLES, list, 86400);return list;}return tables;}@Overridepublic boolean exist(String table) {try {Integer exist = this.tableMapper.exist(table);if (log.isDebugEnabled()) {log.debug("表:{} 存在:{}", table, exist);}return true;} catch (Exception e) {LogTools.err(e);return false;}}@Overridepublic boolean drop(String table) {boolean flag = this.tableMapper.drop(table) >= 0;if (flag) {this.delCache();}return flag;}@Overridepublic boolean copy(String newTable, String usedTable) {boolean flag = this.tableMapper.copy(newTable, usedTable) >= 0;if (flag) {this.delCache();}return flag;}private void delCache() {this.redis.delete(SysRedisConstant.TABLES);}}
t_act_vt_log 为每次自动生成的基础表 需要在这个表建好索引等
相关文章:

spring boot 八、 sharding-jdbc 分库分表 按月分表
在项目resources目录下新建com.jianmu.config.sharding.DateShardingAlgorithm 文件 新增yaml配置 数据源 spring:shardingsphere:props:sql:#是否在日志中打印 SQLshow: true#打印简单风格的 SQLsimple: truedatasource:names: pingxuanlogpingxuanlog:type: com.alibaba.dru…...
Java 8 中Stream流的一些用法
public class Djmxlist {private String dxmc;private Integer sl;public String getDxmc() {return dxmc;}public void setDxmc(String dxmc) {this.dxmc dxmc;}public Integer getSl() {return sl;}public void setSl(Integer sl) {this.sl sl;} }插入一下数据 List<Djm…...

Elasticsearch 8.10 中引入查询规则 - query rules
作者:Kathleen DeRusso 我们很高兴宣布 Elasticsearch 8.10 中的查询规则! 查询规则(query rules)允许你根据正在搜索的查询词或根据作为搜索查询的一部分提供的上下文信息来更改查询。 什么是查询规则? 查询规则&…...

Windows PostgreSql 创建多个数据库目录
1 使用默认用户Administrator 1.1初始化数据库目录 E:\Program Files\PostgreSQL\13> .\bin\initdb -D G:\DATA\pgsql\data3 -W -A md5 1.2连接数据库 这时User为Administrator,密码就是你刚才设置的,我设置的为123456,方便测试。 2 添加…...

Java AOP Framework概述
Java AOP Framework概述 1. AspectJ1.1 使用AspectJ进行切面编程 2. Spring AOP2.1 使用Spring AOP进行切面编程2.2 如何决定使用哪种动态代理2.3 如何通过配置指定代理方式2.4 Spring AOP和AspectJ的关系 3. Spring Boot AOP4. 扩展4.1 AspectJ织入方式详解 参考 Java常用的AO…...

220V转12V芯片-交流45v-265v输入,固定12v输出峰值电流600MA
标题:220V转12V芯片,实现宽电压输入和固定12V输出 摘要:本文介绍了一款具备宽电压输入范围(45V-265V)和固定12V输出的220V转12V芯片。该芯片内置了650V高压MOS管,并通过CS电阻调节输出电流,最大…...

TOGAF架构开发方法—初步阶段
本章描述了满足新企业体系结构业务指令所需的准备和启动活动,包括组织特定体系结构框架的定义和原则的定义。 一、目标 初步阶段的目标是: 确定组织所需的体系结构功能: 审查进行企业架构的组织背景确定受体系结构功能影响的企业组织的元素并确定其范围确定与架构功能相交的…...

软件定制APP开发步骤分析|小程序
软件定制APP开发步骤分析|小程序 软件定制开发步骤: 1.需求分析: 这是软件定制开发的第一步,也是最关键的一步。在这个阶段,软件开发团队需要与客户进行沟通,了解客户的具体需求和期望。通过讨论和交流,确…...

postman接口传参案例
目录 案例1: 接口A 接口B 案例2: //断言 案例1: 接口A 根据返回值需要从返回值中提取userid值,在Tests标签栏下编写脚本 //获取返回的响应值,并转化为json格式 var jsonData pm.response.json(); // 获取返回…...

【2023华为杯A题】WLAN网络信道接入机制建模(代码、思路.....)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

CFCA企业版通配符SSL证书
CFCA是中国CFCA企业版通配符SSL证书金融认证中心的缩写,即China Financial Certification Authority。它是一家经过中国人民银行和国家信息安全机构批准成立的国家级权威安全认证机构,也是国际CA浏览器联盟组织(CA/Browser Forum)…...

基于ASCON的AEAD
1. 引言 前序博客: ASCON:以“慢而稳”赢得NIST轻量级加密算法标准密码学中的AEAD(authenticated encryption with associated data) 对称密钥加密过去数年来已发生改变,具体为: 当今主要使用stream ciphers,因其比…...
汇编宏伪指令介绍
1、汇编宏伪指令介绍 .macro macname macargs .endm(1)“.macro"和”.endm"表示宏定义的开始和结束; (2) “.macro"后面接着宏定义的名字,然后是参数,参数后面的宏定义的实现…...

优化系统报错提示信息,提高人机交互(一)
1、常规报错及处理 package com.example.demo.controller;import com.example.demo.service.IDemoService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.w…...

FPGA纯verilog实现8路视频拼接显示,提供工程源码和技术支持
目录 1、前言版本更新说明免责声明 2、我已有的FPGA视频拼接叠加融合方案3、设计思路框架视频源选择OV5640摄像头配置及采集静态彩条视频拼接算法图像缓存视频输出 4、vivado工程详解5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他注意事项 6、上板调试验证并演示…...

spring boot项目一次性能测试的总结
满足标准:并发大于等于100 ,平均响应时间小于等于3秒 项目在压测过程中并发数只有50,在并发数100的情况下有很多请求链接是失败的 我们该如何入手去处理这些问题并提高并发数呢? 1、首先从压测结果入手,对不满足标准…...

10分钟设置免费海外远程桌面
前言 本教程将向您介绍如何使用 Amazon Lightsail 服务的免费套餐轻松搭建属于您的远程桌面。依托于 Amazon 全球可用区,您可以在世界各地搭建符合您配置需求的远程桌面。 本教程需要先拥有亚马逊云科技海外账户。现在注册亚马逊云科技账户可以享受12个月免费套餐…...

基于复旦微的FMQL45T900全国产化ARM核心模块(100%国产化)
TES745D是一款基于上海复旦微电子FMQL45T900的全国产化ARM核心板。该核心板将复旦微的FMQL45T900(与XILINX的XC7Z045-2FFG900I兼容)的最小系统集成在了一个87*117mm的核心板上,可以作为一个核心模块,进行功能性扩展,能…...

2023.9.11 关于传输层协议 UDP和TCP 详解
目录 UDP协议 TCP协议 TCP十大核心机制 确认应答 超时重传 连接管理(三次握手 四次挥手) 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 面向字节流 粘包问题 TCP 中的异常处理 经典面试题 对比 TCP 和 UDP 如何使用 UDP 实现可靠传…...

thinkphp8路由
thinkphp8已出来有好一段时间了。这些天闲来无事,研究了下tp8的路由。默认情况下,tp8的路由是在route\app.php的文件里。但在实际工作中,我们并不会这样子去写路由。因为这样不好管理。更多的,是通过应用级别去管理路由。假如项目…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...