spring boot中动态增加数据源并且通过sharding-jdbc做分库分表查询

2023-10-27

最近项目中需要通过数仓对接数据出去,需要手动写一些查询,需要支持分库分表的场景,所以就选择了
google guava 做内存缓存,通过redis做持久化缓存,通过sharding-jdbc实现跨表查询
一下贴的是几个主要的类:

1.数据库信息缓存

package com.tudou.potato.datagaea.apps.cache;

import com.alibaba.fastjson.JSONObject;
import com.tudou.potato.datagaea.core.wh.http.resp.RdsLinkDetailResp;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @author: ge.li
 * @create: 2020-05-22 09:42
 **/
@Component
public class DataSourceCache {

    private static final String DATAGAEA_APPS_RDS_LINK = "datagaea_apps_rdslink:";

    @Autowired
    private RedisTemplate redisTemplate;

    public RdsLinkDetailResp getRDSLinkInfo(String code) {
        try {
            String redisKey = DATAGAEA_APPS_RDS_LINK + code;
            String jsonStr = redisTemplate.opsForValue().get(redisKey).toString();
            return JSONObject.parseObject(jsonStr, RdsLinkDetailResp.class);
        } catch (Exception ex) {
            return null;
        }
    }

    public void setRDSLinkInfo(RdsLinkDetailResp data) {
        String redisKey = DATAGAEA_APPS_RDS_LINK + data.getCode();
        redisTemplate.opsForValue().set(redisKey, JSONObject.toJSONString(data));
    }
}

缓存

package com.tudou.potato.datagaea.apps.cache;

import com.alibaba.druid.pool.DruidDataSource;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author: ge.li
 * @create: 2020-05-19 09:56
 **/
public class DynamicDataSource extends AbstractRoutingDataSource {

   public final static Cache<String, DruidDataSource> cache = CacheBuilder.newBuilder()
        //设置cache的初始大小为10,要合理设置该值
        .initialCapacity(10)
        //设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作
        .concurrencyLevel(5)
        //设置cache中的数据在写入之后的存活时间为10 * 60秒
        .expireAfterWrite(10 * 60, TimeUnit.SECONDS)
        //构建cache实例
        .build();

    @Override
    protected String determineCurrentLookupKey() {
        return null;
    }

    public static void setDataSource(String dataSourceName, DruidDataSource dataSource) {
        DynamicDataSource.cache.put(dataSourceName, dataSource);
    }

    public static DruidDataSource getDataSource(String dataSourceName) {
        return DynamicDataSource.cache.getIfPresent(dataSourceName);
    }

    public static void clear() {
        DynamicDataSource.cache.cleanUp();
    }

    public static DruidDataSource createDataSource(String url, String userName, String Password) {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(Password);
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(30);
        return druidDataSource;
    }
}

sharding-jdbc 配置

package com.tudou.potato.datagaea.apps.cache;

import com.alibaba.druid.pool.DruidDataSource;

import com.tudou.potato.api.bean.result.APIResponse;
import com.tudou.potato.api.message.BizCommMessage;
import com.tudou.potato.common.pojo.principal.PrincipalInfoContext;
import com.tudou.potato.datagaea.apps.tls.base.OnlineQueryResult;
import com.tudou.potato.datagaea.apps.tls.repo.impl.RDBConnectionService;
import com.tudou.potato.datagaea.core.wh.http.resp.RdsLinkDetailResp;
import com.tudou.potato.datagaea.core.wh.remote.RdsLinkRemote;
import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.stereotype.Component;

/**
 * @author: ge.li
 * @create: 2020-05-20 10:33
 **/
@Component
public class SharedDataSource {

    @Resource
    private RdsLinkRemote rdsLinkRemote;
    @Resource
    private RDBConnectionService rDBConnectionService;
    @Resource
    private DataSourceCache dataSourceCache;

    public RdsLinkDetailResp createDataSource(String code) {
        RdsLinkDetailResp rdsinfo = null;
        DruidDataSource data =  DynamicDataSource.getDataSource(code);
        try
        {
            //尝试链接
            rdsinfo = dataSourceCache.getRDSLinkInfo(code);
            Connection conn = data.getConnection();
            conn.close();

        }catch(Exception ex)
        {
            if (null == rdsinfo) {
                APIResponse<RdsLinkDetailResp> rdsinfoResp = rdsLinkRemote
                    .detailByCode(code, PrincipalInfoContext.getAuthorization(),
                        PrincipalInfoContext.getReqId());
                if (BizCommMessage.OK != rdsinfoResp.getCode()) {
                    return null;
                }
                dataSourceCache.setRDSLinkInfo(rdsinfoResp.getData());
                rdsinfo = dataSourceCache.getRDSLinkInfo(code);
            }
            DynamicDataSource.setDataSource(code, DynamicDataSource
                .createDataSource(rdsinfo.getJdbcUrl(),
                    rdsinfo.getUsername(), rdsinfo.getPassword()));
        }
        return rdsinfo;
    }

    public OnlineQueryResult sharedDataSourceSelectSQL(List<String> rdsCodes, String tableName,
        List<String> areaCodes, String sqlStr) throws Exception {
        OnlineQueryResult resultData = null;
        List<String> dbNames = new ArrayList();
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        for (String code : rdsCodes) {
            RdsLinkDetailResp rdsinfo = createDataSource(code);
            DruidDataSource data = DynamicDataSource.getDataSource(code);
            dataSourceMap.put(rdsinfo.getRdsDbName(), data);
            dbNames.add(rdsinfo.getRdsDbName());
        }
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        String tables = "";
        for (String dbName : dbNames) {
            for (String areeCode : areaCodes) {
                tables += String
                    .format("%s.%s_%s,", dbName, tableName, areeCode);
            }
        }
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
        // 期望的基础表名
        orderTableRuleConfig.setLogicTable(tableName);
        orderTableRuleConfig.setActualDataNodes(tables);
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);
        DataSource dataSource = ShardingDataSourceFactory
            .createDataSource(dataSourceMap, shardingRuleConfig, new HashMap<>(),
                new Properties());
        Connection conn = dataSource.getConnection();
        resultData = rDBConnectionService.executeSelectSQL(sqlStr, conn);
        return resultData;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring boot中动态增加数据源并且通过sharding-jdbc做分库分表查询 的相关文章

随机推荐

  • TCP报文格局详解

    TCP和谈只定义了一种报文格局 建立 拆除连接 传输数据应用同样的报文 TCP报文格局 TCP报文段首部 20个字节 源端口和目标端口 各占2个字节 16比特的端标语加上32比特的IP地址 共同构成相当于传输层办事接见点的地址 即 插口 这
  • (十九)STM32——输入捕获

    目录 学习目标 成果展示 内容 获取 配置 代码 总结 学习目标 本节内容我们要介绍的是输入捕获 其实也和定时器那部分知识是有关系的 所谓输入捕获 通俗一点来讲 其实就是通过检测上升沿和下降沿来计算你的输入持续时间 具体怎么去检测和捕获呢
  • c++实现图的操作(最小生成树和最短路径)

    题目描述 1 图的深度优先搜索演示 要求 图采用邻接表存储结构 编程实现图的创建 图的深度优先搜索递归算法 2 图的广度优先搜索演示 要求 图采用邻接表存储结构 编程实现图的创建 图的深度优先搜索递归算法 3 求带权无向图的最小生成树问题
  • VueRouter4简介

    第十四节 VueRouter4 x简介 基本用法 路由懒加载 打包分析 动态路由 路由嵌套 相关Api 一 简介和基本用法 1 简介 官网地址 https next router vuejs org zh introduction html
  • 详解随机梯度下降法(Stochastic Gradient Descent,SGD)

    深度学习最常用的优化方法就是随机梯度下降法 但是随机梯度下降法在某些情况下会失效 这是为什么呢 带着这个问题我们接着往下看 一个经典的例子就是假设你现在在山上 为了以最快的速度下山 且视线良好 你可以看清自己的位置以及所处位置的坡度 那么沿
  • 递归的本质理解

    什么是递归 函数里面调用函数本身 这就是递归 public int factorial int n if n lt 1 return 1 return n factorial n 1 先有 递 再有 归 递 是将问题拆分成子问题来解决 子问
  • vue 高德地图 实时路况

    先放效果图 1 准备工作 路况信息只需要使用web端即可实现 2 代码部分 1 在 public index html中引入 2 在需要用到地图的页面中
  • c语言valotile关键字

    volatile 是一种类型修饰符 提醒编译器他后面所定义的变量随时都有可能改变 因此编译后的程序每次需要存储或读取这个变量的时候 都会直接从变量地址中 内存中 读取数据 如果没有volatile关键字 则编译器可能优化读取和存储 可能暂时
  • Python爬虫案例:爬取世界大学排行榜,做数据可视化

    前言 闲的一匹 高三生没多久就要高考了 还有四个月 也是快了 咱来看看世界大学的排行榜 采集一下 做个可视化 看看有没有你心仪的学校 嘿嘿 知识点 动态数据抓包 requests发送请求 结构化 非结构化数据解析 开发环境 python 3
  • CCF-CSP真题《202212-3 JPEG 解码》思路+python,c++满分题解

    想查看其他题的真题及题解的同学可以前往查看 CCF CSP真题附题解大全 试题编号 202212 3 试题名称 JPEG 解码 时间限制 1 0s 内存限制 512 0MB 问题描述 问题背景 四年一度的世界杯即将画上尾声 在本次的世界杯比
  • RT-Thread 中龙芯1C的网络lwip升级到2.1.0

    RT Thread 龙芯1C 智龙开发板 的网络lwip升级到2 1 0 1 硬件平台 智龙开发板V3 42 2 软件平台 RT Thread 4 0 0 其中LWIP 2 1 0 3 问题描述 一直使用 RT Thread 软件平台 配套
  • (史上最全总结)总体方差,样本方差,标准差,抽样方差,标准误差,均方误差,协方差 ...........

    文章目录 数学期望 color blue 数学期望 数学期望 总体和样本 color blue 总体和样本 总体和样本
  • arcgis for javascript TileLayer 自定义高德地图图层

    效果如图 一 创建自定义切片层 要创建自定义图块层 您必须调用BaseTileLayer类的createSubclass 方法 命名自定义层为TintLayer 由于这一层需要知道在哪里访问预定义的图块 我们将创建一个属性 应用程序将为图层
  • Android开发:登录/注册界面的编写

    目录 新建一个空项目 或Activity 在xml中绘制登录界面 关掉ActionBar 运行 最终效果图 后记 在实际开发中 几乎所有的APP都会涉及到用户注册 登录页面的制作 因此本文以Android Studio为开发环境 教大家编写
  • Springboot参数校验和异常处理

    Springboot参数校验和异常处理 参数校验 异常处理 参数校验 pom xml文件添加依赖
  • 2022年4月8日字节跳动机抖音APP推荐实习面试题

    1 AUC是什么 如何计算AUC AUC 随机取一个正样本和一个负样本 正样本的预测值大于负样本预测值的概率 AUC计算的关键是找到所有正样本预测值大于负样本预测值的正负样本对 首先 需要将样本按照预测值进行从小到大排序 最小score对应
  • 爬虫技术和爬虫需求现状和展望

    技术社区中流行的爬虫技术相当多 很多人喜欢基于Python的 也有人喜欢用C 很多人由于系统集成开发和跨平台的需要倾向于java 我就属于后者 其实就原理来说 爬虫组件都是差不多的 无头浏览器 最能够说明爬虫的特性 它们被设计创造出来 大部
  • ACE_Message_Block功能简介

    ACE Message Block在Ace中用来表示消息的存放空间 可用做网络通信中的消息缓冲区 使用非常频繁 下面将在如下方简单的介绍一下ACE Message Block相关功能 创建消息块 释放消息块 从消息块中读写数据 数据的拷贝
  • Linux下设置归档路径不生效,缺少log_archive_config导致归档路径被禁用

    10g的DATA GUARD的一个主要特点就是引入了log archive config参数 如果缺少这个参数 可能会导致归档路径被禁用 看别人建立DATA GUARD时碰到了这个问题 当时觉得比较有意思 于是特意重现一下 当前是一个已经配
  • spring boot中动态增加数据源并且通过sharding-jdbc做分库分表查询

    最近项目中需要通过数仓对接数据出去 需要手动写一些查询 需要支持分库分表的场景 所以就选择了 google guava 做内存缓存 通过redis做持久化缓存 通过sharding jdbc实现跨表查询 一下贴的是几个主要的类 1 数据库信