首页 > 其他分享 >sharding分表应用笔记(三)——多数据源路由

sharding分表应用笔记(三)——多数据源路由

时间:2023-11-20 09:57:18浏览次数:26  
标签:Author 数据源 nagiumi Param 分表 sharding public 路由

sharding分表应用笔记(三)——多数据源路由

目录

1 背景

应用背景:物理数据源只有一个;对于部分数据量大的表实行按月分表处理,其他的表仍然保持原先的模式不变。因为sharding对一些sql语句可能有兼容问题,所以为了预防生产问题,决定直接通过原数据源对未分表的表格进行操作,只有特定的表格才通过sharding数据源进行操作。所以需要进行多数据源路由。本篇记录sharding分表的多数据源路由实现。

环境:spring

2 配置

2.1 命名空间配置

<!-- 多数据源配置 -->
<bean id="multipleDataSource" class="com.example.dbConfig.MultipleDataSource">
    <!-- 默认数据源 -->
    <property name="defaultTargetDataSource" ref="dataSource" />
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <entry key="DEFAULT" value-ref="dataSource"/>
            <entry key="SHARDING" value-ref="shardingDataSource"/>
        </map>
    </property>
</bean>

之后用多数据源的BeanId(multipleDataSource)替换各种数据库配置中原先的数据源BeanId(dataSource)

2.2 spring-jdbc路由配置

继承实现spring-jdbc的AbstractRoutingDataSource多数据源路由接口。实现该接口后,每次进行数据库操作时会通过determineCurrentLookupKey方法获取当前设定的数据库key,然后通过命名空间配置的映射启用对应的数据源。

/**
 * @ClassName: MultipleDataSource
 * @Description: 数据源路由实现类
 * @Author: nagiumi
 * @Date: 2023/6/5
 * @Version:1.0
 */
public class MultipleDataSource extends AbstractRoutingDataSource {
    private static final Logger log = LoggerFactory.getLogger(MultipleDataSource.class);
    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceConfig = MultipleDataSourceHandler.getRouteKey();
        return dataSourceConfig;
    }
}
/**
 * @ClassName: MultipleDataSourceHandler
 * @Description: 多数据源持有类,数据源路由
 * @Author: nagiumi
 * @Date: 2023/6/5
 * @Version:1.0
 */
public class MultipleDataSourceHandler {
    private static final Logger logger = LoggerFactory.getLogger(MultipleDataSourceHandler.class);
    /**
     * 线程副本,保证线程安全
     */
    private static ThreadLocal<String> routeKey = new ThreadLocal<String>();

     /**
     *@Description: 绑定当前线程数据源路由的key 使用完成后必须调用removeRouteKey()方法删除
     *@Param:  * @Param: key
     *@return:
     *@Author: nagiumi
     *@date: 2023/6/5
     */
    public static void setRouteKey(String key){
        logger.warn("系统切换到[{}]数据源",key);
        routeKey.set(key);
    }

    /**
    *@Description: 获取当前线程的路由
    *@Param:  * @Param: null
    *@return: 
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    public static String getRouteKey(){
        return routeKey.get();
    }

    /**
    *@Description: 删除与当前线程绑定的路由key
    *@Param:  * @Param: null
    *@return: 
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    public static void removeRouteKey(){
        logger.warn("系统重置数据源");
        routeKey.remove();
    }
}

3 指定路由

3.1 自定义注解

自定义一个指定路由数据库的注解,通过在表的service类上添加注解来完成对应表的指定路由操作。

数据源枚举

public interface ContextConstant {
    /**
    *@Description: 数据源枚举
    *@Param:  * @Param: null
    *@return:
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    enum DataSourceType {
        DEFAULT, SHARDING
    }
}

定义注解

/**
 * @ClassName: ContextConstant
 * @Description: 自定义切换数据源注解
 * @Author: nagiumi
 * @Date: 2023/6/5
 * @Version:1.0
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    /**
    *@Description: 默认为上报数据库数据源
    *@Param:  * @Param: null
    *@return: 
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    ContextConstant.DataSourceType value() default ContextConstant.DataSourceType.DEFAULT;
}

3.2 功能实现

定义aop进行注解扫描,然后反射获取注解指定的路由

/**
 * @ClassName: DynamicDataSourceAspect
 * @Description: 切换数据源类
 * @Author: nagiumi
 * @Date: 2023/6/5
 * @Version:1.0
 * 设置为1,优先加载,优先级高于AbstractRoutingDataSource的determineCurrentLookupKey()
 *
 */
@Component
@Aspect
@Order(1)
public class DynamicDataSourceAspect {

    private static final Logger log = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    /**
    *@Description: 前置切面
    *@Param:  * @Param: null
    *@return:
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    @Before("execution(* com.example.business..*.*(..))")
    public void before(JoinPoint point) {
        try {
            DataSource annotationOfClass = point.getTarget().getClass().getAnnotation(DataSource.class);
            String methodName = point.getSignature().getName();
            Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
            Method method = point.getTarget().getClass().getMethod(methodName, parameterTypes);
            DataSource methodAnnotation = method.getAnnotation(DataSource.class);
            methodAnnotation = methodAnnotation == null ? annotationOfClass : methodAnnotation;
            ContextConstant.DataSourceType dataSourceType = methodAnnotation != null
                    && methodAnnotation.value() != null ? methodAnnotation.value() : null;
            if (Objects.nonNull(dataSourceType)) {
                log.warn("aspect 准备切换数据源,发起方:{}", point.getTarget().getClass().getName() + "#" + methodName);
                MultipleDataSourceHandler.setRouteKey(dataSourceType.name());
            }
        } catch (NoSuchMethodException e) {
            log.error("aspect error,err={}",e);
        }
    }

    /**
    *@Description: 后置切面
    *@Param:  * @Param: null
    *@return:
    *@Author: nagiumi
    *@date: 2023/6/5
    */
    @After("execution(* com.example.business..*.*(..))")
    public void after(JoinPoint point) {
        String oldKey = MultipleDataSourceHandler.getRouteKey();
        if (StringUtils.isNotBlank(oldKey)) {
            MultipleDataSourceHandler.removeRouteKey();
        }
    }
}

3.3 用例

@Service
@DataSource(ContextConstant.DataSourceType.SHARDING)
public class RepaymentLogBizService {

    @Autowired
    private RepaymentLogMapper repaymentLogMapper;

    //业务方法

}

标签:Author,数据源,nagiumi,Param,分表,sharding,public,路由
From: https://www.cnblogs.com/nagiumi-misaka/p/17843259.html

相关文章

  • 根据行列标题名称,查找二维数据源的值区域内容!
    1职场实例小伙伴们大家好,随着冬至的到来,天气也是越发的寒冷起来,不少地方竟然飘起了今年第一场早雪,而我们今天要讲解重温一个Excel界热度很高的问题:如何根据行列标题名称,查找二维数据源的值区域内容?如下图所示:A1:D4单元格为数据源区域。数据源区域是一个明显的二维表格式的表格。A列......
  • RestCloud AppLink已支持的数据源有哪些?​
    RestCloudAppLink是什么?首先,我们需要了解RestCloudAppLink是什么,AppLink是一款由RestCloud公司推出的超级应用连接器。不需要开发,零代码,低成本即可快速打通数百款应用之间的数据。通过流程搭建,可以智能、高效地完成自动化任务,在大大提高工作效率的同时,也降低了大量的人工成本。Re......
  • sharding分表应用笔记(二)——按时间分表策略配置
    sharding分表应用笔记(二)——按时间分表策略配置目录sharding分表应用笔记(二)——按时间分表策略配置1背景2配置2.1命名空间配置2.2策略接口实现2.2.1时间精确分片策略2.2.2时间范围分片策略3外部链接1背景应用背景:物理数据源只有一个;对于部分数据量大的表实行按月分表处......
  • Sharding-JDBC框架
    背景  Sharding-JDBC配置与分离规则(重点)2.在application.yml中配置读写分离规则server: port:8080spring: shardingsphere:   datasource:     names:       master,slave     #主数据源matser     master:       type:com.alibab......
  • 解决VS2005在Winform窗体设计界面中数据源窗口灰化不显示数据源的问题
    近日发现一个问题,在项目中添加了几个数据源,当在Code界面时,数据源窗口可以显示出我添加的数据源,但是一切换到窗体设计界面,数据源窗口就灰化,数据源窗口中所有的数据源都消失了,切换到Code界面,数据源有出来了,切换到设计界面,又消失了,百思不得其解,一定是VS出问题了……最后经过一顿搜索,原......
  • sharding分表应用笔记(一)——分表数据源配置
    sharding分表应用笔记(一)——分表数据源配置目录sharding分表应用笔记(一)——分表数据源配置1前言2配置2.1相关依赖2.2命名空间配置2.2.1引入sharding命名空间2.2.2物理数据源配置2.2.3分表数据源配置3外部链接1前言应用背景:物理数据源只有一个;对于部分数据量大的表实行......
  • 多源异构数据源融合怎么做,用这个一步搞定
    多源异构数据源融合是将来自不同来源、不同类型和不同结构的数据整合在一起,以实现更全面、准确和综合的分析和决策支持。以下是一个详细的步骤指南,以帮助您了解如何进行多源异构数据源融合。1.确定数据需求和目标:-首先,明确您的数据需求和目标。确定您想要从数据中获取什么样......
  • 自增主键与雪花算法的优缺点、设计更适合分库分表的UUID算法
    (目录)为什么不推荐使用自增主键递增主键的作用我们在数据库里保存的数据就跟excel表一样,一行行似的而在底层,这一行行数据,就是保存在一个个16k大小的页里。每次都去遍历所有的行性能会不好,于是为了加速搜索,我们可以根据主键id,从小到大排列这些行数据,将这些数据页用双向链表......
  • 【初学Nacos小问题】Nacos同一个命名空间下配置的数据源在项目中是如何识别的!
    在user-service项目中添加一个bootstrap.yml文件,需要配置服务名、开发环境、nacos地址、后缀名,对应nacos添加的配置文件名。内容如下:spring:application:name:userservice#服务名称profiles:active:dev#开发环境,这里是devcloud:nacos:serv......
  • Centos7 部署gitea,使用sqlite作为数据源
    #创建用户git,指定登录shell为Bash,-d指定家目录默认/home/git,-m如果指定的家目录不存在,则创建该目录#踩坑:-r不分配登录shell和家目录useradd-s/bin/bash-d-mgit#编辑/etc/sudoers文件以允许git用户在执行sudo命令时无需密码vi/etc/sudoers在文件中找到以rootALL=......