【微服务】后台管理项目多数据源管理方案实战

目录

前言

1、使用Spring提供的AbstractRoutingDataSource

2、使用MyBatis注册多个SqlSessionFactory

3、使用dynamic-datasource框架


前言

        Java后台使用MyBatis-plus 快速访问多个数 据源,这里分享三种常用的多数据源管理方案

1、使用Spring提供的AbstractRoutingDataSource

这种方式的核心是使用 Spring 提供的 AbstractRoutingDataSource 抽象类,注入多个数据源。核心代码如下:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

@Component
@Primary   // 将该Bean设置为主要注入Bean
public class DynamicDataSource extends AbstractRoutingDataSource {


    // 当前使用的数据源标识
    public static ThreadLocal<String> name=new ThreadLocal<>();

    // 写
    @Autowired
    DataSource dataSource1;
    // 读
    @Autowired
    DataSource dataSource2;


    // 返回当前数据源标识
    @Override
    protected Object determineCurrentLookupKey() {
        return name.get();

    }
    
    @Override
    public void afterPropertiesSet() {

        // 为targetDataSources初始化所有数据源
        Map<Object, Object> targetDataSources=new HashMap<>();
        targetDataSources.put("W",dataSource1);
        targetDataSources.put("R",dataSource2);

        super.setTargetDataSources(targetDataSources);

        // 为defaultTargetDataSource 设置默认的数据源
        super.setDefaultTargetDataSource(dataSource1);

        super.afterPropertiesSet();
    }
}
将自己实现的 DynamicDataSource 注册成为默认的 DataSource 实例后,只需要在每次使用 DataSource 时,提前

改变一下其中的name标识,就可以快速切换数据源。这里使用到AOP功能,关键代码如下:

注解类,用于标识读库或者写库

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/***
 * @Author 黎剑
 * @Slogan 无意与众不同,只因品位出众,致敬未来的你
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface WR {
    String value() default "W";
}

切面类

import com.lijian.dynamic.datasource.DynamicDataSource;
import com.lijian.dynamic.datasource.annotation.WR;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/***
 * @author 黎剑
 * @slogan 无意与众不同,只因品位出众,致敬未来的你
 */
@Component
@Aspect
public class DynamicDataSourceAspect implements Ordered {

    // 前置
    @Before("within(com.lijian.dynamic.datasource.service.impl.*) && @annotation(wr)")
    public void before(JoinPoint point, WR wr){
        String name = wr.value();
        DynamicDataSource.name.set(name);

        System.out.println(name);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    //TODO 环绕通知
}

数据库配置类


import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.lijian.dynamic.datasource.DynamicDataSource;
import com.lijian.dynamic.datasource.plugin.DynamicDataSourcePlugin;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/***
 * @author 黎剑
 * @slogan 无意与众不同,只因品位出众,致敬未来的你
 */
@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }


    @Bean
    public DataSourceTransactionManager transactionManager1(DynamicDataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    @Bean
    public DataSourceTransactionManager transactionManager2(DynamicDataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

application.yml

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    datasource1:
      url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
    datasource2:
      url: jdbc:mysql://127.0.0.1:3306/datasource2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver

服务层实现类

import com.lijian.dynamic.datasource.annotation.WR;
import com.lijian.dynamic.datasource.mapper.FrendMapper;
import com.lijian.dynamic.datasource.entity.Frend;
import com.lijian.dynamic.datasource.service.FrendService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Service
public class FrendImplService implements FrendService {

    @Autowired
    FrendMapper frendMapper;


    @Override
    @WR("R")        // 库2
    public List<Frend> list() {
        return frendMapper.list();
    }

    @Override
    @WR("W")        // 库1
    public void save(Frend frend) {
        frendMapper.save(frend);
    }
}

启动类

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@MapperScan("com.lijian.dynamic.datasource.mapper")
@EnableAspectJAutoProxy(exposeProxy=true) // 启动AOP
public class DynamicDatasourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DynamicDatasourceApplication.class, args);
    }

}

2、使用MyBatis注册多个SqlSessionFactory

        如果使用MyBatis框架,要注册多个数据源的话,就需要将MyBatis底层的DataSource、SqlSessionFactory、 DataSourceTransactionManager这些核心对象一并进行手动注册。例如:
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;

@Configuration
// 继承mybatis:
// 1. 指定扫描的mapper接口包(主库)
// 2. 指定使用sqlSessionFactory是哪个(主库)
@MapperScan(basePackages = "com.lijian.datasource.dynamic.mybatis.mapper.r",
        sqlSessionFactoryRef="rSqlSessionFactory")
public class RMyBatisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public SqlSessionFactory rSqlSessionFactory()
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 指定主库
        sessionFactory.setDataSource(dataSource2());
        // 指定主库对应的mapper.xml文件
        /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/r/*.xml"));*/
        return sessionFactory.getObject();
    }



    @Bean
    public DataSourceTransactionManager rTransactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource2());
        return dataSourceTransactionManager;
    }

    @Bean
    public TransactionTemplate rTransactionTemplate(){
        return new TransactionTemplate(rTransactionManager());
    }
}
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionOperations;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;

/***
 *
 * 写数据源配置
 */
@Configuration
// 继承mybatis:
// 1. 指定扫描的mapper接口包(主库)
// 2. 指定使用sqlSessionFactory是哪个(主库)
@MapperScan(basePackages = "com.lijian.datasource.dynamic.mybatis.mapper.w",
        sqlSessionFactoryRef="wSqlSessionFactory")
public class WMyBatisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public SqlSessionFactory wSqlSessionFactory()
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 指定主库
        sessionFactory.setDataSource(dataSource1());
        // 指定主库对应的mapper.xml文件
        /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/order/*.xml"));*/
        return sessionFactory.getObject();
    }

    @Bean
    @Primary
    public DataSourceTransactionManager wTransactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource1());
        return dataSourceTransactionManager;
    }


    @Bean
    public TransactionTemplate wTransactionTemplate(){
        return new TransactionTemplate(wTransactionManager());
    }
}

 注解类

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MultiTransactional {

    String[] value() default {};
}

 AOP

import com.lijian.datasource.dynamic.mybatis.service.transaction.ComboTransaction;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MultiTransactionAop {

    private final ComboTransaction comboTransaction;

    @Autowired
    public MultiTransactionAop(ComboTransaction comboTransaction) {
        this.comboTransaction = comboTransaction;
    }

    @Pointcut("within(com.lijian.datasource.dynamic.mybatis.service.impl.*)")
    public void pointCut() {
    }

    @Around("pointCut() && @annotation(multiTransactional)")
    public Object inMultiTransactions(ProceedingJoinPoint pjp, MultiTransactional multiTransactional) {
        return comboTransaction.inCombinedTx(() -> {
            try {
                return pjp.proceed();       //执行目标方法
            } catch (Throwable throwable) {
                if (throwable instanceof RuntimeException) {
                    throw (RuntimeException) throwable;
                }
                throw new RuntimeException(throwable);
            }
        }, multiTransactional.value());
    }
}
import com.alibaba.druid.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.Callable;
import java.util.stream.Stream;

@Component
public class ComboTransaction {

    @Autowired
    private Db1TxBroker db1TxBroker;

    @Autowired
    private Db2TxBroker db2TxBroker;

    public <V> V inCombinedTx(Callable<V> callable, String[] transactions) {
        if (callable == null) {
            return null;
        }
        // 相当于循环 [wTransactionManager,wTransactionManager]
        Callable<V> combined = Stream.of(transactions)
                .filter(ele -> !StringUtils.isEmpty(ele))
                .distinct()
                .reduce(callable, (r, tx) -> {
                    switch (tx) {
                        case DbTxConstants.DB1_TX:
                            return () -> db1TxBroker.inTransaction(r);
                        case DbTxConstants.DB2_TX:
                            return () -> db2TxBroker.inTransaction(r);
                        default:
                            return null;
                    }
                }, (r1, r2) -> r2);

        try {
            return combined.call();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.Callable;

@Component
public class Db1TxBroker {

    @Transactional(DbTxConstants.DB1_TX)
    public <V> V inTransaction(Callable<V> callable) {
        try {
            return callable.call();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.Callable;

@Component
public class Db2TxBroker {

    @Transactional(DbTxConstants.DB2_TX)
    public <V> V inTransaction(Callable<V> callable) {
        try {
            return callable.call();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
public class DbTxConstants {

    public static final String DB1_TX = "wTransactionManager";

    public static final String DB2_TX = "rTransactionManager";
}

服务层类

import com.lijian.datasource.dynamic.mybatis.entity.Frend;
import com.lijian.datasource.dynamic.mybatis.mapper.r.RFrendMapper;
import com.lijian.datasource.dynamic.mybatis.mapper.w.WFrendMapper;
import com.lijian.datasource.dynamic.mybatis.service.FrendService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;


@Service
public class FrendImplService implements FrendService {

    @Autowired
    private RFrendMapper rFrendMapper;

    @Autowired
    private WFrendMapper wFrendMapper;

    @Autowired
    TransactionTemplate wTransactionTemplate;
    @Autowired
    TransactionTemplate rTransactionTemplate;


    // 读-- 读库
    @Override
    public List<Frend> list() {
        return rFrendMapper.list();
    }

    // 保存-- 写库
    @Override
    public void save(Frend frend) {
        wFrendMapper.save(frend);
    }


    // 保存-- 写库
    @Override
    public void saveW(Frend frend) {
        frend.setName("无羡W");
        wFrendMapper.save(frend);
    }

    // 保存-- 读库
    @Override
    public void saveR(Frend frend) {
        frend.setName("无羡R");
        rFrendMapper.save(frend);
    }

    @Transactional(transactionManager = "wTransactionManager")
    public void saveAll(Frend frend) throws Exception {
        FrendService frendService = (FrendService) AopContext.currentProxy();
        frendService.saveAllR(frend);
    }

    @Transactional(transactionManager = "rTransactionManager")
    public void saveAllR(Frend frend) {
        saveW(frend);
        saveR(frend);
        int a = 1 / 0;
    }
}
这样就完成了读库的注册。而读库与写库之间,就可以通过指定不同的 Mapper XML 文件的地址来进行区分。

3、使用dynamic-datasource框架

        dynamic-datasource是 MyBaits-plus 作者设计的一个多数据源开源方案。使用这个框架需要引入对应的 pom 依赖
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>
这样就可以在 SpringBoot 的配置文件中直接配置多个数据源,application.yaml
spring:
  datasource:
    dynamic:
      #设置默认的数据源或者数据源组,默认值即为master
      primary: master
      #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
          username: root
          password: 123456
          initial-size: 1
          min-idle: 1
          max-active: 20
          test-on-borrow: true
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          url: jdbc:mysql://127.0.0.1:3306/datasource2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
          username: root
          password: 123456
          initial-size: 1
          min-idle: 1
          max-active: 20
          test-on-borrow: true
          driver-class-name: com.mysql.cj.jdbc.Driver
这样就配置完成了 master slave_1 两个数据库。
接下来在使用时,只要在对应的方法或者类上添加 @DS注解即可。服务层实现类, 例如
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.lijian.dynamic.datasource.mapper.FrendMapper;
import com.lijian.dynamic.datasource.entity.Frend;
import com.lijian.dynamic.datasource.service.FrendService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Service
public class FrendImplService implements FrendService {

    @Autowired
    FrendMapper frendMapper;


    @Override
    @DS("slave")  // 从库, 如果按照下划线命名方式配置多个  , 可以指定前缀即可(组名)
    public List<Frend> list() {
        return frendMapper.list();
    }

    @Override
    @DS("#session.userID")
    @DSTransactional #事务控制
    public void save(Frend frend) {
        frendMapper.save(frend);
    }


    @DS("master")
    @DSTransactional
    public void saveAll(){
        // 执行多数据源的操作
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/760137.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SCCB协议介绍,以及与IIC协议对比

在之前的文章里已经介绍了IIC协议&#xff1a;iic通信协议 这篇内容主要介绍一下SCCB协议。 文章目录 SCCB协议&#xff1a;SCCB时序图iic时序图SCCB时序 VS IIC时序 总&#xff1a;SCCB协议常用在摄像头配置上面&#xff0c;例如OV5640摄像头&#xff0c;和IIC协议很相似&…

5.4符号三角形问题

#include<iostream> #include<stdio.h> using namespace std; int half; int ssum; int cnt0;//减号的个数 int n; int p[100][100]; int countt0; void BackTrack(int s) {if(cnt>half||s*(s-1)/2-cnt>half)return ;if(s>n){countt;return ;}for(int i0;…

可信和可解释的大语言模型推理-RoG

大型语言模型&#xff08;LLM&#xff09;在复杂任务中表现出令人印象深刻的推理能力。然而&#xff0c;LLM在推理过程中缺乏最新的知识和经验&#xff0c;这可能导致不正确的推理过程&#xff0c;降低他们的表现和可信度。知识图谱(Knowledge graphs, KGs)以结构化的形式存储了…

成都市水资源公报(2000-2022年)

数据年限&#xff1a;2000-2022年&#xff0c;无2009年 数据格式&#xff1a;pdf、word、jpg 数据内容&#xff1a;降水量、地表水资源量、地下水资源量、水资源总量、蓄水状况、平原区浅层地下水动态、水资源情况分析、供水量、用水量、污水处理、洪涝干旱等

Keysight是德 N9912A 手持式射频分析仪

Keysight是德 N9912A 手持式频谱分析仪 N9912A FieldFox 手持射频分析仪&#xff0c;4 GHz 和 6 GHz 轻盈耐用的电缆与天线分析仪、频谱分析仪、网络分析仪等等。 Keysight FieldFox 便携式分析仪可以在非常恶劣的工作环境中&#xff0c;轻松完成从日常维护到深入故障诊断的…

zabbix server client 安装配置

Zabbix Server 采用源码包部署&#xff0c;数据库采用 MySQL8.0 版本&#xff0c;zabbix-web 使用 nginxphp 来实现。具体信息如下&#xff1a; 软件名 版本 安装方式 Zabbix Server 6.0.3 源码安装 Zabbix Agent 6.0.3 源码安装 MySQL 8.0.28 yum安装 Nginx 1.20…

模型微调方法

文章目录 LoRADoRAMoRA 以下部分参考自: https://mp.weixin.qq.com/s/OxYNpXcyHF57OShQC26n4g LoRA LoRA是微软于2021年推出的一种经济型微调模型参数的方法。 它在冻结大部分的模型参数的情况下&#xff0c;仅仅更新额外的部分参数。其性能与全参数微调相似。 LoRA假设微调期间…

Apache Ranger 2.4.0 集成hadoop 3.X(Kerbos)

1、安装Ranger 参照上一个文章 2、修改配置 把各种plugin转到统一目录&#xff08;源码编译的target目录下拷贝过来&#xff09;&#xff0c;比如 tar zxvf ranger-2.4.0-hdfs-plugin.tar.gz tar zxvf ranger-2.4.0-hdfs-plugin.tar.gz vim install.properties POLICY_MG…

PD芯片OTG功能的应用 LDR6500

随着科技的飞速发展&#xff0c;智能手机、平板电脑等电子设备已经成为我们日常生活和工作中不可或缺的工具。这些设备的功能日益强大&#xff0c;应用场景也愈发广泛&#xff0c;但随之而来的是对充电和数据传输效率的高要求。在这一背景下&#xff0c;PD&#xff08;Power De…

Apache Ranger 2.4.0 集成Hive 3.x(Kerbos)

一、解压tar包 tar zxvf ranger-2.4.0-hive-plugin.tar.gz 二、修改install.propertis POLICY_MGR_URLhttp://localhost:6080REPOSITORY_NAMEhive_repoCOMPONENT_INSTALL_DIR_NAME/BigData/run/hiveCUSTOM_USERhadoop 三、进行enable [roottv3-hadoop-01 ranger-2.4.0-hive…

k8s笔记——helm chat与k8s Operator区别

k8s Operator Kubernetes 为自动化而生。无需任何修改&#xff0c;你即可以从 Kubernetes 核心中获得许多内置的自动化功能。 你可以使用 Kubernetes 自动化部署和运行工作负载&#xff0c;甚至 可以自动化 Kubernetes 自身。 Kubernetes 的 Operator 模式概念允许你在不修改…

爱情再启:庄国栋笑谈“玫瑰人生”爱情觉悟

庄国栋&#xff0c;这位电视剧《玫瑰的故事》中的男主角&#xff0c; 最近在一次采访中坦言&#xff1a;“如果给我一次重来的机会&#xff0c; 我绝对会毫不犹豫地选择爱情&#xff01;” 听到这话&#xff0c; 我不禁想&#xff0c;庄先生&#xff0c;您是不是被剧里的玫瑰…

PotPlayer安装及高分辨率设置

第1步&#xff1a; 下载安装PotPlayer软件 PotPlayer链接&#xff1a;https://pan.baidu.com/s/1hW168dJrLBonUnpLI6F3qQ 提取码&#xff1a;z8xd 第2步&#xff1a; 下载插件&#xff0c;选择系统对应的位数进行运行&#xff0c;该文件不能删除&#xff0c;删除后将失效。 …

(单机架设教程)凯旋|当年的QQ游戏

前言 今天给大家带来一款单机游戏的架设&#xff1a;凯旋 &#xff0c; 当年的QQ游戏 如今市面上的资源参差不齐&#xff0c;大部分的都不能运行&#xff0c;本人亲自测试&#xff0c;运行视频如下&#xff1a; 凯旋单机 搭建教程 此游戏架设需要安装虚拟机&#xff0c; 没有…

pytest测试框架pytest-cov插件生成代码覆盖率

Pytest提供了丰富的插件来扩展其功能&#xff0c;本章介绍下pytest-cov插件&#xff0c;用于生成测试覆盖率报告&#xff0c;帮助开发者了解哪些部分的代码被测试覆盖&#xff0c;哪些部分还需要进一步的测试。 pytest-cov 支持多种报告格式&#xff0c;包括纯文本、HTML、XML …

什么是 Elasticsearch 数据预热?

引言&#xff1a;在现代的信息检索和数据分析领域&#xff0c;Elasticsearch 已经成为一个广泛应用的分布式搜索和分析引擎。作为开源项目的一部分&#xff0c;Elasticsearch 提供了强大的实时搜索和分析能力&#xff0c;使得处理大规模数据变得更加高效和可靠。然而&#xff0…

GPT-5 一年半后发布,对此你有何期待?

IT之家6月22日消息&#xff0c;在美国达特茅斯工程学院周四公布的采访中&#xff0c;OpenAI首席技术官米拉穆拉蒂被问及GPT-5是否会在明年发布&#xff0c;给出了肯定答案并表示将在一年半后发布。此外&#xff0c;穆拉蒂在采访中还把GPT-4到GPT-5的飞跃描述为高中生到博士生的…

在线教育项目(一):如何防止一个账号多个地方登陆

使用jwt做验证&#xff0c;使用账号作为redis中的key,登录的时候生成token放到redis中&#xff0c;每次申请资源的时候去看token 有没有变&#xff0c;因为token每次登录都会去覆盖&#xff0c;只要第二次登录token就不一样了

在我们的大数据平台(XSailbaot)上进行企业级数据建模的思路

1. 背景 笔者所在的公司是差不多二十年前搞CIM&#xff08;公共信息模型的&#xff09;起家的。当时公司的前辈搞了基于CIS协议的模型服务器、数据服务器、模式编辑器等&#xff0c;形成了一套基于公共信息模型建模的平台系统。其中可视化建模&#xff0c;建好了模式类以后&am…

SA 注册流程

目录 1. UE开机后按照3GPP TS 38.104定义的Synchronization Raster搜索特定频点 2.UE尝试检测PSS/SSS&#xff0c;取得下行时钟同步&#xff0c;并获取小区的PCI&#xff1b;如果失败则转步骤1搜索下一个频点&#xff1b;否则继续后续步骤&#xff1b; 3.解析Mib&#xff0c;…