大資料應用之HBase資料插入效能優化實測教程

逸卿發表於2014-09-17

引言:

大家在使用HBase的過程中,總是面臨效能優化的問題,本文從HBase客戶端引數設定的角度,研究HBase客戶端資料批量插入效能優化的問題。事實勝於雄辯,資料比理論更有說服力,基於此,作者設計了這麼一個HBase資料插入效能優化實測實驗,希望大家用自己的伺服器跑出的結果,給自己一個值得信服的結論。

一、客戶單優化引數

  1.Put List Size
  HBase的Put支援單條插入,也支援批量插入。

  2. AutoFlush  
  AutoFlush指的是在每次呼叫HBase的Put操作,是否提交到HBase Server。 預設是true,每次會提交。如果此時是單條插入,就會有更多的IO,從而降低效能

  3.Write Buffer Size
  Write Buffer Size在AutoFlush為false的時候起作用,預設是2MB,也就是當插入資料超過2MB,就會自動提交到Server

  4.WAL
  WAL是Write Ahead Log的縮寫,指的是HBase在插入操作前是否寫Log。預設是開啟,關掉會提高效能,但是如果系統出現故障(負責插入的Region Server  掛掉),資料可能會丟失。

引數

預設值

說明

JVM Heap Size

 

平臺不同值不同自行設定

AutoFlush

True

預設逐條提交

Put List Size

1

支援逐條和批量

Write Buffer Size

2M

與autoflush配合使用

Write Ahead Log

True

預設開啟,需要手動關閉

 

 

 

 

二、原始碼程式

 import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;

/*
 * -------優化案例說明------------
 * 1.優化引數1:Autoflush                預設關閉,需要手動開啟
 * 2.優化引數2:put list size            支援單條與批量
 * 3.優化引數3:JVM heap size             預設值是平臺而不同,需要手動設定
 * 4.優化引數4:Write Buffer Size        預設值2M    
 * 5.優化引數5:Write Ahead Log             預設開啟,需要手動關閉
 * */

public class TestInsert {
    static Configuration hbaseConfig = null;

    public static void main(String[] args) throws Exception {
        Configuration HBASE_CONFIG = new Configuration();
        HBASE_CONFIG.set("hbase.master", "192.168.230.133:60000");
        HBASE_CONFIG.set("hbase.zookeeper.quorum", "192.168.230.133");
        HBASE_CONFIG.set("hbase.zookeeper.property.clientPort", "2181");
        hbaseConfig = HBaseConfiguration.create(HBASE_CONFIG);
        //關閉wal,autoflush,writebuffer = 24M
        insert(false,false,1024*1024*24);
        //開啟AutoFlush,writebuffer = 0
        insert(false,true,0);
        //預設值,全部開啟
        insert(true,true,0);
    }

    private static void insert(boolean wal,boolean autoFlush,long writeBuffer)
            throws IOException {
        String tableName="etltest";
        HBaseAdmin hAdmin = new HBaseAdmin(hbaseConfig);
        if (hAdmin.tableExists(tableName)) {
            hAdmin.disableTable(tableName);
            hAdmin.deleteTable(tableName);
        }

        HTableDescriptor t = new HTableDescriptor(tableName);
        t.addFamily(new HColumnDescriptor("f1"));
        t.addFamily(new HColumnDescriptor("f2"));
        t.addFamily(new HColumnDescriptor("f3"));
        t.addFamily(new HColumnDescriptor("f4"));
        hAdmin.createTable(t);
        System.out.println("table created");
        
        HTable table = new HTable(hbaseConfig, tableName);
        table.setAutoFlush(autoFlush);
        if(writeBuffer!=0){
            table.setWriteBufferSize(writeBuffer);
        }
        List<Put> lp = new ArrayList<Put>();
        long all = System.currentTimeMillis();
        
        System.out.println("start time = "+all);
        int count = 10000;
        byte[] buffer = new byte[128];
        Random r = new Random();
        for (int i = 1; i <= count; ++i) {
            Put p = new Put(String.format("row d",i).getBytes());
            r.nextBytes(buffer);
            p.add("f1".getBytes(), null, buffer);
            p.add("f2".getBytes(), null, buffer);
            p.add("f3".getBytes(), null, buffer);
            p.add("f4".getBytes(), null, buffer);
            p.setWriteToWAL(wal);
            lp.add(p);
            if(i%1000 == 0){
                table.put(lp);
                lp.clear();
            }
        }
        
        System.out.println("WAL="+wal+",autoFlush="+autoFlush+",buffer="+writeBuffer+",count="+count);
        long end = System.currentTimeMillis();
        System.out.println("total need time = "+ (end - all)*1.0/1000+"s");
        
        
        System.out.println("insert complete"+",costs:"+(System.currentTimeMillis()-all)*1.0/1000+"ms");
    }
}

三、叢集配置

3.1 伺服器硬體配置清單

序號

節點名稱

CUP

記憶體

硬碟

頻寬

1

HMaster

 

 

 

 

2

HregionServer1

 

 

 

 

3

HregionServer2

 

 

 

 

4

 

 

 

 

5

 

 

 

 

 

6

 

 

 

 

 

7

 

 

 

 

 

3.2 客戶端硬體配置清單

裝置

節點名稱

 

Cpu

 

 

記憶體

 

 

硬碟

 

 

頻寬

 

 

四、測試報告

資料量

JVM

AutoFlush

Put List Size

WriteBufferSize

WAL

耗時

1000

512m

false

1000

1024*1024*24

false

 

2000

 

 

 

 

 

 

5000

 

 

 

 

 

 

10000

 

 

 

 

 

 

20000

 

 

 

 

 

 

50000

 

 

 

 

 

 

100000

 

 

 

 

 

 

200000

 

 

 

 

 

 

500000

 

 

 

 

 

 

100000

 

 

 

 

 

 

備註:該技術專題討論正在群Hadoop高階交流群:293503507同步直播中,敬請關注。

相關文章