HBase Scan 中 setCaching setMaxResultSize setBatch 解惑

0. 蜜汁參數(shù)

在做 HBase 客戶端 scan 優(yōu)化時(shí)榛臼,經(jīng)常會(huì)碰到以下幾個(gè)參數(shù)峻厚,總是讓人迷惑 ,不知從何優(yōu)化起骤铃。

  • .setCache (緩存大小? 字節(jié)數(shù)拉岁?行數(shù)?)
  • .setMaxResultSize (最大結(jié)果數(shù)惰爬?)
  • .setBatch (批量喊暖?)

造成這種困擾很大的原因是命名問題。
先說下結(jié)論撕瞧,如果把名字改成如下陵叽,語義會(huì)清晰很多 。[1]

  • .setCaching => .setNumberOfRowsFetchSize (客戶端每次 rpc fetch 的行數(shù))
  • .setMaxResultSize => .setMaxResultByteSize (客戶端緩存的最大字節(jié)數(shù))
  • .setBatch => .setColumnsChunkSize (客戶端每次獲取的列數(shù))

1. Client Scan 原理及相關(guān)源碼解讀

HBase 每次 scan 的數(shù)據(jù)量可能會(huì)比較大丛版,客戶端不會(huì)一次性全部把數(shù)據(jù)從服務(wù)端拉回來巩掺。而是通過多次 rpc 分批次的拉取。類似于 TCP 協(xié)議里面一段一段的傳輸页畦,可以做到細(xì)粒度的流量控制胖替。至于如何調(diào)優(yōu),控制每次 rpc 拉取的數(shù)據(jù)量,就可以通過以上三個(gè)比較蛋疼的參數(shù)來控制独令。

我們可以先看一段來自 HBase scan 里面的核心類 ClientScanner 里的讀取邏輯端朵,通過它來了解整個(gè)流程。

@Override
public Result next() throws IOException {
  // If the scanner is closed and there's nothing left in the cache, next is a no-op.
  if (cache.size() == 0 && this.closed) {
    return null;
  }

  // 緩沖中沒有就 RPC 調(diào)用讀取數(shù)據(jù)進(jìn)緩存
  if (cache.size() == 0) {   
        loadCache();
  }
 
  // 緩沖中有直接從緩存中取
  if (cache.size() > 0) {
    return cache.poll();
  }
 
  // if we exhausted this scanner before calling close, write out the scan metrics
  writeScanMetrics();
  return null;
}

每次從緩存 cache 中讀燃箭,緩存為空則 loadCache , 實(shí)際上 cache 是通過一個(gè)鏈表來實(shí)現(xiàn)的逸月,定義如下:
protected final LinkedList<Result> cache = new LinkedList<Result>();

繼續(xù)看 loadCache() ,為了弄清大體主流程遍膜,我刪除了部分代碼

 protected void loadCache() throws IOException {
    Result[] values = null;
    // 剩余最大容量
    long remainingResultSize = maxScannerResultSize;
    // 行數(shù)計(jì)數(shù) 為 setCaching 的值
    int countdown = this.caching;
    // 配置 rpc 請(qǐng)求的條數(shù)
    callable.setCaching(this.caching);
    boolean serverHasMoreResults = false;

    // do while 循環(huán)碗硬,循環(huán)次數(shù)即為 rpc 次數(shù)
    do {
      try {
        // rpc 從 server 拉數(shù)據(jù),請(qǐng)求的條數(shù)為 this.caching 默認(rèn)為 Integer.Max_VALUE
        values = call(callable, caller, scannerTimeout);
         } catch (DoNotRetryIOException | NeedUnmanagedConnectionException e) {
             // 異常處理 這里略過
       }
      // Groom the array of Results that we received back from the server before adding that
      // Results to the scanner's cache
      // 將數(shù)據(jù)放入緩存前瓢颅,先對(duì)數(shù)據(jù)進(jìn)行一些處理恩尾,主要是處理對(duì)于部分對(duì)調(diào)用這不可見的數(shù)據(jù)
      List<Result> resultsToAddToCache =
          getResultsToAddToCache(values, callable.isHeartbeatMessage());
      if (!resultsToAddToCache.isEmpty()) {
        // 遍歷 results 寫入 cache
        for (Result rs : resultsToAddToCache) {
          cache.add(rs);
          // We don't make Iterator here
          for (Cell cell : rs.rawCells()) {
            // 估算每個(gè) cell 的大小,計(jì)算剩余 byte size 
            remainingResultSize -= CellUtil.estimatedHeapSizeOf(cell);
          }
          // 剩余行數(shù) --
          countdown--;
          this.lastResult = rs;
        }
      }

      // We expect that the server won't have more results for us when we exhaust
      // the size (bytes or count) of the results returned. If the server *does* inform us that
      // there are more results, we want to avoid possiblyNextScanner(...). Only when we actually
      // get results is the moreResults context valid.
      if (null != values && values.length > 0 && callable.hasMoreResultsContext()) {
        serverHasMoreResults = callable.getServerHasMoreResults() & partialResults.isEmpty();
      }
      // Values == null means server-side filter has determined we must STOP
    } while (doneWithRegion(remainingResultSize, countdown, serverHasMoreResults)
        && (!partialResults.isEmpty() || possiblyNextScanner(countdown, values == null)));
     // 循環(huán)條件
  }

這里重點(diǎn)看下do while 循環(huán)的條件 doneWithRegion()

  /**
   * @param remainingResultSize
   * @param remainingRows
   * @param regionHasMoreResults
  */
  private boolean doneWithRegion(long remainingResultSize, int remainingRows,
      boolean regionHasMoreResults) {
    // 同時(shí)滿足這些才行這里的
    // remainingResultSize 初始值即為配置的 setMaxResultSize 
   //  remainingRows 初始值為配置的 setCaching (實(shí)際為:行數(shù))
    return remainingResultSize > 0 && remainingRows > 0 && !regionHasMoreResults;
  }

因?yàn)槊看?while 循環(huán)會(huì)進(jìn)行一次 rpc 調(diào)用挽懦,不同的參數(shù)配置組合配置導(dǎo)致 rpc 調(diào)用的次數(shù)不同翰意。必須同時(shí)滿足行數(shù)與字節(jié)數(shù)的的限制才行。

3. 官方配置與建議

這幾個(gè)參數(shù)對(duì)應(yīng)的配置如下

  • hbase.client.scanner.caching - (setCaching):HBase-0.98 默認(rèn)值為為 100信柿,HBase-1.2 默認(rèn)值為 2147483647冀偶,即 Integer.MAX_VALUE。Scan.next() 的一次 RPC 請(qǐng)求 fetch 的記錄條數(shù)渔嚷。配置建議:這個(gè)參數(shù)與 下面的hbase.client.scanner.max.result.size - (setMaxResultSize) 配置使用进鸠,在網(wǎng)絡(luò)狀況良好的情況下,自定義設(shè)置不宜太小形病, 可以直接采用默認(rèn)值客年,不配置。

  • hbase.client.scanner.max.result.size - (setMaxResultSize):HBase-0.98 無該項(xiàng)配置漠吻,HBase-1.2 默認(rèn)值為 210241024量瓜,即 2M。Scan.next() 的一次 RPC 請(qǐng)求 fetch 的數(shù)據(jù)量大小途乃,目前 HBase-1.2 在 Caching 為默認(rèn)值(Integer Max)的時(shí)候绍傲,實(shí)際使用這個(gè)參數(shù)控制 RPC 次數(shù)和流量。配置建議:如果網(wǎng)絡(luò)狀況較好(萬兆網(wǎng)卡)耍共,scan 的數(shù)據(jù)量非常大烫饼,可以將這個(gè)值配置高一點(diǎn)。如果配置過高:則可能 loadCache 速度比較慢划提,導(dǎo)致 scan timeout 異常

  • hbase.server.scanner.max.result.size:服務(wù)端配置枫弟。HBase-0.98 無該項(xiàng)配置,HBase-1.2 新增鹏往,默認(rèn)值為 10010241024淡诗,即 100M骇塘。該參數(shù)表示當(dāng) Scan.next() 發(fā)起 RPC 后,服務(wù)端返回給客戶端的最大字節(jié)數(shù)韩容,防止 Server OOM款违。[2]

  • setBatch() 坑爹的命名,這個(gè)實(shí)際上是配置獲取的列數(shù)群凶,假如表有兩個(gè)列簇 cf插爹,info,每個(gè)列簇5個(gè)列请梢。這樣每行可能有10列了赠尾,setBatch() 可以控制每次獲取的最大列數(shù),進(jìn)一步從列級(jí)別控制流量毅弧。配置建議:當(dāng)列數(shù)很多气嫁,數(shù)據(jù)量大時(shí)考慮配置此參數(shù),例如100列每次只獲取50列够坐。一般情況可以默認(rèn)值(-1 不受限)寸宵。

參考:
[1] HBase client’s weird API names
[2] HBase Client配置參數(shù)說明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市元咙,隨后出現(xiàn)的幾起案子梯影,更是在濱河造成了極大的恐慌,老刑警劉巖庶香,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甲棍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡脉课,警方通過查閱死者的電腦和手機(jī)救军,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倘零,“玉大人,你說我怎么就攤上這事戳寸〕适唬” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵疫鹊,是天一觀的道長(zhǎng)袖瞻。 經(jīng)常有香客問我,道長(zhǎng)拆吆,這世上最難降的妖魔是什么聋迎? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮枣耀,結(jié)果婚禮上霉晕,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好牺堰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布拄轻。 她就那樣靜靜地躺著,像睡著了一般伟葫。 火紅的嫁衣襯著肌膚如雪恨搓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天筏养,我揣著相機(jī)與錄音斧抱,去河邊找鬼。 笑死渐溶,一個(gè)胖子當(dāng)著我的面吹牛夺姑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掌猛,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼盏浙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了荔茬?” 一聲冷哼從身側(cè)響起废膘,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎慕蔚,沒想到半個(gè)月后丐黄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孔飒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年灌闺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坏瞄。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桂对,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸠匀,到底是詐尸還是另有隱情蕉斜,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布缀棍,位于F島的核電站宅此,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏爬范。R本人自食惡果不足惜父腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望青瀑。 院中可真熱鬧璧亮,春花似錦萧诫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至躬络,卻和暖如春尖奔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穷当。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工提茁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人馁菜。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓茴扁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親汪疮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峭火,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • HBase那些事 @(大數(shù)據(jù)工程學(xué)院)[HBase, Hadoop, 優(yōu)化, HadoopChen, hbase]...
    分癡閱讀 3,931評(píng)論 3 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)智嚷,斷路器卖丸,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 該文檔是用Hbase默認(rèn)配置文件生成的,文件源是Hbase-default.xml hbase.rootdir 這...
    我是嘻哈大哥閱讀 4,749評(píng)論 0 7
  • 摘自:http://debugo.com/hbase-params/ 通用和master配置hbase.rootd...
    wangliang938閱讀 2,699評(píng)論 1 5
  • HBase掃描操作Scan 1 介紹 掃描操作的使用和get()方法類似盏道。同樣稍浆,和其他函數(shù)類似,這里也提供了Sca...
    yanzhelee閱讀 9,009評(píng)論 0 5