1. 程式人生 > >大資料之hbase(一) --- HBase介紹,特性,安裝部署,shell命令,client端與hbase的互動過程,程式設計API訪問hbase實現百萬寫入

大資料之hbase(一) --- HBase介紹,特性,安裝部署,shell命令,client端與hbase的互動過程,程式設計API訪問hbase實現百萬寫入

一、HBase介紹
----------------------------------------------
    1.基於hadoop的資料庫,具有分散式,可伸縮的大型資料儲存

    2.用於對資料的隨機訪問,實時讀寫

    3.巨大的表,十億行*百萬列

    4.版本化、非關係型資料庫


二、HBase特性
-------------------------------------------------
    Linear and modular scalability.
    線性模組化擴充套件

    Strictly consistent reads and writes.
    嚴格一直性讀寫

    Automatic and configurable sharding of tables
    自動的可配置的表切割

    Automatic failover support between RegionServers.
    支援區域伺服器之間動態容災

    Convenient base classes for backing Hadoop MapReduce jobs with Apache HBase tables.
    便利的,支援Hadoop MR的基本類庫

    Easy to use Java API for client access.
    易於使用的API

    Block cache and Bloom Filters for real-time queries.
    塊快取和布隆過濾器,用於實時查詢

    Query predicate push down via server side Filters
    通過伺服器端過濾器,實現查詢預測

    Thrift gateway and a REST-ful Web service that supports XML, Protobuf, and binary data encoding options
    具有支援XML,Protobuf,二進位制的選項的Thrift閘道器和服務

    Extensible jruby-based (JIRB) shell
    可拓展的shell

    Support for exporting metrics via the Hadoop metrics subsystem to files or Ganglia; or via JMX
    支援視覺化

    面向列的非關係型資料路。遵循嚴格的一致性讀寫(行級鎖,樂觀鎖)


三、hbase的儲存機制
-------------------------------------------------------------
    面向列儲存,表按照行排序


四、HBase的部署
-------------------------------------------------------------
    1.jdk

    2.ssh

    3.hadoop

    4.下載並tar開Hbase

    5.環境變數,符號連結,驗證安裝是否成功(hbase version)

    6.匯入JAVA_HOME的環境變數到配置檔案[hbase/conf/hbase-env.sh]中
        JAVA_HOME="/soft/jdk"

    7.配置hbase
        (1)本地模式
            a.配置[hbase/conf/hbase-site.xml]
                ...
                <property>
                    <name>hbase.rootdir</name>
                    <value>file:/home/hadoop/HBase/HFiles</value>
                </property>
                ...

        (2)偽分散式
           a.配置[hbase/conf/hbase-site.xml]
                <property>
                    <name>hbase.cluster.distributed</name>
                    <value>true</value>
                </property
                <property>
                    <name>hbase.rootdir</name>
                    <value>hdfs://localhost:8030/hbase</value>
                </property>

        (3)完全分散式
            a.[hbase/conf/hbase-env.sh]
                export JAVA_HOME=/soft/jdk
                export HBASE_MANAGES_ZK=false

            b.[hbase/conf/hbse-site.xml]
                <!-- 使用完全分散式 -->
                <property>
                    <name>hbase.cluster.distributed</name>
                    <value>true</value>
                </property>

                <!-- 指定hbase資料在hdfs上的存放路徑 -->
                <property>
                    <name>hbase.rootdir</name>
                    <value>hdfs://mycluster/hbase</value>
                </property>
                <!-- 配置zk地址 -->
                <property>
                    <name>hbase.zookeeper.quorum</name>
                    <value>192.168.43.131:2181,192.168.43.132:2181,192.168.43.133:2181</value>
                </property>
                <!-- zk的本地目錄 -->
                <property>
                    <name>hbase.zookeeper.property.dataDir</name>
                    <value>/home/ubuntu/zookeeper</value>
                </property>

    8.配置regionservers
        [hbase/conf/regionservers]
        s200
        s300
        s400

    9.啟動hbase叢集(s100)
        $>start-hbase.sh

    10.登入hbase的webui
        $> http://s100:16010


五、hbase叢集管理命令
--------------------------------------
    $> hbase-daemon.sh start master;
    $> hbase-daemon.sh stop master;
    $> hbase-daemon.sh start regionserver
    $> hbase-daemon.sh stop regionserver
    $> hbase-daemons.sh start regionserver


六、hbase的HA部署
----------------------------------------------------------
    因為hbase已經依賴於zk了,所以,直接在其他另外安裝了hbase的主機上執行命令
    $> hbase-daemon.sh start master
    開啟master管理程序即可


七、命令分組
-----------------------------------------------------------
    [general]
    status, table_help, version, whoami

    [ddl]
    alter, alter_async, alter_status, create, describe,
    disable, disable_all, drop, drop_all, enable, enable_all, exists,
    get_table, is_disabled, is_enabled, list, locate_region, show_filters

    [namespace]
    alter_namespace, create_namespace, describe_namespace,
    drop_namespace, list_namespace, list_namespace_tables

    [dml]
    append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve

    [tools]
    assign, balance_switch, balancer, balancer_enabled, catalogjanitor_enabled, catalogjanitor_run,
    catalogjanitor_switch, close_region, compact, compact_rs, flush, major_compact, merge_region, move, normalize,
    normalizer_enabled, normalizer_switch, split, trace, unassign, wal_roll, zk_dump

    [replication]
    add_peer, append_peer_tableCFs, disable_peer, disable_table_replication, enable_peer,
    enable_table_replication, list_peers, list_replicated_tables, remove_peer, remove_peer_tableCFs,
    set_peer_tableCFs, show_peer_tableCFs

    [snapshots]
    clone_snapshot, delete_all_snapshot, delete_snapshot, list_snapshots, restore_snapshot, snapshot

    [configuration]
    update_all_config, update_config

    [quotas]
    list_quotas, set_quota

    [security]
    grant, list_security_capabilities, revoke, user_permission

    [procedures]
    abort_procedure, list_procedures

    [visibility labels]
    add_labels, clear_auths, get_auths, list_labels, set_auths, set_visibility



七、hbase shell
-----------------------------------------------------------
    $> hbase shell                      //登入hbase shell 終端

    $hbase> help                        //檢視help
    $hbase> help 'list_namespace'       //檢視指定命令的幫助
    $hbase> list_namespace               //列出名字空間(裡面存放table,相當於mysql的database)
    $hbase> list_namespace_tables 'mynamespace'               //列出指定名字空間裡面存放的所有table
    $hbase> create_namespace 'ns1'               //建立名稱空間ns1
    $hbase> create 'ns1:t1','f1'                    //在ns1名稱空間下建立表t1
    $hbase> desc 'ns1:t1'                       //顯示錶細節
    $hbase> put 'ns1:t1','row1','f1:id',100     //在ns1的表t1的row1行,f1列族的id列put資料,100,三級[行,列族的列,時間戳版本]定位
    $hbase> get 'ns1:t1','row1'                 //獲取表t1的行id為row1的資料
    $hbase> scan 'ns1:t1'                       //全表掃描
    $hbase> disable 'ns1:t1'                    //禁用t1表
    $hbase> drop 'ns1:t1'                       //刪除t1(注意刪除表之前要先禁用表才能刪除)



八、hbase的表在hdfs上的儲存結構
------------------------------------------------------------------
    /hbase/data/{namespace}/{tablename}/{regionID}/{columnfamily}/{StoreFile}
    /hbase/data/ns1/t1/bdaa7c6d847b310af02cefe6a917864b/f1/a97d571e34df440d8d115bb685dbc5b0


九、client端與hbase的互動過程
------------------------------------------------------------------
    0.hbase啟動時,hmaster會負責將所有的region分配到每個HregionSerer上

    1.聯絡zk找出meta所在的rs(regionsServer)
        zk:/hbase/meta-region-server

    2.通過meta表,查詢到row key所在的具體rs伺服器,這樣就找到了region位置。並快取這次的查詢的主要資訊,以便於下次查詢

    3.聯絡定位好的rs伺服器,讓其開啟region,得到一個HRegion的例項,例項中每個列族都會對應一個Store

    4.每個store都會包含一個或者多個storefile(裡面封裝有實際的儲存資料hfile,是一種輕量級封裝)
    同時還會有一個與該store對應的memStore(記憶體中存放資料)

    5.寫過程分析:
        a.每個HRegionServer都會有一個與之對應的WAL,WAN是一個順序檔案(kv)用來儲存要寫入的資料的序列號和實際資料(實際資料儲存在memStore中)
        b.當發生寫請求的時候,會先執行1-4步驟,找到所要寫入資料的region所在的具體位置,然後檢視是否開啟了預寫日誌(寫入到記憶體)
        c.如果開啟了,那麼資料就會被寫入HSR的WAL中,進而資料就會被儲存到記憶體中(實際上是儲存在memStore中)
        d.檢查memStore是否已經滿了,滿了的話,就會將memStore中的資料重新整理到磁碟(hdfs)中,持久化儲存
        e.當然,當hbase關閉的時候,memStore中未寫入到hdfs中的資料也會被重新整理到hdfs中進行持久化儲存


十、程式設計API訪問hbase,實現百萬寫入
------------------------------------------------------------------
    1.建立hbase模組,新增maven依賴
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.6</version>
        </dependency>

    2.程式碼實現
   import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.hbase.Cell;
    import org.apache.hadoop.hbase.HBaseConfiguration;
    import org.apache.hadoop.hbase.TableName;
    import org.apache.hadoop.hbase.client.*;
    import org.apache.hadoop.hbase.util.Bytes;
    import org.junit.Before;
    import org.junit.Test;

    import java.io.IOException;
    import java.text.DecimalFormat;
    import java.util.List;

    /**
     * 測試 --hbaseapi
     */
    public class TsCRUD {

        public Connection conn;
        public Table tb;

        @Before
        public void getConn() throws Exception {
            //獲取配置檔案
            Configuration conf = HBaseConfiguration.create();
            //工廠類建立連線
            conn = ConnectionFactory.createConnection(conf);
            //get table
            TableName tbName = TableName.valueOf("ns1:t1");
            tb = conn.getTable(tbName);
        }


        @Test
        public void tsPut() throws Exception {
            //new put row
            Put put = new Put(Bytes.toBytes("row3"));
            //add put column cile
            put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("id"), Bytes.toBytes(102));
            tb.put(put);
            System.out.println("put over");

        }

        @Test
        public void tsGet() throws Exception {
            Get get = new Get(Bytes.toBytes("row3"));
            Result rs = tb.get(get);
            byte [] bs = rs.getValue(Bytes.toBytes("f1"), Bytes.toBytes("id"));
            System.out.println(Bytes.toInt(bs));
        }

        @Test
        public void tsBigPut() throws Exception {
            long time = System.currentTimeMillis();
            //關閉自動重新整理
            HTable t = (HTable) tb;
            t.setAutoFlush(false);

            //開始插入
            for (int i = 5; i < 1000000; i++) {

                //為了保證id的一致性(8 --> 0000008)
                DecimalFormat format = new DecimalFormat();
                format.applyPattern("0000000");
                Put put = new Put(Bytes.toBytes("row" + format.format(i)));

                //關閉寫前日誌Hlog,不讓其執行WAL(不推薦使用,因為當伺服器宕機會丟失資料)
                put.setWriteToWAL(false);

                //add put column cile
                put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("id"), Bytes.toBytes(i));
                put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("tom" + i));
                put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("age"), Bytes.toBytes(i % 100));
                t.put(put);

                //每2000,一提交
                if (i % 2000 == 0) {
                    t.flushCommits();
                }
            }
            //提交剩餘
            t.flushCommits();

            System.out.println("耗時:" + (System.currentTimeMillis() - time));
        }

    }