Spring系列之批处理Spring Batch介绍

概述

官网,GitHub

A lightweight, comprehensive batch framework designed to enable the development of robust batch applications vital for the daily operations of enterprise systems.

执行流程
在这里插入图片描述

实战

假设有个待处理的任务,如文件batch-test.csv

1,TODO
2,TODO
3,TODO

Maven引入依赖:

<dependency><groupId>org.springframework.batch</groupId><artifactId>spring-batch-core</artifactId>
</dependency>

测试类:

private static final String CSV_FILE = "batch-test.csv";@Resource
private JobLauncher jobLauncher;@Resource
private JobRepository jobRepository;@Resource
private PlatformTransactionManager manager;@Test
public static void test() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {// 创建readerFlatFileItemReader<TodoItem> reader = new FlatFileItemReader<>();reader.setResource(new FileSystemResource(CSV_FILE));reader.setLineMapper(new TestLineMapper());// 创建processorTestItemProcessor processor = new TestItemProcessor();// 创建writerFlatFileItemWriter<TodoItem> writer = new FlatFileItemWriter<>();writer.setResource(new FileSystemResource(CSV_FILE));writer.setLineAggregator(new TestLineAggregator());// 创建StepStepBuilderFactory stepBuilderFactory = new StepBuilderFactory(jobRepository, manager);Step step = stepBuilderFactory.get("step").<TodoItem, TodoItem>chunk(1).reader(reader).processor(processor).writer(writer).build();// 创建JobJobBuilderFactory jobBuilderFactory = new JobBuilderFactory(jobRepository);Job job = jobBuilderFactory.get("job").start(step).build();// 启动任务jobLauncher.run(job, new JobParameters());
}

POJO实体类:

@Data
public class TodoItem {private String id;private String status;
}

其中处理器如下:

public class TestItemProcessor implements ItemProcessor<TodoItem, TodoItem> {@Overridepublic TodoItem process(TodoItem item) {// 模拟任务处理逻辑log.info("doing item, id=" + item.getId());item.setStatus("DONE");return item;}
}

行(记录)聚合器如下:

public class TestLineAggregator implements LineAggregator<TodoItem> {@Overridepublic String aggregate(TodoItem item) {return item.getId() + "," + item.getStatus();}
}

行映射器如下:

public class TestLineMapper implements LineMapper<TodoItem> {@Overridepublic TodoItem mapLine(String line, int lineNumber) {String[] args = line.split(",");TodoItem item = new TodoItem();item.setId(args[0]);item.setStatus(args[1]);return item;}
}

方法执行成功时,console控制台输出:

doing item, id=1
doing item, id=2
doing item, id=3

另外batch-test.csv会变成:

1,DONE
2,DONE
3,DONE

概念

Job

Job和Step是Spring Batch执行批处理任务最为核心的两个概念。Job是一个封装整个批处理过程的一个概念。Job在Spring Batch的体系当中是最顶层的抽象概念,是最上层接口:

/*** 重启策略应用于整个作业,而不是某个步骤*/
public interface Job {String getName();default boolean isRestartable() {return true;}void execute(JobExecution execution);@Nullabledefault JobParametersIncrementer getJobParametersIncrementer() {return null;}default JobParametersValidator getJobParametersValidator() {return new DefaultJobParametersValidator();}
}

定义有五个方法,实现类主要有两种类型的Job,SimpleJob,FlowJob。除Job外还有JobInstance、JobExecution两个更加底层的抽象。

Job是运行的基本单位,内部由Step组成,本质上可看成Step的容器。一个Job可按照指定的逻辑顺序组合Step,并提供给所有Step设置相同属性的方法,如一些事件监听,跳过策略。

Spring Batch以SimpleJob类的形式提供Job接口的默认简单实现,在Job之上创建一些标准功能:

@Bean
public Job footballJob() {return this.jobBuilderFactory.get("footballJob").start(playerLoad()).next(gameLoad()).next(playerSummarization()).end().build();
}

JobInstance

源码如下:

public class JobInstance extends Entity {private final String jobName;
}

其中Entity如下:

public class Entity implements Serializable {private Long id;private volatile Integer version;
}

JobInstance指的是Job运行当中,作业执行过程当中的概念。Instance即实例。

JobParameters

同一个Job每天运行一次的话,则每天都有一个JobIntsance,但他们的Job定义都是一样的,怎么来区别一个Job的不同JobIntsance?

Spring Batch提供JobParameters用来唯一标识JobIntsance。JobParameters对象包含一组用于启动批处理作业的参数,它可以在运行期间用于识别或甚至用作参考数据。JobInstance=Job+JobParameters。

JobExecution指的是单次尝试运行一个定义好的Job的代码层面的概念。Job的一次执行可能失败或成功。只有当执行成功完成时,给定的与执行相对应的JobInstance才也被视为完成。

JobParameters源码如下:

public class JobParameters implements Serializable {private final Map<String, JobParameter<?>> parameters;
}

可知,JobParameters是JobParameter的Map集合。而JobParameter是一个泛型类:

public class JobParameter<T> implements Serializable {private final T value;private final Class<T> type;private final boolean identifying;
}

JobExecution

public class JobExecution extends Entity {private final JobParameters jobParameters;private JobInstance jobInstance;private volatile Collection<StepExecution> stepExecutions;private volatile BatchStatus status;private volatile LocalDateTime startTime;private volatile LocalDateTime createTime;private volatile LocalDateTime endTime;private volatile LocalDateTime lastUpdated;private volatile ExitStatus exitStatus;private volatile ExecutionContext executionContext;private transient volatile List<Throwable> failureExceptions;
}

JobExecution当中提供getStatus方法用于获取一个Job某一次特地执行的一个状态。BatchStatus代表Job枚举状态:

public enum BatchStatus {COMPLETED,STARTING,STARTED,STOPPING,STOPPED,FAILED,ABANDONED,UNKNOWN;
}

这些属性对于一个Job的执行来说是非常关键的信息,且Spring Batch会将其持久到数据库当中,用于存储JobExecution的表为batch_job_execution

Step

每一个Step对象都封装批处理作业的一个独立阶段。事实上每一个Job本质上都是由一个或多个步骤组成。每一个Step包含定义和控制实际批处理所需的所有信息。任何特定的内容都由编写Job的开发人员自行决定。

一个Step可非常简单也可非常复杂。如,一个Step的功能是将文件中的数据加载到数据库中,基于现在Spring Batch的支持则几乎不需要写代码。更复杂的Step可能具有复杂的业务逻辑,这些逻辑作为处理的一部分。

与Job一样,Step具有与JobExecution类似的StepExecution。

StepExecution

StepExecution表示一次执行Step,每次运行一个Step时都会创建一个新的StepExecution,类似于JobExecution。但是,某个步骤可能由于其之前的步骤失败而无法执行。且仅当Step实际启动时才会创建StepExecution。

一次Step执行的实例由StepExecution类的对象表示。每个StepExecution都包含对其相应步骤的引用以及JobExecution和事务相关的数据,例如提交和回滚计数以及开始和结束时间。

此外,每个步骤执行都包含一个ExecutionContext,其中包含开发人员需要在批处理运行中保留的任何数据,例如重新启动所需的统计信息或状态信息。下面是一个从数据库当中截图的实例:

ExecutionContext

ExecutionContext即每一个StepExecution的执行环境。它包含一系列的键值对。获取ExecutionContext:

ExecutionContext ecStep = stepExecution.getExecutionContext();
ExecutionContext ecJob = jobExecution.getExecutionContext();

JobRepository

JobRepository用于存储任务执行的状态信息,比如什么时间点执行什么任务、任务执行结果如何等。提供2种实现,一种是通过Map形式保存在内存中,程序重启后任务信息丢失,在分布式下无法获取其他节点的任务执行情况;另一种是保存在数据库中,将数据保存在下面6张表里:

  • BATCH_JOB_INSTANCE
  • BATCH_JOB_EXECUTION_PARAMS
  • BATCH_JOB_EXECUTION
  • BATCH_STEP_EXECUTION
  • BATCH_JOB_EXECUTION_CONTEXT
  • BATCH_STEP_EXECUTION_CONTEXT

JobRepository是一个用于将上述Job,Step等概念进行持久化的一个类。它同时给Job和Step以及下文会提到的JobLauncher实现提供CRUD操作。首次启动Job时,将从repository中获取JobExecution,并且在执行批处理的过程中,StepExecution和JobExecution将被存储到repository当中。@EnableBatchProcessing注解可以为JobRepository提供自动配置。

支持主流数据库:DB2、Derby、H2、HSQLDB、MySQL、Oracle、PostgreSQL、SQLServer、Sybase。

源码:

public interface JobRepository {default List<String> getJobNames() {return Collections.emptyList();}default List<JobInstance> findJobInstancesByName(String jobName, int start, int count) {return Collections.emptyList();}default List<JobExecution> findJobExecutions(JobInstance jobInstance) {return Collections.emptyList();}boolean isJobInstanceExists(String jobName, JobParameters jobParameters);JobInstance createJobInstance(String jobName, JobParameters jobParameters);JobExecution createJobExecution(String jobName, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException;void update(JobExecution jobExecution);void add(StepExecution stepExecution);void addAll(Collection<StepExecution> stepExecutions);void update(StepExecution stepExecution);void updateExecutionContext(StepExecution stepExecution);void updateExecutionContext(JobExecution jobExecution);@Nullabledefault JobInstance getJobInstance(String jobName, JobParameters jobParameters) {throw new UnsupportedOperationException();}@NullableStepExecution getLastStepExecution(JobInstance jobInstance, String stepName);long getStepExecutionCount(JobInstance jobInstance, String stepName);@NullableJobExecution getLastJobExecution(String jobName, JobParameters jobParameters);default void deleteStepExecution(StepExecution stepExecution) {throw new UnsupportedOperationException();}default void deleteJobExecution(JobExecution jobExecution) {throw new UnsupportedOperationException();}default void deleteJobInstance(JobInstance jobInstance) {throw new UnsupportedOperationException();}
}

JobLauncher

用于启动指定JobParameters的Job:

@FunctionalInterface
public interface JobLauncher {JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException;
}

run方法根据传入的Job以及jobparamaters从JobRepository获取一个JobExecution并执行Job。

Line、Item、Field

三个很重要的概念:

  • Line:表示行,Spring Batch提供LineAggregator、LineMapper、LineTokenizer、LineCallbackHandler等接口;
  • Item:表示记录,逻辑概念,可包含多行,Spring Batch提供ItemReader、ItemWriter、ItemProcessor等接口;
  • Field:表示字段,Spring Batch提供FieldExtractor、FieldSet、FieldSetFactory等接口;
特性LineItemField
定义层次数据源中未解析的基础单元逻辑层级,业务数据的领域对象数据(字段/属性)
关系Line是Item的输入由Field组成一个ItemItem组成部分

ItemReader

public interface ItemReader<T> {@NullableT read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException;
}

ItemReader是一个读数据的接口,为每一个Step提供数据输入。当ItemReader读完所有数据时,它会返回null来告诉后续操作数据已经读完。

Spring Batch提供很多实现类,支持各种读取数据源,包括各种类型数据库,文件,数据流等,几乎涵盖所有场景:

  • FlatFileItemReader
  • JdbcPagingItemReader
  • JdbcCursorItemReader

FlatFileItemReader

实战例子即为FlatFileItemReader,用于读取表格文件,文本文件,有如下属性:

  • setResource 指定文件资源的位置:通过ClassPathResource(类所在路径)或者FileSystemResource(文件系统所在路径)来指定要读取的文件
  • setLineMapper 行映射:指定行与实体对象之间的映射关系,示例代码使用DefaultLineMapper
  • seEncoding 读取编码格式,默认为‘iso-8859-1’
  • setStrict 严格模式,输入文件不存在会抛出异常,阻断当前Job,默认为true

JdbcPagingItemReader

例子:

@Bean
public JdbcPagingItemReader itemReader(DataSource source, PagingQueryProvider provider) {Map<String, Object> params = new HashMap<>();params.put("status", "NEW");return new JdbcPagingItemReaderBuilder<CustomerCredit>().name("creditReader").dataSource(source).queryProvider(provider).parameterValues(params).rowMapper(customerCreditMapper()).pageSize(1000).build();
}@Bean
public SqlPagingQueryProviderFactoryBean queryProvider() {SqlPagingQueryProviderFactoryBean provider = new SqlPagingQueryProviderFactoryBean();provider.setSelectClause("select id, name, credit");provider.setFromClause("from customer");provider.setWhereClause("where status=:status");provider.setSortKey("id");return provider;
}

JdbcPagingItemReader必须指定一个PagingQueryProvider,负责提供SQL查询语句来按分页返回数据。

JdbcCursorItemReader

例子:

private JdbcCursorItemReader<Map<String, Object>> buildItemReader(final DataSource dataSource, String tableName, String tenant) {JdbcCursorItemReader<Map<String, Object>> reader = new JdbcCursorItemReader<>();reader.setDataSource(dataSource);reader.setSql("sql here");reader.setRowMapper(new RowMapper());return reader;
}

ItemWriter

public interface ItemWriter<T> {void write(List<? extends T> items) throws Exception;
}

写数据的抽象,为每一个Step提供数据写出的功能。单位是可以配置的,可以一次写一条、一个chunk的数据,ItemWriter对于读入的数据是不能做任何操作的。

提供多种ItemWriter接口的实现类,包括对文本文件、XML文件、数据库、JMS消息等写的处理,支持自定义writer功能。

Spring Batch提供很多实现类,支持各种读取数据源,包括各种类型数据库,文件,数据流等,几乎涵盖所有场景:

  • FlatFileItemWriter
  • StaxEventItemWriter

FlatFileItemWriter

StaxEventItemWriter

用于写到XML文件,需引入如下依赖,用法和FlatFileItemWriter类似:

<dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId>
</dependency>

默认编码为utf-8,其他属性:

  • setRootTagName:设置根节点标签名称
  • setMarshaller:指定对象与节点映射关系

ItemProcessor

处理操作,其接口:

public interface ItemProcessor<I, O> {O process(I item) throws Exception;
}

ItemProcessor主要负责数据的转换与处理,process方法的形参传入I类型的对象,通过处理后返回O型的对象。支持自定义业务代码来对数据进行处理。

ItemProcessor对项目的业务逻辑处理的一个抽象, 当ItemReader读取到一条记录之后,ItemWriter还未写入这条记录之前,可以借助temProcessor提供一个处理业务逻辑的功能,并对数据进行相应操作。如果在ItemProcessor发现一条数据不应该被写入,可以通过返回null来表示。ItemProcessor和ItemReader以及ItemWriter可以非常好的结合在一起工作,他们之间的数据传输也非常方便,直接使用即可。

进阶

注解

Spring Batch提供的注解:

  • EnableBatchProcessing
  • JobScope
  • StepScope
  • AfterChunk
  • AfterChunkError
  • AfterJob
  • AfterProcess
  • AfterRead
  • AfterStep
  • AfterWrite
  • BeforeChunk
  • BeforeJob
  • BeforeProcess
  • BeforeRead
  • BeforeStep
  • BeforeWrite
  • OnProcessError
  • OnReadError
  • OnSkipInProcess
  • OnSkipInRead
  • OnSkipInWrite
  • OnWriteError

异常

包括:

  • UnexpectedJobExecutionException
  • FatalStepExecutionException
  • StartLimitExceededException
  • NonTransientResourceException
  • ItemWriterException
  • ItemReaderException
  • ItemStreamException
  • ReaderNotOpenException
  • UnexpectedInputException
  • WriterNotOpenException
  • WriteFailedException
  • RepeatException
  • FlushFailedException
  • JobExecutionAlreadyRunningException
  • JobRestartException
  • JobInstanceAlreadyCompleteException
  • JobParametersInvalidException
  • UnsupportedOperationException
  • 还有很多

每种异常的出错场景,问题根源,以及解决方法,有待进一步学习。

问题

如何默认不启动Job?
在使用Java config使用Spring Batch的Job时,如果不做任何配置,项目在启动时就会默认去跑定义好的批处理Job。如何让项目在启动时不自动去跑Job呢?在application.properties中添加如下属性:spring.batch.job.enabled=false

在读数据时内存不够?
在使用Spring Batch做数据迁移时,发现在Job启动后,执行到一定时间点时就卡在一个地方不动,且log也不再打印,等待一段时间之后,得到如下错误:
红字的信息为:Resource exhaustion event:the JVM was unable to allocate memory from the heap.

项目发出一个资源耗尽的事件,告诉JVM无法再为堆分配内存?
造成这个错误的原因是:batch Job的reader是一次性拿回数据库里的所有数据,并没有进行分页,当这个数据量太大时,就会导致内存不够用。解决办法有两个:

  1. 调整reader读数据逻辑,按分页读取,但实现上会麻烦一些,且运行效率会下降
  2. 增大service内存

原则

构建批处理任务时,应考虑以下关键原则和注意事项:

  1. 批处理体系结构通常会影响体系结构
  2. 尽可能简化并避免在单批应用程序中构建复杂的逻辑结构
  3. 保持数据的处理和存储在物理上靠得很近(换句话说,将数据保存在处理过程中)
  4. 最大限度地减少系统资源的使用,尤其是IO,在internal memory中执行尽可能多的操作
  5. 分析SQL语句,查看应用程序IO,以确保避免不必要的物理IO,特别是,需要寻找以下四个常见缺陷:
    1. 当数据可以被读取一次并缓存或保存在工作存储中时,读取每个事务的数据
    2. 重新读取先前在同一事务中读取数据的事务的数据
    3. 导致不必要的表或索引扫描
    4. 未在SQL语句的WHERE子句中指定键值
  6. 在批处理运行中不要做两次一样的事情。例如,如果需要数据汇总以用于报告目的,则应该(如果可能)在最初处理数据时递增存储的总计,因此您的报告应用程序不必重新处理相同的数据
  7. 在批处理应用程序开始时分配足够的内存,以避免在此过程中进行耗时的重新分配
  8. 总是假设数据完整性最差。插入适当的检查和记录验证以维护数据完整性
  9. 尽可能实施校验和以进行内部验证。例如,对于一个文件里的数据应该有一个数据条数纪录,告诉文件中的记录总数以及关键字段的汇总
  10. 在具有真实数据量的类似生产环境中尽早计划和执行压力测试
  11. 在大批量系统中,数据备份可能具有挑战性,特别是如果系统以24-7在线的情况运行。数据库备份通常在在线设计中得到很好的处理,但文件备份应该被视为同样重要。如果系统依赖于文件,则文件备份过程不仅应该到位并记录在案,还应定期进行测试。

参考

  • 批处理框架Spring Batch

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[保姆式教程]使用labelimg2软件标注定向目标检测数据和格式转换

定向目标检测是一种在图像或视频中识别和定位对象的同时&#xff0c;还估计它们方向的技术。这种技术特别适用于处理有一定旋转或方向变化的对象&#xff0c;例如汽车、飞机或文本。定向目标检测器的输出是一组旋转的边界框&#xff0c;这些框精确地包围了图像中的对象&#xf…

Socket编程:UDP网络编程项目

目录 一、回显服务器 二、翻译器 三、聊天室 一、回显服务器 项目介绍&#xff1a;使用UDPIPv4协议进行Linux网络编程&#xff0c;实现回显服务器和客户端 功能介绍&#xff1a;客户端发送数据&#xff0c;经过服务端再返回到客户端&#xff0c;输出数据 源代码&#xff1…

HarmonyOS4+NEXT星河版入门与项目实战(24)------Stage模型

文章目录 1、概念2、配置文件1、全局配置文件2、模块配置文件3、UIAbility生命周期1、图文归纳2、生命周期方法入口4、页面生命周期1、图文描述1、概念 2、配置文件 1、全局配置文件 2、模块配置文件 统一修改配置文件技巧:点击任意json 文件,选择 Open editor ,在显示的列表…

torch_geometric使用手册-Heterogeneous Graph Learning(专题三)

大量的现实世界数据集以异构图(Heterogeneous Graph) 的形式存储,这促使了在PyG中引入专门的功能。例如,大多数推荐系统中的图(如社交图)都是异构图,它们存储着关于不同类型的实体及其不同类型关系的信息。本教程介绍了如何将异构图映射到PyG中,以及如何将其作为输入用于…

手机实时提取SIM卡打电话的信令声音-蓝牙电话如何适配eSIM卡的手机

手机实时提取SIM卡打电话的信令声音 --蓝牙电话如何适配eSIM卡的手机 一、前言 蓝牙电话的海外战略中&#xff0c;由于海外智能手机市场中政策的差异性&#xff0c;对内置eSIM卡的手机进行支持是非常合理的需求。Android系列手机中&#xff0c;无论是更换通信运营商&#xf…

QT6学习第五天 第一个QT Quick程序

QT6学习第五天 第一个QT Quick程序 概述创建Qt Quick程序使用Qt资源文件程序发布 概述 如果将程序的用户界面成为前端&#xff0c;程序的数据存储和逻辑业务成为后端&#xff0c;那么传统QT Widgets程序的前后端都是用C完成的。对于现代软件开发而言&#xff0c;前端演化速度远…

LabVIEW内燃机气道试验台测控系统

基于LabVIEW软件开发的内燃机气道试验台测控系统主要应用于内燃机气道的性能测试和数据分析&#xff0c;通过高精度的测控技术&#xff0c;有效提升内燃机的测试精度和数据处理能力。 项目背景 随着内燃机技术的发展&#xff0c;对其气道性能的精准测量需求日益增加。该系统通…

flutter底部导航栏中间按钮凸起,导航栏中间部分凹陷效果

关键代码: Scaffold中设置floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked和extendBody: true&#xff0c; BottomAppBar中设置shape: const CircularNotchedRectangle() Scaffold(extendBody: true,//body是否延伸脚手架底部&#xff0c;在底部导航…

108.【C语言】数据结构之二叉树查找值为x的节点

目录 1.题目 代码模板 2.分析 分类讨论各种情况 大概的框架 关键部分(继续递归)的详解 递归调用展开图 3.测试结果 其他写法 4.结论 5.注意事项 不推荐的写法 1.题目 查找值为x的节点并返回节点的地址 代码模板 typedef int BTDataType; typedef struct BinaryT…

十五、linux之搭建JavaEE环境

1 概述 如果需要在 Linux 下进行 JavaEE 的开发&#xff0c;我们需要安装如下软件 2 安装 JDK 安装步骤 mkdir /opt/jdk mkdir /opt/jdk通过 xftp6 上传到 /opt/jdk 下 cd /opt/jdk 解压 tar -zxvf jdk-8u261-linux-x64.tar.gz tar -zxvf jdk-8u261-linux-x64.tar.…

基于PHP的音乐网站的设计与实现

摘 要 本系统采用PHP编程语言和MySQL数据库技术搭载了Apache服务器&#xff0c;完成了基于PHP的音乐网站设计&#xff0c;通过此次毕 业论文的撰写我明白了对于论文的选题要精确&#xff0c;要明确&#xff0c;要有明确的见解&#xff0c;要有足够的论证和创意&#xff0c;必须…

mysql 触发器进入历史

一、触发器 MySQL 触发器&#xff08;Triggers&#xff09;是一种数据库对象&#xff0c;它与表关联&#xff0c;能在特定的事件&#xff08;如插入、更新或删除&#xff09;发生时自动执行一些指定的操作。使用触发器可以帮助我们自动维护数据库的完整性、一致性&#xff0c;…

Springboot项目搭建(8)-用户登出与个人中心修改

1.提要信息 1.1 catch和then方法 then和catch是JavaScript中Promise对象的两个方法&#xff0c;用于处理异步操作的成功&#xff08;成功回调&#xff09;和失败&#xff08;失败回调&#xff09;情况。这两个方法通常与async/await语法一起使用&#xff0c;但也可以单独使用…

【2024】使用Docker搭建redis sentinel哨兵模式集群全流程(包含部署、测试、错误点指正以及直接部署)

目录&#x1f4bb; 前言**Docker Compose介绍**最终实现效果 一、搭建集群1、创建文件结构2、创建redis节点3、验证节点4、创建sentinel哨兵5、验证Sentinel功能 二、spring连接1、添加依赖2、添加配置3、启动测试 三、直接部署流程1、拉取配置2、修改端口创建 前言 本篇文章主…

Python毕业设计选题:基于django+vue的智慧社区可视化平台的设计与实现+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 养老机构管理 业主管理 社区安防管理 社区设施管理 车位…

webpack 项目访问静态资源

使用 webpack dev serve 启动 react 项目后&#xff0c;发现无法使用 http://localhost:8080/1.png 访问到项目的 /static 目录下的 1.png 文件。我的 webpack-dev.js 配置如下&#xff1a; const webpack require(webpack) const webpackMerge require(webpack-merge) cons…

【FAQ】使用Node.js 镜像 构建本地项目

在nodejs官方并没有提供使用node.js构建本地项目的方法&#xff0c;但是通过阅读官方文档&#xff0c;可以发现&#xff0c;官方在包管理器界面提供了如下语句 所以node.js容器是可以执行语句的 下面通过docker 的 -w 、-v 参数设置容器工作目录和目录映射&#xff08;实现本…

MySQL技巧之跨服务器数据查询:进阶篇-从A服务器的MySQ数据库复制到B服务器的SQL Server数据库的表中

MySQL技巧之跨服务器数据查询&#xff1a;进阶篇-从A服务器的MySQ数据库复制到B服务器的SQL Server数据库的表中 基础篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MyS…

Flutter 指纹识别

在这篇博客中&#xff0c;我们将介绍如何使用 Flutter 的 local_auth 插件在 Android 和 iOS 设备上实现指纹识别功能。通过这一步一步的实现&#xff0c;我们将学习如何检查设备是否支持生物识别、如何触发指纹验证&#xff0c;并处理可能出现的错误。 效果图&#xff08;因为…

CentOS 9 配置静态IP

文章目录 1_问题原因2_nmcli 配置静态IP3_使用配置文件固定IP4_重启后存在的问题5_nmcli 补充 1_问题原因 CentOS 7 于 2014年6月发布&#xff0c;基于 RHEL 7&#xff0c;并在 2024年6月30日 结束维护。 CentOS 9 作为目前的最新版本&#xff0c;今天闲来闲来无事下载下来后…