欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Batch批處理框架操作指南

 更新時(shí)間:2022年07月20日 17:09:45   作者:石杉的架構(gòu)筆記  
Spring?Batch?是?Spring?提供的一個(gè)數(shù)據(jù)處理框架。企業(yè)域中的許多應(yīng)用程序需要批量處理才能在關(guān)鍵任務(wù)環(huán)境中執(zhí)行業(yè)務(wù)操作,這篇文章主要介紹了Spring?Batch批處理框架操作指南,需要的朋友可以參考下

簡(jiǎn)介

Spring Batch 是 Spring 提供的一個(gè)數(shù)據(jù)處理框架。企業(yè)域中的許多應(yīng)用程序需要批量處理才能在關(guān)鍵任務(wù)環(huán)境中執(zhí)行業(yè)務(wù)操作。

這些業(yè)務(wù)運(yùn)營(yíng)包括:

  • 無(wú)需用戶交互即可最有效地處理大量信息的自動(dòng)化,復(fù)雜處理。這些操作通常包括基于時(shí)間的事件(例如月末計(jì)算,通知或通信)。

  • 在非常大的數(shù)據(jù)集中重復(fù)處理復(fù)雜業(yè)務(wù)規(guī)則的定期應(yīng)用(例如,保險(xiǎn)利益確定或費(fèi)率調(diào)整)。

  • 集成從內(nèi)部和外部系統(tǒng)接收的信息,這些信息通常需要以事務(wù)方式格式化,驗(yàn)證和處理到記錄系統(tǒng)中。批處理用于每天為企業(yè)處理數(shù)十億的交易。

Spring Batch 是一個(gè)輕量級(jí),全面的批處理框架,旨在開(kāi)發(fā)對(duì)企業(yè)系統(tǒng)日常運(yùn)營(yíng)至關(guān)重要的強(qiáng)大批處理應(yīng)用程序。

Spring Batch 構(gòu)建了人們期望的 Spring Framework 特性(生產(chǎn)力,基于 POJO 的開(kāi)發(fā)方法和一般易用性),同時(shí)使開(kāi)發(fā)人員可以在必要時(shí)輕松訪問(wèn)和利用更高級(jí)的企業(yè)服務(wù)。Spring Batch 不是一個(gè) schuedling 的框架。

Spring Batch 提供了可重用的功能,這些功能對(duì)于處理大量的數(shù)據(jù)至關(guān)重要,包括記錄/跟蹤,事務(wù)管理,作業(yè)處理統(tǒng)計(jì),作業(yè)重啟,跳過(guò)和資源管理。

它還提供更高級(jí)的技術(shù)服務(wù)和功能,通過(guò)優(yōu)化和分區(qū)技術(shù)實(shí)現(xiàn)極高容量和高性能的批處理作業(yè)。

Spring Batch 可用于兩種簡(jiǎn)單的用例(例如將文件讀入數(shù)據(jù)庫(kù)或運(yùn)行存儲(chǔ)過(guò)程)以及復(fù)雜的大量用例(例如在數(shù)據(jù)庫(kù)之間移動(dòng)大量數(shù)據(jù),轉(zhuǎn)換它等等) 上)。大批量批處理作業(yè)可以高度可擴(kuò)展的方式利用該框架來(lái)處理大量信息。

Spring Batch 架構(gòu)

一個(gè)典型的批處理應(yīng)用程序大致如下:

  • 從數(shù)據(jù)庫(kù),文件或隊(duì)列中讀取大量記錄。

  • 以某種方式處理數(shù)據(jù)。

  • 以修改之后的形式寫(xiě)回?cái)?shù)據(jù)。

其對(duì)應(yīng)的示意圖如下:

Spring Batch 的一個(gè)總體的架構(gòu)如下:

在 Spring Batch 中一個(gè) job 可以定義很多的步驟 step,在每一個(gè) step 里面可以定義其專(zhuān)屬的 ItemReader 用于讀取數(shù)據(jù)。

ItemProcesseor 用于處理數(shù)據(jù),ItemWriter 用于寫(xiě)數(shù)據(jù),而每一個(gè)定義的 job 則都在 JobRepository 里面,我們可以通過(guò) JobLauncher 來(lái)啟動(dòng)某一個(gè) job。

Spring Batch 核心概念

下面是一些概念是 Spring Batch 框架中的核心概念。

什么是 Job

Job 和 Step 是 Spring Batch 執(zhí)行批處理任務(wù)最為核心的兩個(gè)概念。

其中 Job 是一個(gè)封裝整個(gè)批處理過(guò)程的一個(gè)概念。Job 在 Spring Batch 的體系當(dāng)中只是一個(gè)最頂層的一個(gè)抽象概念,體現(xiàn)在代碼當(dāng)中則它只是一個(gè)最上層的接口。

其代碼如下:

/**
 * Batch domain object representing a job. Job is an explicit abstraction
 * representing the configuration of a job specified by a developer. It should
 * be noted that restart policy is applied to the job as a whole and not to a
 * step.
 */
public interface Job {
 String getName();
 boolean isRestartable();
 void execute(JobExecution execution);
 JobParametersIncrementer getJobParametersIncrementer();
 JobParametersValidator getJobParametersValidator();
}

在 Job 這個(gè)接口當(dāng)中定義了五個(gè)方法,它的實(shí)現(xiàn)類(lèi)主要有兩種類(lèi)型的 job,一個(gè)是 simplejob,另一個(gè)是 flowjob。

在 Spring Batch 當(dāng)中,job 是最頂層的抽象,除 job 之外我們還有 JobInstance 以及 JobExecution 這兩個(gè)更加底層的抽象。

一個(gè) job 是我們運(yùn)行的基本單位,它內(nèi)部由 step 組成。job 本質(zhì)上可以看成 step 的一個(gè)容器。

一個(gè) job 可以按照指定的邏輯順序組合 step,并提供了我們給所有 step 設(shè)置相同屬性的方法,例如一些事件監(jiān)聽(tīng),跳過(guò)策略。

Spring Batch 以 SimpleJob 類(lèi)的形式提供了 Job 接口的默認(rèn)簡(jiǎn)單實(shí)現(xiàn),它在 Job 之上創(chuàng)建了一些標(biāo)準(zhǔn)功能。

一個(gè)使用 java config 的例子代碼如下:

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

這個(gè)配置的意思是:首先給這個(gè) job 起了一個(gè)名字叫 footballJob,接著指定了這個(gè) job 的三個(gè) step,他們分別由方法 playerLoad,gameLoad,playerSummarization 實(shí)現(xiàn)。

什么是 JobInstance

我們?cè)谏衔囊呀?jīng)提到了 JobInstance,他是 Job 的更加底層的一個(gè)抽象,他的定義如下:

public interface JobInstance {
 /**
  * Get unique id for this JobInstance.
  * @return instance id
  */
 public long getInstanceId();
 /**
  * Get job name.
  * @return value of 'id' attribute from <job>
  */
 public String getJobName(); 
}

他的方法很簡(jiǎn)單,一個(gè)是返回 Job 的 id,另一個(gè)是返回 Job 的名字。

JobInstance 指的是 job 運(yùn)行當(dāng)中,作業(yè)執(zhí)行過(guò)程當(dāng)中的概念。Instance 本就是實(shí)例的意思。

比如說(shuō)現(xiàn)在有一個(gè)批處理的 job,它的功能是在一天結(jié)束時(shí)執(zhí)行行一次。我們假定這個(gè)批處理 job 的名字為 'EndOfDay'。

在這個(gè)情況下,那么每天就會(huì)有一個(gè)邏輯意義上的 JobInstance,而我們必須記錄 job 的每次運(yùn)行的情況。

什么是 JobParameters

在上文當(dāng)中我們提到了,同一個(gè) job 每天運(yùn)行一次的話,那么每天都有一個(gè) jobIntsance,但他們的 job 定義都是一樣的,那么我們?cè)趺磥?lái)區(qū)別一個(gè) job 的不同 jobinstance 了。

不妨先做個(gè)猜想,雖然 jobinstance 的 job 定義一樣,但是他們有的東西就不一樣,例如運(yùn)行時(shí)間。

Spring Batch 中提供的用來(lái)標(biāo)識(shí)一個(gè) jobinstance 的東西是:JobParameters。

JobParameters 對(duì)象包含一組用于啟動(dòng)批處理作業(yè)的參數(shù),它可以在運(yùn)行期間用于識(shí)別或甚至用作參考數(shù)據(jù)。我們假設(shè)的運(yùn)行時(shí)間,就可以作為一個(gè) JobParameters。

例如,我們前面的 'EndOfDay' 的 job 現(xiàn)在已經(jīng)有了兩個(gè)實(shí)例,一個(gè)產(chǎn)生于 1 月 1 日,另一個(gè)產(chǎn)生于 1 月 2 日,那么我們就可以定義兩個(gè) JobParameter 對(duì)象:一個(gè)的參數(shù)是 01-01,, 另一個(gè)的參數(shù)是 01-02。

因此,識(shí)別一個(gè) JobInstance 的方法可以定義為:

因此,我么可以通過(guò) Jobparameter 來(lái)操作正確的 JobInstance。

什么是 JobExecution

JobExecution 指的是單次嘗試運(yùn)行一個(gè)我們定義好的 Job 的代碼層面的概念。job 的一次執(zhí)行可能以失敗也可能成功。只有當(dāng)執(zhí)行成功完成時(shí),給定的與執(zhí)行相對(duì)應(yīng)的 JobInstance 才也被視為完成。

還是以前面描述的 EndOfDay 的 job 作為示例,假設(shè)第一次運(yùn)行 01-01-2019 的 JobInstance 結(jié)果是失敗。

那么此時(shí)如果使用與第一次運(yùn)行相同的 Jobparameter 參數(shù)(即 01-01-2019)作業(yè)參數(shù)再次運(yùn)行,那么就會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)于之前 jobInstance 的一個(gè)新的 JobExecution 實(shí)例,JobInstance 仍然只有一個(gè)。

JobExecution 的接口定義如下:

public interface JobExecution {
 /**
  * Get unique id for this JobExecution.
  * @return execution id
  */
 public long getExecutionId();
 /**
  * Get job name.
  * @return value of 'id' attribute from <job>
  */
 public String getJobName(); 
 /**
  * Get batch status of this execution.
  * @return batch status value.
  */
 public BatchStatus getBatchStatus();
 /**
  * Get time execution entered STARTED status. 
  * @return date (time)
  */
 public Date getStartTime();
 /**
  * Get time execution entered end status: COMPLETED, STOPPED, FAILED 
  * @return date (time)
  */
 public Date getEndTime();
 /**
  * Get execution exit status.
  * @return exit status.
  */
 public String getExitStatus();
 /**
  * Get time execution was created.
  * @return date (time)
  */
 public Date getCreateTime();
 /**
  * Get time execution was last updated updated.
  * @return date (time)
  */
 public Date getLastUpdatedTime();
 /**
  * Get job parameters for this execution.
  * @return job parameters  
  */
 public Properties getJobParameters();

}

每一個(gè)方法的注釋已經(jīng)解釋的很清楚,這里不再多做解釋。只提一下 BatchStatus,JobExecution 當(dāng)中提供了一個(gè)方法 getBatchStatus 用于獲取一個(gè) job 某一次特地執(zhí)行的一個(gè)狀態(tài)。

BatchStatus 是一個(gè)代表 job 狀態(tài)的枚舉類(lèi),其定義如下:

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

這些屬性對(duì)于一個(gè) job 的執(zhí)行來(lái)說(shuō)是非常關(guān)鍵的信息,并且 Spring Batch 會(huì)將他們持久到數(shù)據(jù)庫(kù)當(dāng)中。

在使用 Spring Batch 的過(guò)程當(dāng)中 Spring Batch 會(huì)自動(dòng)創(chuàng)建一些表用于存儲(chǔ)一些 job 相關(guān)的信息,用于存儲(chǔ) JobExecution 的表為 batch_job_execution。

下面是一個(gè)從數(shù)據(jù)庫(kù)當(dāng)中截圖的實(shí)例:

什么是 Step

每一個(gè) Step 對(duì)象都封裝了批處理作業(yè)的一個(gè)獨(dú)立的階段。事實(shí)上,每一個(gè) Job 本質(zhì)上都是由一個(gè)或多個(gè)步驟組成。每一個(gè) step 包含定義和控制實(shí)際批處理所需的所有信息。

任何特定的內(nèi)容都由編寫(xiě) Job 的開(kāi)發(fā)人員自行決定。一個(gè) step 可以非常簡(jiǎn)單也可以非常復(fù)雜。

例如,一個(gè) step 的功能是將文件中的數(shù)據(jù)加載到數(shù)據(jù)庫(kù)中,那么基于現(xiàn)在 Spring Batch 的支持則幾乎不需要寫(xiě)代碼。更復(fù)雜的 step 可能具有復(fù)雜的業(yè)務(wù)邏輯,這些邏輯作為處理的一部分。

與 Job 一樣,Step 具有與 JobExecution 類(lèi)似的 StepExecution,如下圖所示:

什么是 StepExecution

StepExecution 表示一次執(zhí)行 Step,每次運(yùn)行一個(gè) Step 時(shí)都會(huì)創(chuàng)建一個(gè)新的 StepExecution,類(lèi)似于 JobExecution。

但是,某個(gè)步驟可能由于其之前的步驟失敗而無(wú)法執(zhí)行。且僅當(dāng) Step 實(shí)際啟動(dòng)時(shí)才會(huì)創(chuàng)建 StepExecution。

一次 step 執(zhí)行的實(shí)例由 StepExecution 類(lèi)的對(duì)象表示。每個(gè) StepExecution 都包含對(duì)其相應(yīng)步驟的引用以及 JobExecution 和事務(wù)相關(guān)的數(shù)據(jù),例如提交和回滾計(jì)數(shù)以及開(kāi)始和結(jié)束時(shí)間。

此外,每個(gè)步驟執(zhí)行都包含一個(gè) ExecutionContext,其中包含開(kāi)發(fā)人員需要在批處理運(yùn)行中保留的任何數(shù)據(jù),例如重新啟動(dòng)所需的統(tǒng)計(jì)信息或狀態(tài)信息。

下面是一個(gè)從數(shù)據(jù)庫(kù)當(dāng)中截圖的實(shí)例:

什么是 ExecutionContext

ExecutionContext 即每一個(gè) StepExecution 的執(zhí)行環(huán)境。它包含一系列的鍵值對(duì)。

我們可以用如下代碼獲取 ExecutionContext:

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

什么是 JobRepository

JobRepository 是一個(gè)用于將上述 job,step 等概念進(jìn)行持久化的一個(gè)類(lèi)。它同時(shí)給 Job 和 Step 以及下文會(huì)提到的 JobLauncher 實(shí)現(xiàn)提供 CRUD 操作。

首次啟動(dòng) Job 時(shí),將從 repository 中獲取 JobExecution,并且在執(zhí)行批處理的過(guò)程中,StepExecution 和 JobExecution 將被存儲(chǔ)到 repository 當(dāng)中。

@EnableBatchProcessing 注解可以為 JobRepository 提供自動(dòng)配置。

什么是 JobLauncher

JobLauncher 這個(gè)接口的功能非常簡(jiǎn)單,它是用于啟動(dòng)指定了 JobParameters 的 Job,為什么這里要強(qiáng)調(diào)指定了 JobParameter,原因其實(shí)我們?cè)谇懊嬉呀?jīng)提到了,jobparameter 和 job 一起才能組成一次 job 的執(zhí)行。

下面是代碼實(shí)例:

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

上面 run 方法實(shí)現(xiàn)的功能是根據(jù)傳入的 job 以及 jobparamaters 從 JobRepository 獲取一個(gè) JobExecution 并執(zhí)行 Job。

什么是 Item Reader

ItemReader 是一個(gè)讀數(shù)據(jù)的抽象,它的功能是為每一個(gè) Step 提供數(shù)據(jù)輸入。當(dāng) ItemReader 以及讀完所有數(shù)據(jù)時(shí),它會(huì)返回 null 來(lái)告訴后續(xù)操作數(shù)據(jù)已經(jīng)讀完。

Spring Batch 為 ItemReader 提供了非常多的有用的實(shí)現(xiàn)類(lèi),比如 JdbcPagingItemReader,JdbcCursorItemReader 等等。

ItemReader 支持的讀入的數(shù)據(jù)源也是非常豐富的,包括各種類(lèi)型的數(shù)據(jù)庫(kù),文件,數(shù)據(jù)流,等等。幾乎涵蓋了我們的所有場(chǎng)景。

下面是一個(gè) JdbcPagingItemReader 的例子代碼:

@Bean
public JdbcPagingItemReader itemReader(DataSource dataSource, PagingQueryProvider queryProvider) {
        Map<String, Object> parameterValues = new HashMap<>();
        parameterValues.put("status", "NEW");

        return new JdbcPagingItemReaderBuilder<CustomerCredit>()
               .name("creditReader")
               .dataSource(dataSource)
               .queryProvider(queryProvider)
               .parameterValues(parameterValues)
               .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 必須指定一個(gè) PagingQueryProvider,負(fù)責(zé)提供 SQL 查詢語(yǔ)句來(lái)按分頁(yè)返回?cái)?shù)據(jù)。

下面是一個(gè) JdbcCursorItemReader 的例子代碼:

private JdbcCursorItemReader<Map<String, Object>> buildItemReader(final DataSource dataSource, String tableName,
            String tenant) {

        JdbcCursorItemReader<Map<String, Object>> itemReader = new JdbcCursorItemReader<>();
        itemReader.setDataSource(dataSource);
        itemReader.setSql("sql here");
        itemReader.setRowMapper(new RowMapper());
        return itemReader;
    }

什么是 Item Writer

既然 ItemReader 是讀數(shù)據(jù)的一個(gè)抽象,那么 ItemWriter 自然就是一個(gè)寫(xiě)數(shù)據(jù)的抽象,它是為每一個(gè) step 提供數(shù)據(jù)寫(xiě)出的功能。

寫(xiě)的單位是可以配置的,我們可以一次寫(xiě)一條數(shù)據(jù),也可以一次寫(xiě)一個(gè) chunk 的數(shù)據(jù),關(guān)于 chunk 下文會(huì)有專(zhuān)門(mén)的介紹。ItemWriter 對(duì)于讀入的數(shù)據(jù)是不能做任何操作的。

Spring Batch 為 ItemWriter 也提供了非常多的有用的實(shí)現(xiàn)類(lèi),當(dāng)然我們也可以去實(shí)現(xiàn)自己的 writer 功能。

什么是 Item Processor

ItemProcessor 對(duì)項(xiàng)目的業(yè)務(wù)邏輯處理的一個(gè)抽象,當(dāng) ItemReader 讀取到一條記錄之后,ItemWriter 還未寫(xiě)入這條記錄之前,I 我們可以借助 temProcessor 提供一個(gè)處理業(yè)務(wù)邏輯的功能,并對(duì)數(shù)據(jù)進(jìn)行相應(yīng)操作。

如果我們?cè)?ItemProcessor 發(fā)現(xiàn)一條數(shù)據(jù)不應(yīng)該被寫(xiě)入,可以通過(guò)返回 null 來(lái)表示。

ItemProcessor 和 ItemReader 以及 ItemWriter 可以非常好的結(jié)合在一起工作,他們之間的數(shù)據(jù)傳輸也非常方便。我們直接使用即可。

chunk 處理流程

Spring Batch 提供了讓我們按照 chunk 處理數(shù)據(jù)的能力,一個(gè) chunk 的示意圖如下:

它的意思就和圖示的一樣,由于我們一次batch的任務(wù)可能會(huì)有很多的數(shù)據(jù)讀寫(xiě)操作,因此一條一條的處理并向數(shù)據(jù)庫(kù)提交的話效率不會(huì)很高。

因此 Spring Batch 提供了 chunk 這個(gè)概念,我們可以設(shè)定一個(gè) chunk size,spring batch 將一條一條處理數(shù)據(jù),但不提交到數(shù)據(jù)庫(kù),只有當(dāng)處理的數(shù)據(jù)數(shù)量達(dá)到 chunk size 設(shè)定的值得時(shí)候,才一起去 commit。

java 的實(shí)例定義代碼如下:

在上面這個(gè) step 里面,chunk size 被設(shè)為了 10,當(dāng) ItemReader 讀的數(shù)據(jù)數(shù)量達(dá)到 10 的時(shí)候,這一批次的數(shù)據(jù)就一起被傳到 itemWriter,同時(shí) transaction 被提交。

skip 策略和失敗處理

一個(gè) batch 的 job 的 step,可能會(huì)處理非常大數(shù)量的數(shù)據(jù),難免會(huì)遇到出錯(cuò)的情況,出錯(cuò)的情況雖出現(xiàn)的概率較小,但是我們不得不考慮這些情況,因?yàn)槲覀冏鰯?shù)據(jù)遷移最重要的是要保證數(shù)據(jù)的最終一致性。

Spring Batch 當(dāng)然也考慮到了這種情況,并且為我們提供了相關(guān)的技術(shù)支持,請(qǐng)看如下 bean 的配置:

我們需要留意這三個(gè)方法,分別是 skipLimit(),skip(),noSkip()。

skipLimit 方法的意思是我們可以設(shè)定一個(gè)我們?cè)试S的這個(gè) step 可以跳過(guò)的異常數(shù)量,假如我們?cè)O(shè)定為 10,則當(dāng)這個(gè) step 運(yùn)行時(shí),只要出現(xiàn)的異常數(shù)目不超過(guò) 10,整個(gè) step 都不會(huì) fail。

注意,若不設(shè)定 skipLimit,則其默認(rèn)值是 0。

skip 方法我們可以指定我們可以跳過(guò)的異常,因?yàn)橛行┊惓5某霈F(xiàn),我們是可以忽略的。

noSkip 方法的意思則是指出現(xiàn)這個(gè)異常我們不想跳過(guò),也就是從 skip 的所以 exception 當(dāng)中排除這個(gè) exception。

從上面的例子來(lái)說(shuō),也就是跳過(guò)所有除 FileNotFoundException 的 exception。

那么對(duì)于這個(gè) step 來(lái)說(shuō),F(xiàn)ileNotFoundException 就是一個(gè) fatal 的 exception,拋出這個(gè) exception 的時(shí)候 step 就會(huì)直接 fail。

批處理操作指南

本部分是一些使用 Spring Batch 時(shí)的值得注意的點(diǎn)。

批處理原則

在構(gòu)建批處理解決方案時(shí),應(yīng)考慮以下關(guān)鍵原則和注意事項(xiàng):

  • 批處理體系結(jié)構(gòu)通常會(huì)影響體系結(jié)構(gòu)

  • 盡可能簡(jiǎn)化并避免在單批應(yīng)用程序中構(gòu)建復(fù)雜的邏輯結(jié)構(gòu)

  • 保持?jǐn)?shù)據(jù)的處理和存儲(chǔ)在物理上靠得很近(換句話說(shuō),將數(shù)據(jù)保存在處理過(guò)程中)。

  • 最大限度地減少系統(tǒng)資源的使用,尤其是 I/O。在 internal memory 中執(zhí)行盡可能多的操作。

  • 查看應(yīng)用程序 I/O(分析 SQL 語(yǔ)句)以確保避免不必要的物理 I/O。特別是,需要尋找以下四個(gè)常見(jiàn)缺陷:當(dāng)數(shù)據(jù)可以被讀取一次并緩存或保存在工作存儲(chǔ)中時(shí),讀取每個(gè)事務(wù)的數(shù)據(jù);重新讀取先前在同一事務(wù)中讀取數(shù)據(jù)的事務(wù)的數(shù)據(jù);導(dǎo)致不必要的表或索引掃描;未在 SQL 語(yǔ)句的 WHERE 子句中指定鍵值。

  • 在批處理運(yùn)行中不要做兩次一樣的事情。例如,如果需要數(shù)據(jù)匯總以用于報(bào)告目的,則應(yīng)該(如果可能)在最初處理數(shù)據(jù)時(shí)遞增存儲(chǔ)的總計(jì),因此您的報(bào)告應(yīng)用程序不必重新處理相同的數(shù)據(jù)。

  • 在批處理應(yīng)用程序開(kāi)始時(shí)分配足夠的內(nèi)存,以避免在此過(guò)程中進(jìn)行耗時(shí)的重新分配。

  • 總是假設(shè)數(shù)據(jù)完整性最差。插入適當(dāng)?shù)臋z查和記錄驗(yàn)證以維護(hù)數(shù)據(jù)完整性。

  • 盡可能實(shí)施校驗(yàn)和以進(jìn)行內(nèi)部驗(yàn)證。例如,對(duì)于一個(gè)文件里的數(shù)據(jù)應(yīng)該有一個(gè)數(shù)據(jù)條數(shù)紀(jì)錄,告訴文件中的記錄總數(shù)以及關(guān)鍵字段的匯總。

  • 在具有真實(shí)數(shù)據(jù)量的類(lèi)似生產(chǎn)環(huán)境中盡早計(jì)劃和執(zhí)行壓力測(cè)試。

  • 在大批量系統(tǒng)中,數(shù)據(jù)備份可能具有挑戰(zhàn)性,特別是如果系統(tǒng)以 24-7 在線的情況運(yùn)行。數(shù)據(jù)庫(kù)備份通常在在線設(shè)計(jì)中得到很好的處理,但文件備份應(yīng)該被視為同樣重要。如果系統(tǒng)依賴于文件,則文件備份過(guò)程不僅應(yīng)該到位并記錄在案,還應(yīng)定期進(jìn)行測(cè)試。

如何默認(rèn)不啟動(dòng) job

在使用 java config 使用 Spring Batch 的 job 時(shí),如果不做任何配置,項(xiàng)目在啟動(dòng)時(shí)就會(huì)默認(rèn)去跑我們定義好的批處理 job。那么如何讓項(xiàng)目在啟動(dòng)時(shí)不自動(dòng)去跑 job 呢?

Spring Batch 的 job 會(huì)在項(xiàng)目啟動(dòng)時(shí)自動(dòng) run,如果我們不想讓他在啟動(dòng)時(shí) run 的話,可以在 application.properties 中添加如下屬性:

spring.batch.job.enabled=false

在讀數(shù)據(jù)時(shí)內(nèi)存不夠

在使用 Spring Batch 做數(shù)據(jù)遷移時(shí),發(fā)現(xiàn)在 job 啟動(dòng)后,執(zhí)行到一定時(shí)間點(diǎn)時(shí)就卡在一個(gè)地方不動(dòng)了,且 log 也不再打印,等待一段時(shí)間之后,得到如下錯(cuò)誤:

紅字的信息為:Resource exhaustion event:the JVM was unable to allocate memory from the heap.

翻譯過(guò)來(lái)的意思就是項(xiàng)目發(fā)出了一個(gè)資源耗盡的事件,告訴我們 java 虛擬機(jī)無(wú)法再為堆分配內(nèi)存。

造成這個(gè)錯(cuò)誤的原因是:這個(gè)項(xiàng)目里的 batch job 的 reader 是一次性拿回了數(shù)據(jù)庫(kù)里的所有數(shù)據(jù),并沒(méi)有進(jìn)行分頁(yè),當(dāng)這個(gè)數(shù)據(jù)量太大時(shí),就會(huì)導(dǎo)致內(nèi)存不夠用。

解決的辦法有兩個(gè):

  • 調(diào)整 reader 讀數(shù)據(jù)邏輯,按分頁(yè)讀取,但實(shí)現(xiàn)上會(huì)麻煩一些,且運(yùn)行效率會(huì)下降

  • 增大 service 內(nèi)存

到此這篇關(guān)于Spring Batch批處理框架操作指南的文章就介紹到這了,更多相關(guān)Spring Batch批處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java如何處理數(shù)據(jù)成為樹(shù)狀結(jié)構(gòu)

    Java如何處理數(shù)據(jù)成為樹(shù)狀結(jié)構(gòu)

    這篇文章主要介紹了Java如何處理數(shù)據(jù)成為樹(shù)狀結(jié)構(gòu)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 深入學(xué)習(xí)Java 熱部署的知識(shí)

    深入學(xué)習(xí)Java 熱部署的知識(shí)

    對(duì)于Java應(yīng)用程序來(lái)說(shuō),熱部署就是在運(yùn)行時(shí)更新Java類(lèi)文件。在基于Java的應(yīng)用服務(wù)器實(shí)現(xiàn)熱部署的過(guò)程中,類(lèi)裝入器扮演著重要的角色。大多數(shù)基于Java的應(yīng)用服務(wù)器,包括EJB服務(wù)器和Servlet容器,都支持熱部署。,需要的朋友可以參考下
    2019-06-06
  • Java實(shí)現(xiàn)Web應(yīng)用中的定時(shí)任務(wù)(實(shí)例講解)

    Java實(shí)現(xiàn)Web應(yīng)用中的定時(shí)任務(wù)(實(shí)例講解)

    下面小編就為大家分享一篇Java實(shí)現(xiàn)Web 應(yīng)用中的定時(shí)任務(wù)的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • SpringBoot2零基礎(chǔ)到精通之異常處理與web原生組件注入

    SpringBoot2零基礎(chǔ)到精通之異常處理與web原生組件注入

    SpringBoot是Spring全家桶的成員之一,基于約定優(yōu)于配置的思想(即有約定默認(rèn)值,在不配置的情況下會(huì)使用默認(rèn)值,在配置文件下配置的話會(huì)使用配置的值)。SpringBoot是一種整合Spring技術(shù)棧的方式(或者說(shuō)是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開(kāi)發(fā)的腳手架
    2022-03-03
  • Java都有哪些創(chuàng)建線程的方法

    Java都有哪些創(chuàng)建線程的方法

    這篇文章主要介紹了Java都有哪些創(chuàng)建線程的方法,文章分享Java創(chuàng)建線程得幾種方法及推薦使用哪種方法,下面詳細(xì)內(nèi)容需要的小伙伴可以參考一下
    2022-05-05
  • m1 Mac設(shè)置多jdk版本并動(dòng)態(tài)切換的實(shí)現(xiàn)

    m1 Mac設(shè)置多jdk版本并動(dòng)態(tài)切換的實(shí)現(xiàn)

    本文主要介紹 Mac 下如何安裝 JDK 并且多版本如何切換,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Maven項(xiàng)目中讀取src/main/resources目錄下的配置文件的方法

    Maven項(xiàng)目中讀取src/main/resources目錄下的配置文件的方法

    本篇文章主要介紹了Maven項(xiàng)目中讀取src/main/resources目錄下的配置文件的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • javaweb圖書(shū)商城設(shè)計(jì)之圖書(shū)模塊(4)

    javaweb圖書(shū)商城設(shè)計(jì)之圖書(shū)模塊(4)

    這篇文章主要介紹了javaweb圖書(shū)商城設(shè)計(jì)之圖書(shū)模塊的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 使用@CacheEvict清除指定下所有緩存

    使用@CacheEvict清除指定下所有緩存

    這篇文章主要介紹了使用@CacheEvict清除指定下所有緩存,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java分治法與二分搜索算法實(shí)例分析

    Java分治法與二分搜索算法實(shí)例分析

    這篇文章主要介紹了Java分治法與二分搜索算法,簡(jiǎn)單講述了分治法與二分搜索算法的原理并結(jié)合java實(shí)例分析了二分搜索算法的實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2017-11-11

最新評(píng)論