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

spring batch使用reader讀數(shù)據(jù)的內(nèi)存容量問題詳解

 更新時(shí)間:2020年07月20日 17:17:28   作者:topEngineerray  
這篇文章主要介紹了spring batch使用reader讀數(shù)據(jù)的內(nèi)存容量問題詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

概述

本篇博客是記錄使用spring batch做數(shù)據(jù)遷移時(shí)時(shí)遇到的一個(gè)關(guān)鍵問題:數(shù)據(jù)遷移量大時(shí)如何保證內(nèi)存。當(dāng)我們?cè)谑褂胹pring batch時(shí),我們必須配置三個(gè)東西: reader,processor,和writer。其中,reader用于從數(shù)據(jù)庫(kù)中讀數(shù)據(jù),當(dāng)數(shù)據(jù)量較小時(shí),reader的邏輯不會(huì)對(duì)內(nèi)存帶來太多壓力,但是當(dāng)我們要去讀的數(shù)據(jù)量非常大的時(shí)候,我們就不得不考慮內(nèi)存等方面的問題,因?yàn)槿魯?shù)據(jù)量非常大,內(nèi)存,執(zhí)行時(shí)間等等都會(huì)受到影響。關(guān)于spring batch的基礎(chǔ)知識(shí)和介紹請(qǐng)參考這篇博客:批處理框架spring batch介紹及使用。

問題是什么

在上面的內(nèi)容當(dāng)中我們已經(jīng)提到了,我們面臨的問題是數(shù)據(jù)遷移量大時(shí)的內(nèi)存問題。但是這樣的描述非?;\統(tǒng),因此博主決定將這一部分單獨(dú)拎出來說。

在學(xué)習(xí)了spring batch的知識(shí)之后我們應(yīng)該很清楚的一點(diǎn)是,每一個(gè)spring batch的step都包含如下的部分:

即讀數(shù)據(jù),處理數(shù)據(jù),寫數(shù)據(jù)。這三個(gè)步驟里面最可能會(huì)導(dǎo)致內(nèi)存變大問題的無疑是讀數(shù)據(jù)環(huán)節(jié)。讀數(shù)據(jù)作為spring batch的數(shù)據(jù)輸入,是整個(gè)spring batch job的開頭邏輯。

若我們的數(shù)據(jù)量不大,如只有幾十萬條,那我們無疑不會(huì)面臨內(nèi)存問題,即便一次將所有數(shù)據(jù)加載到內(nèi)存當(dāng)中,占的內(nèi)存也不會(huì)非常多,且spring batch數(shù)據(jù)遷移的速度非常之快,幾十萬條的數(shù)據(jù)往往是幾十秒的時(shí)間就可以遷移完成。但是當(dāng)數(shù)據(jù)量變大之后,問題就不一樣了。當(dāng)我們的數(shù)據(jù)量達(dá)到數(shù)百萬或上千萬時(shí),若一次性將所有數(shù)據(jù)全部讀到內(nèi)存當(dāng)中,則會(huì)占據(jù)遠(yuǎn)遠(yuǎn)超出正常范圍的非常大的內(nèi)存。該問題示意圖如下所示:

我們寫的任何程序都會(huì)有一個(gè)運(yùn)行內(nèi)存,假設(shè)這個(gè)內(nèi)存的總?cè)萘楷F(xiàn)在只有4g,而我們數(shù)據(jù)庫(kù)里需要操作的數(shù)據(jù)有8g,那么無疑,一次性的將數(shù)據(jù)讀出來就會(huì)出錯(cuò)。這便是需要考慮得問題。

Spring提供的reader實(shí)現(xiàn)

spring提供了非常豐富的Reader實(shí)現(xiàn),其中比較常用的從數(shù)據(jù)庫(kù)讀數(shù)據(jù)的有JdbcCursorItemReader,JdbcPagingItemReader等。

JdbcCursorItemReader

使用JdbcCursorItemReader的示例代碼如下:

@Bean
public JdbcCursorItemReader<CustomerCredit> itemReader() {
 return new JdbcCursorItemReaderBuilder<CustomerCredit>()
   .dataSource(this.dataSource)
   .name("creditReader")
   .sql("select ID, NAME, CREDIT from CUSTOMER")
   .rowMapper(new CustomerCreditRowMapper())
   .build();
 
}

JdbcCursorItemReader的好處在于使用簡(jiǎn)單,但是我們從它的sql就能發(fā)現(xiàn),JdbcCursorItemReader會(huì)一次把所有的數(shù)據(jù)全部拿回來,當(dāng)數(shù)據(jù)量過大而服務(wù)器內(nèi)存不夠時(shí),就會(huì)遇到下面無法分配內(nèi)存的問題:

報(bào)錯(cuò)信息為:Resource exhaustion event:The JVM was unable to allocate memory from the heap. 意思就是需要分配內(nèi)存的數(shù)據(jù)太多,但是無法找到足夠的內(nèi)存了。

反映在內(nèi)存里,堆內(nèi)存會(huì)呈現(xiàn)出如下的情況:

隨著每一次數(shù)據(jù)讀入,堆內(nèi)存都會(huì)增大,原因就在于JdbcCursorItemReader一次性讀回了所有的數(shù)據(jù),返回之后就會(huì)存在一個(gè)對(duì)象里面,而這個(gè)對(duì)象的尺寸過大,因此直接進(jìn)入了老年代。在數(shù)據(jù)遷移完成之前,這些數(shù)據(jù)都不會(huì)被回收。如下圖所示:

毫無疑問,當(dāng)我們的數(shù)據(jù)量大時(shí)不應(yīng)該使用這種類型的reader來讀取數(shù)據(jù)。

JdbcPagingItemReader

JdbcPagingItemReader的作用和它的名字一樣,它可以分頁讀取數(shù)據(jù),但是使用起來相比于JdbcCursorItemReader更加復(fù)雜,示例代碼如下:

@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;
}

可以看到我們能夠設(shè)置page的大小,JdbcPagingItemReader將根據(jù)這個(gè)頁的大小,每次讀取這么多的數(shù)據(jù),因此這些數(shù)據(jù)返回保存的對(duì)象,就只會(huì)是小對(duì)象,因此他們不會(huì)直接在老年代里分配,而是先分配在年輕代,隨著年輕代不斷變大,minor gc也不斷進(jìn)行,回收掉已經(jīng)處理完的數(shù)據(jù),老年代的內(nèi)存使用量不會(huì)有任何增大,類似下圖:

老年代內(nèi)存不會(huì)有任何變化,年輕帶會(huì)隨著服務(wù)器數(shù)據(jù)遷移進(jìn)行而增大同時(shí)被回收。

在使用JdbcPagingItemReader時(shí),有一個(gè)必須注意的地方就是排序關(guān)鍵字是必須指定的,原因在于排序是分頁實(shí)現(xiàn)原理的技術(shù)基礎(chǔ)。sortKey和我們指定的其他字句一起構(gòu)建出SQL語句出來。在sortKey上必須使用unique key constraint約束,因?yàn)橹挥羞@樣才能得以確保執(zhí)行之間不會(huì)丟失任何數(shù)據(jù)。這也可以說是JdbcCursorItemReader相對(duì)便利的一點(diǎn)優(yōu)勢(shì)。

總結(jié)

數(shù)據(jù)量小時(shí)選擇的方案差別不會(huì)很大,當(dāng)數(shù)據(jù)量大時(shí),為了有好的內(nèi)存表現(xiàn)則使用分頁的reader是必要的。但同時(shí),因?yàn)橐獙?shí)現(xiàn)分頁,也會(huì)帶來一些不可避免的限制。

到此這篇關(guān)于spring batch使用reader讀數(shù)據(jù)的內(nèi)存容量問題詳解的文章就介紹到這了,更多相關(guān)spring batch使用reader讀數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 簡(jiǎn)介Java的Hibernate框架中的Session和持久化類

    簡(jiǎn)介Java的Hibernate框架中的Session和持久化類

    這篇文章主要介紹了Java的Hibernate框架中的Session和持久化類,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • 詳解SpringCloud使用Consul做注冊(cè)中心

    詳解SpringCloud使用Consul做注冊(cè)中心

    這篇文章主要介紹了SpringCloud使用Consul做注冊(cè)中心,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Spring Validator接口校驗(yàn)與全局異常處理器

    Spring Validator接口校驗(yàn)與全局異常處理器

    這篇文章主要介紹了Spring Validator接口校驗(yàn)與全局異常處理器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 純Java實(shí)現(xiàn)數(shù)字證書生成簽名的簡(jiǎn)單實(shí)例

    純Java實(shí)現(xiàn)數(shù)字證書生成簽名的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)硪黄僇ava實(shí)現(xiàn)數(shù)字證書生成簽名的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • Spring高級(jí)注解@PropertySource詳細(xì)解讀

    Spring高級(jí)注解@PropertySource詳細(xì)解讀

    這篇文章主要介紹了Spring高級(jí)注解@PropertySource詳細(xì)解讀,@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過YAML解析器,配合自定義PropertySourceFactory實(shí)現(xiàn)解析yaml文件,需要的朋友可以參考下
    2023-11-11
  • 為什么說HashMap線程不安全

    為什么說HashMap線程不安全

    本文主要介紹了為什么說HashMap線程不安全,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析

    你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析

    這篇文章主要介紹了你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • SpringBoot中?Jackson?日期的時(shí)區(qū)和日期格式問題解決

    SpringBoot中?Jackson?日期的時(shí)區(qū)和日期格式問題解決

    因?yàn)樽罱?xiàng)目需要國(guó)際化,需要能夠支持多種國(guó)際化語言,目前需要支持三種(法語、英語、簡(jiǎn)體中文),這篇文章主要介紹了SpringBoot中?Jackson?日期的時(shí)區(qū)和日期格式問題,需要的朋友可以參考下
    2022-12-12
  • Java通過遞歸算法解決迷宮與漢諾塔及八皇后問題

    Java通過遞歸算法解決迷宮與漢諾塔及八皇后問題

    方法就是用來完成解決某件事情或?qū)崿F(xiàn)某個(gè)功能的辦法;程序調(diào)用自身的編程技巧稱為遞歸,本文主要講的是通過遞歸來實(shí)現(xiàn)三個(gè)經(jīng)典的問題,解決迷宮,漢諾塔,八皇后問題,感興趣的朋友可以參考一下
    2022-05-05
  • java開發(fā)環(huán)境的完整搭建過程

    java開發(fā)環(huán)境的完整搭建過程

    這篇文章主要給大家介紹了關(guān)于java開發(fā)環(huán)境的完整搭建過程,文中介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02

最新評(píng)論