HBase淺度學習

簡介

hbase是大數據hadoop的數據庫

存儲數據html

支持海量數據的存儲
hbase是構建在hdfs上的分佈式數據庫

檢索數據前端

hbase支持對存儲在hbase表中的海量數據進行隨機的實時的查詢服務 
hbase對其大表中的海量數據構建了層層索引

已經有RDBMS數據庫爲何還須要hbase這種hadoop數據庫?(何時須要選擇hbase)

要存儲的數據爲海量的數據java

RDBMS 
    集羣性能比較弱,不容易集羣節點擴展
    一旦存儲的表的數據量較大,致使表的索引文件也變大,影響到後續的讀寫效率            
    
hbase 
    構建在hdfs上分佈式數據庫,支持節點無限擴展
    hbase的出現就是RDBMS在面對海量數據存儲及檢索時的一個可替代工具/框架

要存儲的數據爲非結構化的數據node

結構化數據 
    mysql或hive表中的數據結構化的數據 

非結構化的數據 
    每條數據的字段數量不相同 
    圖片、視頻、文本數據都是非結構化的數據

hbase是一種nosql數據庫(非關係型數據庫)

「Not Only SQL」的縮寫,不只僅是sql ,以nosql數據庫在記錄數據時所使用的數據結構的不一樣將nosql數據庫分爲四你們族mysql

列存儲數據庫家族 -- 表明 hbase  
    表中每列的數據是一個連續的存儲單元 
    hive表或者mysql中默認每行的數據是一個連續的存儲單元 

文檔型數據庫家族 -- 表明MongoDB  
    以文檔形式記錄數據庫中的數據
    爬蟲項目中
    
鍵值對數據庫家族 --表明redis
    以key-value形式記錄數據的數據庫 
    redis是基於內存的key-value數據庫 
        sparkStreaming/strom/Flink進行實時分析計算-》redis-》接入前端進行實時更新展現

圖形結構數據庫家族--表明Neo4J 
    以圖形形式記錄數據

https://baike.baidu.com/item/...linux

hbase常見的應用場景

  • 接入在線業務提供內容查詢服務 (藉助hbase分佈式數據庫進行海量用戶數據的存儲,並依靠其完善的檢索機制爲海量數據提供隨機的實時的查詢服務)
  • 微博、論壇、朋友圈等社交數據的存儲
    海量數據
    圖片、視頻、文本數據都是非結構化的數據
  • 各大電商平臺的訂單數據
    未完成的訂單(熱數據)-- oracle
    已完成的訂單(冷數據)-- hbase
  • 物流信息存儲查詢
  • 銀行客戶交易數據
  • 支付公司的交易數據
  • 移動電信公司的話單記錄存儲
  • 交通數據存儲
  • 醫療數據web

  • 大數據分析平臺中的數據存儲庫
    能夠用hbase做爲大數據分析平臺中的數據源
    MapReduce、hive、spark等計算框架能夠直接從hbase表中讀寫數據redis

  • HBase在滴滴出行的應用場景和最佳實踐
    https://blog.51cto.com/xiaogo...算法

hbase的特色:

hbase源自於谷歌三大論文之一的 BigTable     
    GFS  -- hdfs  
    MapReduce  -- MapReduce 
    BigTable -- hbase 
hbase在hadoop生態圈中的地位 
    構建在hdfs上分佈式數據庫,支持海量數據的存儲 
    能夠MapReduce、hive、spark框架進行集成使用  
基於【列存儲】的數據庫 
    列存儲與行存儲  
        RDBMS數據庫都是默認行存儲  
            每行的數據在底層是一個連續的存儲單元 
            在select查詢時若是隻涉及到表中的其中幾列數據,則無關列也會被加載讀取,大大增長系統的io流 
        Hbase數據庫默認是列存儲 
            每列的數據在底層是一個連續的存儲單元 
            在select查詢時若是隻涉及到表中的其中幾列數據,則只有涉及到的列會被加載讀取
            由於每列的數據保存在一塊兒,而且每列的數據的數據類型相同,則更容易實現壓縮存儲  
適合存儲非結構化和結構化的數據  
基於key-value形式存儲的數據庫 
    根據key來獲取對應的value值
    rowkey+列簇+列+時間戳 =》value
高可靠、高性能、可伸縮的分佈式數據庫 
    高可靠、可伸縮:構建在hdfs上 
    高性能:對比RDBMS,針對海量數據的讀寫是高性能的

行存儲與列存儲
https://blog.csdn.net/dc_726/...sql

Hive和HBase的區別?

hive
    面向分析的數據倉庫工具(非數據庫),使用的是Hql語句分析
    查詢高延遲
    存儲結構化數據
    不能直接接入web前端業務使用
    默認行存儲,是純邏輯表
    Hive自己不存儲和計算數據,它徹底依賴於HDFS和MapReduce,本質就是將hql轉化爲mr。
hbase
    面向數據存儲和檢索的數據庫
        數據存儲 -- 海量數據存儲(底層是hdfs)
        數據檢索 -- 支持海量數據隨機的、實時的數據檢索(依靠層層索引)
    查詢低延遲
        能夠實現隨機實時檢索大表中的數據
    適合存儲結構化和非結構化數據        
    能夠接入web前端業務使用
    hbase是列存儲,是物理表,不是邏輯表,經過索引方便快速查詢更新等操做
    hbase是一個在hdfs上開發的面向列的分佈式數據庫,自己不支持sql,可是能夠藉助其餘插件實現sql功能。
        經過hive建立與hbase表的關聯映射 -- 使用hql實現離線分析
        經過Phoenix插件實現實時分析

    Phoenix介紹:
        針對hbase開發的第三方插件,目前已貢獻給Apache               
        Phoenix是構建在HBase上的一個SQL層
        Phoenix徹底使用Java編寫,做爲HBase內嵌的JDBC驅動能讓咱們用標準的JDBC API而不是HBase客戶端API來建立表、插入數據和查詢數據。
        Phoenix查詢引擎會將SQL查詢轉換爲一個或多個HBase掃描,編排執行以生成標準的JDBC結果集。
                JDBC是一種用於執行SQL語句的Java API               
        版本    Phoenix 2.x/3.x - HBase 0.94.x
                Phoenix 4.x - HBase 0.98.1+

RDBMS和HBase的區別?

** HBase是分佈式架構,支持服務器在線添加和移除,能夠很好的擴展(基於hdfs)
** RDBMS可使用sql語句,HBase一般使用API來訪問[第三方插件支持phoenix]
** RDBMS是基於行存儲,HBase是基於列存儲,能夠支持更好的存儲和壓縮
** RDBMS適合存儲結構化的數據,HBase適合結構化和非結構化的數據存儲
** RDBMS支持比較好的事務,HBase不支持事務
** RDBMS支持多表Join,HBase不支持Join
** 一般HBase表的應用場景比較簡單,不適合業務邏輯很複雜的查詢環境
** RDBMS相比較hbase有更完善的索引機制
** HBase一般應用都是單表數據量巨大,用關係型數據庫沒法知足的狀況

hbase架構角色

hbase分佈式數據庫是主從架構

master

hbase的集羣的主節點 
管理用戶對hbase表的增刪改查(表總體非表內的數據)
管理並分配表的region給regionserver從節點,分配時遵循一個【散列原則:同一張表多個分片儘可能分配個不一樣的機器】及【負載均衡原則:不一樣的機器儘可能處理相同數量的分片】  
監控regionserver的運行狀態及regionserver節點宕機後的容災處理  
    master藉助zookeeper間接監控regionserver 
    zookeeper會感知regionserver節點的上線和下線 
        regionserver啓動後會在zookeeper上註冊信息
    但某個regionserver節點宕機後zookeeper會第一時間感知並及時通知master,master會進行容災處理將此regionserver節點上管理的region重構在其餘regionserver節點上

regionserver

hbase的從節點  
管理master所分配的region 
真正響應客戶端對錶的讀寫請求的節點

HRegion

table在行的方向上分隔爲多個Region。Region是HBase中分佈式存儲和負載均衡的最小單元,即不一樣的region能夠分別在不一樣的Region Server上,但同一個Region是不會拆分到多個server上。

Store

每一個region至少一個store,每一個列簇對應一個store
一個Store由一個memStore和0或者 多個StoreFile組成。 HBase以store的大小來判斷是否須要切分region

HLog

HLog(WAL log):WAL意爲write ahead log,用來作災難恢復使用,HLog記錄數據的全部變動,一旦region server 宕機,就能夠從log中進行恢復。
每一個 Region Server 維護一個 Hlog,而不是每一個 Region 一個。
HLog文件就是一個普通的Hadoop Sequence File, Sequence File的value是key時HLogKey對象,其中記錄了寫入數據的歸屬信息,除了table和region名字外,還同時包括sequence number和timestamp,timestamp是寫入時間,sequence number的起始值爲0,或者是最近一次存入文件系統中的sequence number。 Sequence File的value是HBase的KeyValue對象,即對應HFile中的KeyValue。

memStore

memStore 是放在內存裏的。保存修改的數據即keyValues。當memStore的大小達到一個閥值(默認128MB)時,memStore會被flush到文 件,即生成一個快照。目前hbase 會有一個線程來負責memStore的flush操做。

StoreFile

memStore內存中的數據寫到文件後就是StoreFile,StoreFile底層是以HFile的格式保存。當storefile文件的數量增加到必定閾值後,系統會進行合併(minor、major compaction),在合併過程當中會進行版本合併和刪除工做(majar),造成更大的storefile。

hdfs

hbase表數據最終落地在hdfs上 
爲hbase的表數據提供了一個存儲平臺

zookeeper

hbase強依賴zookeeper  
    kafka、storm也是強依賴zookeeper
zookeeper基於第三方觀察者模式監控regionserver、master的運行狀態及節點宕機後的容災處理 
    保證hbase集羣的高可用性
        hbase能夠爲master節點配置多個備份 
        當active master宕機後zookeeper會感知並從備份master中選舉出一個做爲後續的active master  
zookeeper持有hbase集羣的全部的服務器節點信息及全部用戶表的元數據信息的位置信息 
    持有hbase集羣的全部的服務器節點信息 
        hbase服務啓動後master及regionserver節點會向zookeeper上註冊本身的節點信息 
            
    持有全部用戶表的元數據所在的meta表的region位置信息!!! 
        hive表的元數據 -- 存在RDBMS數據庫 
        hbase表的元數據 -- 存在在hbase上的一張名稱爲meta的系統表中  
        
        hbase上全部用戶表的元數據信息都存在hbase上的一個meta表中  
        meta表的數據量一般比較少,全部meta表一般只有一個region
        此meta表的region會被master分配給某個regionserver節點管理  
        zookeeper持有該meta表的region所在的regionserver節點信息 (知道meta表的region在哪一個regionserver節點上) 
        
        
        meta表存有用戶表的哪些元數據信息呢?      
            用戶表分紅了幾個region 
            每一個region的key的範圍信息  
            每一個region所在regionserver節點信息 
            ……

hbase安裝部署

一、安裝hadoop並啓動hdfs服務

二、安裝並啓動zookeeper服務

三、上傳解壓並修改hbase配置文件

$ tar zxf /opt/softwares/hbase-1.2.0-cdh5.14.2.tar.gz -C /opt/cdh-5.14.2/
    
1)修改hbase-env.sh    
    # The java implementation to use.  Java 1.7+ required.
    export JAVA_HOME=/opt/cdh-5.14.2/jdk1.8.0_112
    # Tell HBase whether it should manage it's own instance of Zookeeper or not.
    export HBASE_MANAGES_ZK=false
    
2)修改hbase-site.xml 

聲明hbase表相關數據在hdfs上的根目錄
<property>
        <name>hbase.rootdir</name>
        <value>hdfs://192.168.134.101:8020/hbase</value>
      </property>
      
      <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
      </property>
      
      <!-- 聲明外置的zookeeper集羣節點服務器ip地址  -->
      <property>
        <name>hbase.zookeeper.quorum</name>
        <value>192.168.134.101</value>
      </property>
3)修改 regionservers 
    聲明集羣中的哪些服務器做爲hbase的regionserver節點 
    相似於hadoop中配置slaves
    
    192.168.134.101

四、啓動hbase服務

在主節點服務器上啓動master進程 
    $ bin/hbase-daemon.sh start master
在全部的hbase的從節點服務器上啓動regionserver進程 
    $ bin/hbase-daemon.sh start regionserver 
    
或者在master節點服務器上執行 
    $ bin/start-hbase.sh

五、hbase的web管理平臺

http://192.168.134.101:60010/master-status 

    user table -- 用戶表  
    system table --系統表 
        hbase:meta    
            hbase的元數據表 
            存儲了全部用戶表的region的引用 
        hbase:namespace 
            命名空間表

六、啓動hbase後的zookeeper及hdfs上的變化

hdfs上 
        /hbase/data/
            hbase的表數據的命名空間庫目錄 
            自定義的命名空間庫目錄將出如今該data目錄下
        /hbase/data/default 
            默認命名空間庫目錄 
            在hbase上建表時若是未指定表的命名空間庫則默認建立在default下 
        /hbase/data/hbase 
            系統命名空間庫目錄 
            meta --- meta表數據目錄  
            namespace --命名空間庫元數據表     
            
    zookeeper 
        $ bin/zkCli.sh 
        ls /hbase                    
            meta-region-server  -- meta表的位置信息 
            rs -- regionserver節點的信息 
            backup-masters -- master節點的備份信息 
            master -- active master節點信息

hbase表的存儲模型及存儲模型中的專業術語

rowkey:行健  
    用來標識hbase表中惟一一行數據  
    相似RDBMS中的主鍵  
column family :列簇/列族    
    能夠將某些列組織到一塊兒造成一個家族 
    列簇爲一張表的列增長一層索引
    在hbase表建立時能夠聲明多個列簇,通常應用中列簇的數量不超過3個,最好只設置1個列簇???? 
    在建立表至少要聲明一個列簇 ,可是不須要聲明列名 
column : 列 
    值所屬的列  
    hbase表中不一樣的行能夠有不一樣的列 
    在hbase表中插入具體數據時再指定列名 
    某個列必需要屬於某個列簇  
cell : 單元格  
    單元格是hbase表最小最基本的存儲單元  
    單元格是實際值的存儲地 
    每一個單元格的組成 : rowkey+列簇+列+時間戳=》value值  
        時間戳: 
            value值在插入到單元格那一刻的時間戳 
            時間戳能夠用來區分一個單元格中多個歷史版本的值 
        版本: 
            hbase表的單元格中能夠存儲多個歷史版本值  
            一個單元格中默認顯示的最新版本的值 
        
在hbase表中如何指定惟一的一個單元格/惟一的值 
    rowkey+列簇+列=》單元格 
    rowkey+列簇+列+時間戳=》惟一的值

hbase shell基本使用

與hbase進行交互的幾種方式

hbase shell -- 測試 
web ui(hue)-- 測試  
java api / Phoenix -- 生產

$ bin/hbase shell 進入到hbase的shell交互命令行

退格鍵出現亂碼:

xshell 
    文件-屬性-終端-鍵盤-兩個都選擇ASCII 127  
secureCRT 
    選項-會話選項-仿真-終端-選擇linux 
    選項-會話選項-映射鍵-兩個勾選

help 查看hbase shell支持的命令

COMMAND GROUPS:
  Group name: general
  Commands: status, table_help, version, whoami

  Group name: ddl
  Commands: 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

  Group name: namespace
  Commands: alter_namespace, create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables

  Group name: dml
  Commands: append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve

  Group name: tools
  Commands: assign, balance_switch, balancer, balancer_enabled, catalogjanitor_enabled, catalogjanitor_run, catalogjanitor_switch, close_region, compact, compact_mob, compact_rs, flush, major_compact, major_compact_mob, merge_region, move, normalize, normalizer_enabled, normalizer_switch, split, trace, unassign, wal_roll, zk_dump

  Group name: replication
  Commands: add_peer, append_peer_tableCFs, disable_peer, disable_table_replication, enable_peer, enable_table_replication, get_peer_config, list_peer_configs, list_peers, list_replicated_tables, remove_peer, remove_peer_tableCFs, set_peer_tableCFs, show_peer_tableCFs, update_peer_config

  Group name: snapshots
  Commands: clone_snapshot, delete_all_snapshot, delete_snapshot, list_snapshots, restore_snapshot, snapshot

  Group name: configuration
  Commands: update_all_config, update_config

  Group name: quotas
  Commands: list_quotas, set_quota

  Group name: security
  Commands: grant, list_security_capabilities, revoke, user_permission

  Group name: procedures
  Commands: abort_procedure, list_procedures

  Group name: visibility labels
  Commands: add_labels, clear_auths, get_auths, list_labels, set_auths, set_visibility

  Group name: rsgroup
  Commands: add_rsgroup, balance_rsgroup, get_rsgroup, get_server_rsgroup, get_table_rsgroup, list_rsgroups, move_servers_rsgroup, move_tables_rsgroup, remove_rsgroup

建立表命令

create 'ns1:t1', {NAME => 'f1', VERSIONS => 5}

在ns1命名空間庫下建立一個t1表
    t1表有一個名稱爲f1的列簇,而且該列簇下的單元格可最大支持5個版本值

create_namespace 'ns1' 建立一個命名空間庫

list_namespace

list 查看用戶表

create 't1', {NAME => 'f1'}, {NAME => 'f2'}, {NAME => 'f3'}

在默認命名空間庫下建立一個t1表  
    該表有三個名稱爲 f1 f2 f3的列族

describe 't1' 描述一張表

create 't2', {NAME => 'f1', VERSIONS => 2}, {NAME => 'f2', VERSIONS => 4}, {NAME => 'f3'}

在hbase表同一張表中不一樣的列簇能夠有不一樣的屬性值 
    由於同一張表下的同一個列簇中的cell存在同一個文件中,不一樣列簇中的cell存放在不一樣文件中

create 't1', 'f1', 'f2', 'f3'

建立一個t1表,而且該表的三個列簇都使用默認屬性    
若是但願對列簇進行特殊屬性設定,須要使用 {NAME => 'f1', VERSIONS => 2}

建立一個員工表並插入數據

create 'emp' , 'info1','info2'   

# put插入/更新數據 
# 一次只能插入一個cell,注意和sql的區別,不能insert插入一整行數據

hbase(main):037:0> put 'emp', '10003', 'info1:name', 'tom'
0 row(s) in 0.2320 seconds

hbase(main):038:0> put 'emp', '10003', 'info1:age', '25'
0 row(s) in 0.0090 seconds

hbase(main):039:0> put 'emp', '10003', 'info2:school', 'jiaoda'
0 row(s) in 0.0200 seconds

hbase(main):040:0> put 'emp', '10003', 'info2:qq', '1234554321'
0 row(s) in 0.0100 seconds

hbase(main):041:0> put 'emp', '10004', 'info1:name', 'lio'
0 row(s) in 0.0060 seconds

hbase(main):042:0> put 'emp', '10004', 'info1:sex', 'boy'
0 row(s) in 0.0090 seconds

hbase(main):043:0> put 'emp', '10004', 'info1:tall', '175cm'
0 row(s) in 0.0300 seconds

hbase(main):044:0> put 'emp', '10004', 'info2:job1', 'java'
0 row(s) in 0.0140 seconds

hbase(main):045:0> put 'emp', '10004', 'info2:job2', 'bigdata'
0 row(s) in 0.0330 seconds

hbase(main):046:0> put 'emp', '10005', 'info1:name', 'lili'
0 row(s) in 0.0190 seconds

hbase(main):047:0> put 'emp', '10005', 'info2:school', 'ligong'
0 row(s) in 0.0190 seconds

hbase(main):048:0> put 'emp', '10006', 'info1:name', 'mary'
0 row(s) in 0.0510 seconds

hbase(main):049:0> put 'emp', '10006', 'info1:age', '18'
0 row(s) in 0.0440 seconds

hbase(main):050:0> put 'emp', '10006', 'info2:job1', 'UI'

scan查詢數據

scan 'emp'    
scan 'emp' , {COLUMNS => 'info1'}     查看某張表中某個列簇下的數據  
scan 'emp' , {COLUMNS => 'info1:name'}    查看某列數據  
scan 'emp' , {COLUMNS => ['info1:name','info1:age']}     查看多列數據  
scan 'emp' , {COLUMNS => ['info1:name','info1:age']}     查看多列數據  
scan 'emp' , {COLUMNS => 'info1:name',LIMIT => 3}     最前面的3條數據 
scan 'emp' , {COLUMNS => 'info1',STARTROW => '10004',STOPROW=>'10006'}    某個rowkey範圍內的數據

顯示出來的每行是一個cell


get查詢數據

scan 是一個 範圍掃描查詢 
get 只能查詢某條範圍內的數據
get 'emp','10004'  查詢某行數據
get 'emp','10004' ,{COLUMN => 'info1'} 查詢某行數據下的某個列簇下的數據
get 'emp','10004' ,{COLUMN => 'info1:name'}  查詢某個cell中的數據最新版本的值  
get 't1', 'r1', {COLUMN => 'c1', TIMESTAMP => ts1}  查詢指定歷史版本的值 
get 't1', 'r1', {COLUMN => 'c1',  VERSIONS => 4} 查詢指定的cell中最新4個歷史版本值

delete/deleteall刪除數據

delete--刪除某個value值

deleteall--刪除的某行或某個cell

delete 't1', 'r1', 'c1', ts1  刪除指定歷史版本的值  
delete 'emp','10004','info2:job1'  不指定時間戳刪除的是最新版本的值 
deleteall 'ns1:t1', 'r1'  刪除某行數據  
deleteall 't1', 'r1'
deleteall 't1', 'r1', 'c1'  刪除某個cell單元格  
deleteall 't1', 'r1', 'c1', ts1  測試 !!!

演示多版本值:

create 'emp2' ,{NAME => 'info', VERSIONS => 5}
put 'emp2','10005','info:age' ,'18'
put 'emp2','10005','info:age' ,'19'
put 'emp2','10005','info:age' ,'20' 
scan 'emp2',{  VERSIONS => 2}   查詢全部cell最新2個版本的值  
delete 'emp2','10005','info:age' 不指定時間戳刪除的是最新版本的值  
delete 'emp2','10005','info:age' ,1543999422333  刪除指定歷史版本的值

修改表的hbase shell 命令

alter 't1', NAME => 'f1', VERSIONS => 5  將t1表中的f1列簇的VERSIONS屬性值改成 5  
alter 'ns1:t1', NAME => 'f1', METHOD => 'delete'  將t1表中的f1列簇刪除 
alter 't1', NAME => 'f2', METHOD => 'delete'

truncate 'emp2' 清空表

disable 'emp1' 禁用

drop 'emp1' 刪除表

count 'emp' 統計多少行


hbase表的讀寫流程

十五章-46頁 架構圖

HBase讀數據流程: --根據rowkey查詢emp表數據

一、client先去訪問zookeeper,從zookeeper裏面獲取meta表所在位置信息
        0.96以前的版本除了meta表還有一個root表,root表存儲meta表位置信息,先經過zookeeper獲取root表位置
        在從root表中讀取meta表位置
        如今直接將meta表位置存入zookeeper中,減小會話次數
二、client向meta所在regionserver發起訪問,讀取meta表數據,獲取hbase集羣上全部user表的元數據
三、根據meta表中emp表的region的位置信息,client找到了當前須要訪問的emp表對應的region及所在的regionserver服務器
四、client向對應regionserver服務器發起讀請求
五、regionserver收到client訪問請求,先掃描memstore,在掃描blockcache,最後再讀取storefile[HDFS]文件
六、regionserver把數據響應給client

HBase寫數據流程: --根據rowkey寫入emp表

一、client先去訪問zookeeper,從zookeeper裏面獲取meta表所在位置信息
二、client向meta所在regionserver發起訪問,讀取meta表數據,獲取hbase集羣上全部user表的元數據
三、根據meta表中emp表的region的位置信息,client找到了當前須要訪問的emp表對應的region及所在的regionserver服務器
四、client向對應regionserver服務器發起寫請求
五、regionserver收到client請求,並響應,client先把數據寫入HLog,防止數據丟失
六、再把數據寫入memstore內存緩存區,默認128M
七、當Hlog和memstore都寫入成功,則這條數據寫入成功    
八、當memstore達到閥值[128M],會把memstore裏面的數據Flush成storefile
九、當[128M]storefile愈來愈多,會觸發compact合併操做,把多storefile合併成一個大的storefile
    合併的期間會刪除過時的版本或數據,例如更新或delete刪除的數據並未直接刪除,而是打了刪除標籤直到此時纔會真正刪除    
十、當單個storefiles[region]愈來愈大,達到必定閥值(10G或其餘動態閾值)時會觸發split操做,region被一分爲二被管理

寫流程中的三大機制

flush 機制
compaction機制 
split機制

hbase java api使用

增刪改查操做

hbase表的物理模型

hbase中將表分紅了1個或多個region進行分佈式管理
region是hbase表管理的基本單元   

hbase爲何將表分紅多個region進行管理呢? 
    若是表比較大不利於表數據的並行讀寫操做 
    分而治之
    
一張表如何分紅多個region的? 
    建立表時進行預分區 
        默認建表時不進行預分區則表只有1個region   
        建表時能夠指定一個表的region的個數及region的key的範圍
            這個指定的key是rowkey的前綴
    region被動split分割
        當向某張表的某個region中持續寫入數據,region所承載的數據量達到必定的閾值【10G或小於10G的一個動態值】,則會進行被動的split分割,1個region分爲2個region 
        
表的region如何被master分配管理的? 
    一個表的多個region被master【散列】分配個regionserver集羣進行管理
    每一個regionserver節點能夠管理不一樣表的region,可是默認狀況下每一個regionserver節點最終管理的region的總數量是相同的【負載均衡】

    
region的內部結構 
    每一個region是由1個Hlog及1到多個store組成(每一個region中store的數量=該表的列簇的數量,每一個store下存儲了某一個列簇下的全部的數據)      
        每一個store是由1個memstore及0到多個storefile組成 
            memstore: 
                寫緩存,用來加快hbase表的寫速度 
                memstore的閾值是128M,當memstore中緩存的數據量達到128M則會flush成storeFile文件 
            
            storefile
                由memstore中flush出    
                storefile文件就是hbase表數據的存儲文件 
                storefile文件最終落地到hdfs上最終造成HFile 
                
        Hlog文件 
            每一個region中還包含一個Hlog文件  
            Hlog文件是一個預寫制日誌文件【WAL】  
            寫數據時默認狀況下數據會先寫入到對應region的Hlog中進行備份
            再將數據寫入到memstore中 
            當數據成功寫入Hlog+memstore後則後臺判斷這次寫入數據成功 
            當由於regionserver節點宕機致使memstore中的數據丟失時能夠從Hlog進行恢復 
            
            某些場景用能夠配置關閉WAL預寫機制  
            在1.x版本中能夠配置一個regionserver節點對應一個Hlog文件(一個regionserver節點上全部的region共用一個Hlog文件)=》能夠減小HLog文件的尋址次數  


    hbase表數據在hdfs上的存儲目錄結構 
        
        /hbase/data/default  
            在各個命名空間庫下包含有多個以代表命名的目錄 
        /hbase/data/default/emp 
            在表目錄下包含有1個或多個以region編號命名的目錄(該目錄下存儲了該表對應region下的數據)                    
            region的name  
                能夠在60010web平臺上查看到  
                region name的命名規則: 表名+Start Key+時間戳+region編號   
        /hbase/data/default/emp/8b1ae0ef2208947a238544b4b94ffeaa 
            在region編碼命名得目錄下會出現1個或多個以列簇名命名的目錄 
        /hbase/data/default/emp/8b1ae0ef2208947a238544b4b94ffeaa/info1 
            在列簇名命名的目錄下出現0到多個storefile文件

hbase表的讀寫流程

十五章-46頁 架構圖

組件介紹

1)client  客戶端 
    hbase shell --交互命令行  
    Hue - web  
    MapReduce  
    hive 
    spark 
    …… 
2)zookeeper  
    監控master及regionserver的狀態,保證hbase集羣的高可用 
    持有hbase集羣的節點信息及meta表的region的位置信息  
3)master  
    負責分配表的region給regionserver  
    負責集羣的負載均衡  
    讀寫過程沒有通過master節點,因此master節點負載率一般比較低 
4)regionserver  
    regionserver節點一般與hdfs的datanode節點部署在同一臺物理機上 
    regionserver負責管理表的region的節點 
    是真正相應客戶端讀寫請求的節點(響應客戶端IO請求的節點)    
5)hadoop 
    hadoop的hdfs爲hbase提供了一個數據存儲平臺 
    hdfs上主要存儲了hbase的兩種文件  
        HFile  
            就是hbase的StoreFile
            表數據的存儲文件  
            Hfile是hadoop的二進制格式文件   
        Hlog  
            預寫制日誌文件  
            Hlog是hadoop的sequence格式文件

hbase表數據的讀流程:(根據某個rowkey讀取emp表的數據)

一、client先去訪問zookeeper,從zookeeper裏面獲取meta表的region所在的regionserver節點信息
                0.96以前的版本除了meta表還有一個root表,root表存儲meta表位置信息,先經過zookeeper獲取root表位置
    在從root表中讀取meta表位置
    如今直接將meta表位置存入zookeeper中,減小會話次數
    
二、client向meta表的region所在regionserver發起讀請求,讀取meta表數據,獲取hbase集羣上全部用戶表的元數據
三、根據meta表中emp表的region的位置信息,client找到了當前須要訪問的emp表對應的region及所在的regionserver服務器
四、client向對應regionserver服務器發起讀請求
五、regionserver收到client訪問請求,在當前節點上找到emp表的region,並肯定目標store,先掃描memstore(由於數據此時可能存在memstore並未flush成storeFile),在掃描blockcache(讀緩存,近期已經讀過的數據會加載到該緩衝區中),最後再讀取storefile[HDFS]文件,
六、regionserver把數據響應給client

hbase表數據的寫流程:(根據某個rowkey向emp表寫數據)

一、client先去訪問zookeeper,從zookeeper裏面獲取meta表的region所在的regionserver節點信息
二、client向meta表的region所在regionserver發起讀請求,讀取meta表數據,獲取hbase集羣上全部用戶表的元數據
三、根據meta表中emp表的region的位置信息,client找到了當前須要訪問的emp表對應的region及所在的regionserver服務器
四、client向對應regionserver服務器發起寫請求   
五、regionserver收到client寫請求並響應,默認狀況下regionserver先把數據寫入目前region的HLog中,防止數據丟失
六、再把數據寫入到目標store下的memstore內存緩存區,memstore內存緩存區的默認大小128M 
    $ vi hbase-common/src/main/resources/hbase-default.xml      
    <name>hbase.hregion.memstore.flush.size</name> => 128M  
    
七、當Hlog和memstore都寫入成功,則這次數據寫入成功    
八、當memstore內的數據量達到閥值[128M],會把memstore裏面的數據Flush成storefile
九、當持續寫入數據,致使store下的storefile愈來愈多,當store文件數量或每間隔一段時間則會觸發compact合併操做,hbase會把每一個store下的全部的storefile合併成一個大的單一的storefile
十、當合並後的單個storefiles文件愈來愈大,達到必定閥值(10G或其餘小於10G的動態閾值)時會觸發split操做,region被一分爲二,並由master將新的region分配給regionserver節點管理

寫數據過程當中發送的三大機制flush、compaction、split

一、flush機制

當memstore內的數據量達到閥值[128M],會把memstore裏面的數據Flush成storefile
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
<description>
Memstore will be flushed to disk if size of the memstore
exceeds this number of bytes.  Value is checked by a thread that runs
every hbase.server.thread.wakefrequency.</description>
</property>
思考: 
        例如一個regionserver節點上同時管理了100個region,平均每一個region內有2個memstore,則該regionserver須要同時維護100*2=200 個  
        
        假如單個memstore內的數據量都沒有達到128M,可是都在100M以上,則此時全部的memstore內的緩存的數據量將超過  200*100M = 20G  
        
        佔用的內容空間是 regionserver -jvm -heap堆內存空間
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value></value>
<description>Maximum size of all memstores in a region server before new
    updates are blocked and flushes are forced. Defaults to 40% of heap (0.4).
    Updates are blocked and flushes are forced until size of all memstores
    in a region server hits hbase.regionserver.global.memstore.size.lower.limit.
    The default value in this configuration has been intentionally left emtpy in order to
    honor the old hbase.regionserver.global.memstore.upperLimit property if present.</description>
</property>
默認值爲 regionserver -jvm -heap堆內存空間的40%   
        當一個regionserver節點上的全部的memstore內緩存的數據量超過regionserver-jvm -heap堆內存空間的40%時,
        將會阻塞此regionserver節點上全部的region的更新操做
        
        如何配置 regionserver-jvm -heap堆內存空間 大小 
            $ vi conf/hbase-env.sh 
            export HBASE_HEAPSIZE=1G 
            正常大小都在  4G-20G
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value></value>
<description>Maximum size of all memstores in a region server before flushes are forced.
    Defaults to 95% of hbase.regionserver.global.memstore.size (0.95).
    A 100% value for this value causes the minimum possible flushing to occur when updates are
    blocked due to memstore limiting.
    The default value in this configuration has been intentionally left emtpy in order to
    honor the old hbase.regionserver.global.memstore.lowerLimit property if present.</description>
</property>
默認值爲 regionserver -jvm -heap堆內存空間的40%*0.95=38%  
        當一個regionserver節點上的全部的memstore內緩存的數據量超過regionserver -jvm -heap堆內存空間的38%時,
        會進行強制的flush操做

二、compaction機制

當flush到store下的storefile文件過多太小將影響到hbase後續的讀效率
    hbase後啓動compaction合併機制,最終將每一個store下的全部的storeFile文件合併爲一個大的單一的storeFile文件 
        
    compaction機制 分割兩個合併過程
        minor compaction --小合併  
            系統後臺會有一個專用的線程監控每一個store下的storeFile文件的數量
            當數量超過3個時會進行小合併 
            小合併只是一個歸類合併無用掃描讀取文件內的內容也沒有進行排序操做 
            該過程較快而且不會消耗集羣資源 
        major compaction --大合併 
            全部的region每隔3.5天~10.5天之間會進行一次大合併 
            大合併過程當中會加載讀取一個store下全部的storefile文件並進行如下操做
                會依據cell中的rowkey值的字典順序進行排序 
                會對打上’刪除‘標籤的cell或者過時的cell進行完全的刪除  
                    執行的刪除cell的操做並無將cell當即從storeFile文件中刪除
                    只是打上一個’刪除‘標籤,在大合併期間cell纔會被完全的刪除
<property>
        <name>hbase.hregion.majorcompaction</name>
        <value>604800000</value>
        <description>The time (in miliseconds) between 'major' compactions of all
        HStoreFiles in a region.  Default: Set to 7 days.  Major compactions tend to
        happen exactly when you need them least so enable them such that they run at
        off-peak for your deploy; or, since this setting is on a periodicity that is
        unlikely to match your loading, run the compactions via an external
        invocation out of a cron job or some such.</description>
    </property>
    <!-- 跳動係數
    最終region大合併間隔時間爲7*(1-0.5) ~ 7*(1+0.5)        3.5~10.5天 -->
    <property>
        <name>hbase.hregion.majorcompaction.jitter</name>
        <value>0.50</value>
        <description>Jitter outer bound for major compactions.
        On each regionserver, we multiply the hbase.region.majorcompaction
        interval by some random fraction that is inside the bounds of this
        maximum.  We then add this + or - product to when the next
        major compaction is to run.  The idea is that major compaction
        does happen on every regionserver at exactly the same time.  The
        smaller this number, the closer the compactions come together.</description>
    </property>
    <!-- 小合併 -->
    <property>
        <name>hbase.hstore.compactionThreshold</name>
        <value>3</value>
        <description>
        If more than this number of HStoreFiles in any one HStore
        (one HStoreFile is written per flush of memstore) then a compaction
        is run to rewrite all HStoreFiles files as one.  Larger numbers
        put off compaction but when it runs, it takes longer to complete.</description>
    </property>
    <property>
        <name>hbase.hstore.blockingStoreFiles</name>
        <value>10</value>
        <description>
        If more than this number of StoreFiles in any one Store
        (one StoreFile is written per flush of MemStore) then updates are
        blocked for this HRegion until a compaction is completed, or
        until hbase.hstore.blockingWaitTime has been exceeded.</description>
    </property>
    <property>
        <name>hbase.hstore.blockingWaitTime</name>
        <value>90000</value>
        <description>
        The time an HRegion will block updates for after hitting the StoreFile
        limit defined by hbase.hstore.blockingStoreFiles.
        After this time has elapsed, the HRegion will stop blocking updates even
        if a compaction has not been completed.</description>
    </property>
    <property>
        <name>hbase.hstore.blockingWaitTime</name>
        <value>90000</value>
        <description>
        The time an HRegion will block updates for after hitting the StoreFile
        limit defined by hbase.hstore.blockingStoreFiles.
        After this time has elapsed, the HRegion will stop blocking updates even
        if a compaction has not been completed.</description>
    </property>
    <property>
        <name>hbase.hstore.compaction.kv.max</name>
        <value>10</value>
        <description>How many KeyValues to read and then write in a batch when flushing
                or compacting.  Do less if big KeyValues and problems with OOME.
                Do more if wide, small rows.</description>
    </property>
大合併過程會消耗大量的hbase集羣資源(IO,cpu,內存 )  
            大合併能夠看作是以短時間的集羣資源消耗換取之後長期的讀效率的提高

三、split機制

當大合併後的某個region下的某個store下的storefile文件大小達到必定的閾值,則會引發該region的split分割 

0.94版本以前
    是一個定值
    單純使用hbase.hregion.max.filesize控制的是某個store下storeFile的大小,默認是10G時自動split分割
    默認配置文件hbase-common/src/main/resources/hbase-default.xml 
        $ echo $((10737418240/1024/1024/1024))    
    結論:
        對小表不友好
        數據量較小的表就有可能永遠不會觸發分裂,容易產生數據熱點
    
0.94版本-1.2版本
    由hbase.hregion.max.filesize和hbase.regionserver.region.split.policy共同控制
    split.policy的默認值 IncreasingToUpperBoundRegionSplitPolicy 底層是根據一個公式來計算是否要split
    公式:Min (R*R* hbase.hregion.memstore.flush.size , 「hbase.hregion.max.filesize」) 
        R爲同臺regionserver上同一個表的region的個數
        hbase.hregion.memstore.flush.size默認值是128M
        假若有一張表tableA,其多個region分佈在regionserver集羣上:
        若是在某一個regionserver上持有了tableA的1個region,則該regionserver上的tableA的region觸發分割時的大小 => min(10G,1*1*128M)=128M
        若是在某一個regionserver上持有了tableA的2個region,則該regionserver上的tableA的region觸發分割時的大小 => min(10G,2*2*128M)=512M
        … 3… =>:min(10G,3*3*128M)=1152M
        ……
        ……
        … 9… =>min( 10G ,9*9*128M= 10.125G )=>10G              
        結論:
            同一個regionserver節點上持有某張表的region數量達到9個時,則該表的region分割觸發值纔開始按照hbase.hregion.max.filesize最大值10G進行分割
            這種切分策略很好的彌補了ConstantSizeRegionSplitPolicy的短板,可以自適應大表和小表
            可是不少小表會在大集羣中產生大量小region,最終表數據在集羣中過於分散
                例如節點數量爲10個,一個表最終達到分割閾值10G前將會有產生90個region,前期分割過頻繁
            
1.2版本 
    由hbase.hregion.max.filesize和hbase.regionserver.region.split.policy共同控制
    split.policy默認值改成SteppingSplitPolicy
    控制策略: 
        某臺regionserver上持有某個表的region個數爲1個時=》split切分閾值爲flush size * 2
        其餘狀況爲hbase.hregion.max.filesize=》10G 
    結論: 
        彌補IncreasingToUpperBoundRegionSplitPolicy帶來的問題
        小表前期隨數據量增長不會過分過多分割
            例如節點數量爲10個,一個表最終達到分割閾值10G前將會有產生10個region
            每臺上存在1個region後,之後分割閾值即按照10G 執行 

        
region在分割時: 
    消耗集羣資源 
    region在split時會短暫的offline下線致使客戶端訪問不穩定 
    
    
爲何在建表時表的列簇的數量不宜過多 ??? 
    由於一個region中store的數量等於該表的列簇的數量 
    region的split分割的依據是region下的某個store下的storeFile文件的大小 
    若是一個region下有多個store,其中一個store下的storeFile文件大小逐漸變大
    而其餘的store下的數據量比較小
    若是數據量較大的store下的文件大小達到閾值則會觸發整個region的split分割 
    數據量少的store會被迫分裂在多個region中,致使數據過於分散增長hbase對該store下數據的檢索成本

hbase java api

使用java 編程對hbase進行增刪改查操做

一、配置maven工程依賴

1)關閉eclipse ,併合並repository目錄  
    
2)新建maven工程或使用以前的maven工程並再pom.xml文件中添加如下依賴
<!-- hadoop start -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.6.0</version>
        </dependency>
        <!-- hadoop end -->
        <!-- hbase start -->
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.0</version>
        </dependency>
        <!-- hbase end -->
        <!-- hive start -->
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>1.1.0</version>
        </dependency>
3)下載hadoop及hbase的配置文件並加入到maven工程中 

    在maven工程中建立source funder 
        src/main/resources  
    將hadoop及hbase的配置文件加入到src/main/resources下

二、hbase java api演示

如何經過hbase java api建立表、刪除表、修改表

http://hbase.apache.org/book.... =》95. Examples

package com.example.hbase.admin;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.io.compress.Compression.Algorithm;

public class Example {

  private static final String TABLE_NAME = "MY_TABLE_NAME_TOO";
  private static final String CF_DEFAULT = "DEFAULT_COLUMN_FAMILY";

  public static void createOrOverwrite(Admin admin, HTableDescriptor table) throws IOException {
    if (admin.tableExists(table.getTableName())) {
      admin.disableTable(table.getTableName());
      admin.deleteTable(table.getTableName());
    }
    admin.createTable(table);
  }

  public static void createSchemaTables(Configuration config) throws IOException {
    try (Connection connection = ConnectionFactory.createConnection(config);
         Admin admin = connection.getAdmin()) {

      HTableDescriptor table = new HTableDescriptor(TableName.valueOf(TABLE_NAME));
      table.addFamily(new HColumnDescriptor(CF_DEFAULT).setCompressionType(Algorithm.NONE));

      System.out.print("Creating table. ");
      createOrOverwrite(admin, table);
      System.out.println(" Done.");
    }
  }

  public static void modifySchema (Configuration config) throws IOException {
    try (Connection connection = ConnectionFactory.createConnection(config);
         Admin admin = connection.getAdmin()) {

      TableName tableName = TableName.valueOf(TABLE_NAME);
      if (!admin.tableExists(tableName)) {
        System.out.println("Table does not exist.");
        System.exit(-1);
      }

      HTableDescriptor table = admin.getTableDescriptor(tableName);

      // Update existing table
      HColumnDescriptor newColumn = new HColumnDescriptor("NEWCF");
      newColumn.setCompactionCompressionType(Algorithm.GZ);
      newColumn.setMaxVersions(HConstants.ALL_VERSIONS);
      admin.addColumn(tableName, newColumn);

      // Update existing column family
      HColumnDescriptor existingColumn = new HColumnDescriptor(CF_DEFAULT);
      existingColumn.setCompactionCompressionType(Algorithm.GZ);
      existingColumn.setMaxVersions(HConstants.ALL_VERSIONS);
      table.modifyFamily(existingColumn);
      admin.modifyTable(tableName, table);

      // Disable an existing table
      admin.disableTable(tableName);

      // Delete an existing column family
      admin.deleteColumn(tableName, CF_DEFAULT.getBytes("UTF-8"));

      // Delete a table (Need to be disabled first)
      admin.deleteTable(tableName);
    }
  }

  public static void main(String... args) throws IOException {
    Configuration config = HBaseConfiguration.create();

    //Add any necessary configuration files (hbase-site.xml, core-site.xml)
    config.addResource(new Path(System.getenv("HBASE_CONF_DIR"), "hbase-site.xml"));
    config.addResource(new Path(System.getenv("HADOOP_CONF_DIR"), "core-site.xml"));
    createSchemaTables(config);
    modifySchema(config);
  }
}

做業:

region的結構及region相關概念  --簡述
hbase表數據讀寫流程及寫過程當中的三種機制  --簡述 
hbase java api的使用  -- 提交

day3:

hbase與MapReduce集成使用  

hbase與hive集成使用  

hbase與sqoop集成使用    

hbase與Hue集成使用

hbase與MapReduce集成使用

利用MapReduce並行計算框架對hbase表數據進行讀寫操做         
MapReduce程序 
    使用hbase自帶mr-jar功能包 lib/hbase-server-1.2.0-cdh5.14.2.jar,實現向hbase中批量的導入或統計數據  
    自定義MapReduce程序向hbase表實現讀寫操做

1、使用使用hbase自帶MapReduce功能 jar包

lib/hbase-server-1.2.0-cdh5.14.2.jar              
    藉助此jar包中的MapReduce程序能夠實現利用MapReduce並行計算框架

一、使用自帶的MapReduce功能jar包須要進行環境配置

配置jar包中的MapReduce程序在讀寫hbase表時做爲一個客戶端所須要的hbase的jar包依賴 
使這些MapReduce程序在執行時能夠在當前環境中加載讀取到hbasejar包

找一個固定的會話窗口執行命令

$ export HBASE_HOME=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2    
$ export HADOOP_HOME=/opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2
$ bin/hbase  mapredcp  -- 返回MapReduce程序在讀寫hbase表數據時所須要的hbase的jar包的本地路徑 


$ export HADOOP_CLASSPATH=`bin/hbase  mapredcp`
將MapReduce程序讀寫hbase表數據時所須要的jar包本地路徑加入到hadoop的環境變量中。以後MapReduce在執行時會自動獲取HADOOP_CLASSPATH的值並從中獲取所需的hbase jar包的路徑 

$ echo ${HADOOP_CLASSPATH}   驗證

二、測試執行hbase自帶的MapReduce-jar包程序

$ /opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2/bin/yarn jar /opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2/lib/hbase-server-1.2.0-cdh5.14.2.jar
An example program must be given as the first argument.
Valid program names are:
CellCounter: Count cells in HBase table. 統計hbase表cell詳情
WALPlayer: Replay WAL files.
completebulkload: Complete a bulk data load.
copytable: Export a table from local cluster to peer cluster. 利用MapReduce程序實現拷貝hbase表
export: Write table data to HDFS. 利用MapReduce程序從hbase表中導出數據
exportsnapshot: Export the specific snapshot to a given FileSystem.
import: Import data written by Export. 利用MapReduce程序向hbase導入數據
importtsv: Import data in TSV format. 利用MapReduce程序向hbase導入tsv格式數據
rowcounter: Count rows in HBase table. 利用MapReduce程序統計行

1)利用hbase自帶的MapReduce程序統計hbase表的行

2)利用hbase自帶的MapReduce程序實現向hbase表中批量導入數據 --- 直接導入方式

在hbase 上建立目標表 
    > create 'student' ,'info'  
    
建立tsv測試文件並上傳到hdfs上 
    $ vi student.tsv    
        10003   tom     boy     20
        10004   lili    girl    19
        10005   lio     boy     21
        10007   litao   boy     18
        10008   mary    girl    20
        
    $ bin/hdfs dfs -put student.tsv /user  
        
執行導入MapReduce任務 

    $ /opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2/bin/yarn jar /opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2/lib/hbase-server-1.2.0-cdh5.14.2.jar  \
    importtsv \
    -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:sex,info:age   \
    student \
    hdfs://192.168.134.101:8020/user/student.tsv

3)使用bulk load方式將一個tsv格式的文件導入到hbase表中

直接導入方式: 
    regionserver響應客戶端的寫請求-》regionserver將數據寫入Hlog-》寫入memstore中=》從memstore從flush成storeFile文件-》compaction合併
    
    
bulk load方式導入: 
    先使用MapReduce程序將到導入的tsv文件直接轉化爲最終的storeFile文件並存儲到hdfs上的某個目錄下=》將最終的storeFile文件寫入(移動)到目標表的store下
    
    
使用bulk load方式導入的好處: 
    bulk load方式導入能夠避開直接導入數據時的hbase集羣的資源消耗(內存、io、cpu)(避開了數據先寫入hlog-》memstore-》flush等),將tsv文件轉化爲storeFile文件的工做壓力轉移給MapReduce分佈式實現,最終hbase只需將轉化後的storeFile文件移動寫入到目標表中 


            
            
建立新的目標表 
        > create 'student1','info'


        
過程1:文件格式轉化(將tsv文件轉化爲storeFile文件)

        
    執行轉化文件格式任務     
        -Dimporttsv.bulk.output=/path/for/output  在直接導入方式基礎上次參數則當前MapReduce任務將會把要導入到hbase表中的tsv文件轉換爲Hfile文件,而不是直接寫入到hbase表 
        /path/for/output爲由MapReduce轉化後的Hfile文件在hdfs上的存儲路徑 
        
        yarn jar /opt/modules/hbase-1.2.0-cdh5.14.2/lib/hbase-server-1.2.0-cdh5.14.2.jar importtsv -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:sex,info:age -Dimporttsv.bulk.output=/path/for/output student1 hdfs://centos01:8020/user/student.tsv 
        
    現象: 
        此任務是MapReduce任務 
        > scan 'student1'  此時數據還未寫入到hbase表中  
        /path/for/output/info  --- Hfile文件  

        

過程2:將由MapReduce轉化好的Hfile文件寫入(移動)到目標region的store下 

    用completebulkload完成bulkload上傳

    yarn jar /opt/modules/hbase-1.2.0-cdh5.14.2/lib/hbase-server-1.2.0-cdh5.14.2.jar completebulkload /path/for/output student3


    現象: 
        此任務不是MapReduce任務,此過程由hbase自行完成  
        > scan 'student1'   數據已經寫入 
        /path/for/output/info  --- Hfile文件已經消失
        /hbase/data/default/student1/1b9a3a4e47cc3859a0909dc096685260/info -出現新的文件

2、自定義MapReduce程序完成讀寫hbase表數據

需求:     
    自定義MapReduce程序將hbase中的student表中的10004行到10007行之間的info:name和info:age 寫入到 hbase的user表中 basic:XM ,basic:NL,rowkey不變  

    
    
 ReadStudentMapper extends  TableMapper<ImmutableBytesWritable, Put> 
    若是map從hbase表中讀數據則自定義的Mapper類須要繼承TableMapper  
    <ImmutableBytesWritable, Put>
        聲明的是map端輸出的key和value類型  
        ImmutableBytesWritable是對字節數組的封裝類並繼承了WritableComparable類型

        
        
map(ImmutableBytesWritable key, Result value, Context context)        
    ImmutableBytesWritable key  - 是從目標表中讀取到的某行數據的rowkey值    
    Result value  -- 是從目標表中讀取到的對應行全部cell的封裝實例
package com.hadoop.hbase;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class Student2UserMapReduce extends Configured implements Tool {

    // Step 1 : Mapper
    public static class ReadStudentMapper extends  TableMapper<ImmutableBytesWritable, Put> {

        @SuppressWarnings("deprecation")
        @Override
        protected void map(ImmutableBytesWritable key, Result value,
                Context context) throws IOException, InterruptedException {

            // create put
            Put put = new Put(key.get()); //直接引用原表中的rowkey做爲目標表的rowkey
            // 將student表中該行中的info:name info:age 兩列數據過濾數並添加put實例中 
            for (Cell cell : value.rawCells()) {
                // get CF:info 過濾出特定列簇由於可能有多個列簇
                if ("info".equals(Bytes.toString(CellUtil.cloneFamily(cell)))) {
                    // add name
                    if ("name".equals(Bytes.toString(CellUtil
                            .cloneQualifier(cell)))) {
                        put.add(Bytes.toBytes("basic"), Bytes.toBytes("XM"),
                                CellUtil.cloneValue(cell));
                    }
                    // add age
                    else if ("age".equals(Bytes.toString(CellUtil
                            .cloneQualifier(cell)))) {
                        put.add(Bytes.toBytes("basic"), Bytes.toBytes("NL"),
                                CellUtil.cloneValue(cell));
                    }
                }
            }

            // context output
            context.write(key, put);
        }
    }

    // Step 2 : Reducer

    public static class WriteUserReducer extends
            TableReducer<ImmutableBytesWritable, Put, NullWritable> {

        @Override
        protected void reduce(ImmutableBytesWritable key, Iterable<Put> values,
                Context context) throws IOException, InterruptedException {

            for (Put put : values) {
                context.write(NullWritable.get(), put);
            }

        }

    }

    // Step 3 : Driver
    public int run(String[] args) throws Exception {
        // 1) Configuration
        Configuration conf = this.getConf();
        // 2) create job
        Job job = Job.getInstance(conf, this.getClass().getSimpleName());
        job.setJarByClass(Student2UserMapReduce.class);

        // 3) set job
        // set scan 設置map端的查詢條件 ,
        Scan scan = new Scan();
        scan.setStartRow(Bytes.toBytes("10004"));
        scan.setStopRow(Bytes.toBytes("10007"));
        scan.addFamily(Bytes.toBytes("info"));  //只掃描特定的列簇
        // setMapper
        TableMapReduceUtil.initTableMapperJob(
                "student", // input table
                scan, // Scan instance
                ReadStudentMapper.class, // mapper class
                ImmutableBytesWritable.class, // mapper output key
                Put.class, // mapper output value
                job
                );

        // setReducer
        TableMapReduceUtil.initTableReducerJob(
                "user", // output table
                WriteUserReducer.class, // reducer class
                job);

        // set reduce nums
        job.setNumReduceTasks(1); // at least one, adjust as required

        boolean isSuccess = job.waitForCompletion(true);
        if (!isSuccess) {
            throw new IOException("error with job!");
        }
        return isSuccess ? 0 : 1;

    }

    public static void main(String[] args) throws Exception {
        Configuration conf = HBaseConfiguration.create();
        int status = ToolRunner.run(//
                conf, //
                new Student2UserMapReduce(), //
                args //
                );
        System.exit(status);

    }

}
測試執行 
    在hbase上提早建立目標表 
         create 'user','basic'
    導出jar包並上傳到linux集羣並提交執行
        $ bin/yarn jar jars/s2u.jar  
    檢查執行結果
        > scan 'user'

如何爲hbase的master節點配置備份節點(tar包安裝方式搭建的集羣)  HMaster HA

防止master單節點故障
    雖然hbase表數據的讀寫不通過master,master宕機一段時間內集羣還能夠正常讀寫,當時仍是有不可或缺的做用
如何實現
    Master HA的實現是藉助於zookeeper基於觀察者模式監控master狀態
    一旦active master節點宕機後zookeeper會第一時間感知並從其餘的多個備份master節點(backup-master)中選舉出一個master做爲後續的active master節點

一、搭建Apache Hadoop集羣並啓動

$ sbin/start-dfs.sh              --啓動HDFS

二、搭建zookeeper集羣並啓動

$ bin/zkServer.sh start

三、部署HBase集羣

先在某臺節點上操做,完成後再拷貝給其餘節點
    $ vi conf/regionservers  //添加regionserver服務器主機名或IP
    $ vi conf/backup-masters     // 在HABASE_HOME/conf目錄下添加backup-masters文件,裏面定義哪些服務器是備用master
    $ vi conf/hbase-site.xml   //向hbase-site.xml中添加配置信息
<property>  
                <name>hbase.rootdir</name>  
                <value>hdfs://hadoop-senior01.bf.com:8020/hbase</value>
            </property>
            <property>
                <name>hbase.cluster.distributed</name>
                <value>true</value>
            </property>            
            <property>
                <name>hbase.zookeeper.quorum</name>
                <value>blue01.mydomain,blue02.mydomain,blue03.mydomain</value>
            </property>
            <property>
                <name>hbase.master</name>
                <value>hdfs://192.168.134.101:60000</value>
            </property>
            
            <name>hbase.master</name>  => 聲明集羣中的哪臺服務器做爲最初的active master節點
拷貝此臺hbase安裝目錄到其餘兩個節點:
    $ scp -r hbase-0.98.6-hadoop2/ blue02.mydomain:/opt/modules/
    $ scp -r hbase-0.98.6-hadoop2/ blue03.mydomain:/opt/modules/

四、啓動hbase服務進程

$ bin/start-hbase.sh  //在<name>hbase.master</name> 定義的服務器上執行該命令

五、觀察每一個服務器的角色

啓動hbase服務後,會發現除<name>hbase.master</name> 定義的服務器上有Hmaster進程外
在conf/backup-masters內定義的服務器上也有master進程
active  master默認在<name>hbase.master</name> 定義的服務器上

六、測試
http://192.168.122.128:60010/master-status

能夠看到:
    Master 192.168.122.128
    Backup Masters 192.168.122.129

關閉192.168.122.128服務器上的HMaster:
    $ kill -9 12978
能夠看到
    Masters 192.168.122.129

hbase與hive集成使用

目的: 
    利用hive 的分析功能接口,使用hql語句分析hbase表中的數據 
    
hbase自己是不支持sql查詢語句,僅僅支持簡單的 get scan 查詢數據 
    聚合查詢(max avg min max)、分組、聯合、子查詢 --- 不支持  
    
如何實現使用sql或類sql語句分析hbase表中數據呢?(sql on hbase ) 
    與hive進行集成
        在hive端建立一個與hbase表的關聯映射表
        使用hive sql語句間接分析hbase表中的數據 
        hive sql =》hive-》MapReduce程序=》比較慢適合離線分析
    使用phoniex插件 
        phoniex插件是專爲hbase開發的一款第三方插件,Apache TM   
        經過此插件可使用標準的sql語句分析hbase表中的數據 
        sql =》phoniex插件 =》轉化爲Get或Scan查詢 =》很是快能夠實現實時交互查詢

============================hbase與hive集成測試===================

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'   
    建立hive與hbase的管理映射表
    hive與hbase以前的數據映射通訊依靠的是HBaseStorageHandler類 
    hive-hbase-handler-1.1.0-cdh5.14.2.jar

官方部署使用參考資料:

官方文檔步驟在hive的官網上: 
    https://cwiki.apache.org/confluence/display/Hive/Home#Home-UserDocumentation

一、hive-env.sh中聲明HBASE_HOME路徑

hive須要獲取hbase的配置文件及lib目錄下的jar包

export HBASE_HOME=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2

二、修改hive-site.xml

聲明zookeeper的地址,根據本身的集羣有幾個聲明幾個;
    hive分析的數據在hbase裏,hive關聯hbase須要聯繫zookeeper
<property>
    <name>hbase.zookeeper.quorum</name>
    <value>bigdata01.project.com</value>
</property>

三、測試

在hive端的操做
在hive端執行hql去映射並分析hbase上已經存在的一張表
    

實現:
    HBase中已經存儲一張student信息表
    在hive建立一張與hbase上的student表的關聯映射表
    使用hql分析hive端此關聯表中的數據

1)建立外部關聯映射表

需求是使用hql語句去分析hbase中已經有了一張包含數據的表
hive須要建立一個外部表與之映射
假如僅僅是但願使用hql語法分析hbase表的數據
    須要建立一個外部表
    在hive端刪除此關聯表時不會影響hbase表的數據
    
$ bin/hive --service metastore &

CREATE EXTERNAL TABLE hive_hbase_student (
id int,
name string,
sex string,
age string
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:name,info:sex,info:age")
TBLPROPERTIES ("hbase.table.name" = "student");

說明:

第一個:key是固定格式,默認爲hbase的rowkey,不須要指定列簇;
其餘字段會與hive表的字段順序一一對應映射;
能夠只映射hbase表中的部分列

2)驗證:

select * from hive_hbase_student ;

總結:

執行建立關聯表時包找不到類異常說明hive缺乏hbase某些jar包
    通常建立hive與hbase表映射表都是外部表
    由於需求一般都是使用hql分析hbase上已經有數據的表 
    在hive端刪除映射表時hbase中表不會被同步刪除;

思考:

在hive端向關聯表中中插入數據或load加載數據後hbase表中數據是否會同步更新?
可否經過hive端間接向hbase中導入/插入數據?

測試:

1)向hive_hbase_student表中load加載數據

$ vi student01.txt //新建測試數據
20111 tom1 boy 21
20112 lio1 boy 20

load data local inpath '/opt/cdh-5.14.2/hive-1.1.0-cdh5.14.2/student02.txt' into table hive_hbase_student ;  
報錯:
    非本地表不能使用load加載數據
    不能使用load從本地加載數據到hive與hbase的映射表中(爲非本地表)
解決: 
    先建立一個臨時表,使用load導入本地數據到臨時表中
    而後在經過insert into 語句向關聯表中插入數據
    hive端支持insert語句向hive與hbase的關聯表中插入數據

2)向hive_hbase_student表中inster插入數據

CREATE TABLE temp3(
id int,
name string,
sex string,
age string
)
row format delimited fields terminated by 't';

load data local inpath '/opt/cdh-5.14.2/hive-1.1.0-cdh5.14.2/student02.txt' into table temp3 ;

insert into table hive_hbase_student select * from temp3 ;

驗證:

select * from hive_hbase_student ;
scan 'student'

結論:

數據插入成功
能夠經過hive做爲接口向hbase表中插入數據 
能夠經過此途徑快速將hive表數據插入到hbase表

hbase與sqoop集成使用

使用sqoop將RDBMS中的數據導入到hbase表中 
sqoop -》 hdfs 、hive、hbase

一、修改sqoop的配置文件

#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2

#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2

#set the path to where bin/hbase is available
export HBASE_HOME=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2

#Set the path to where bin/hive is available
export HIVE_HOME=/opt/cdh-5.14.2/hive-1.1.0-cdh5.14.2

#Set the path for where zookeper config dir is
export ZOOCFGDIR=/opt/cdh-5.14.2/zookeeper-3.4.5-cdh5.14.2

二、在mysql上建立一個測試表(訂單表)

> create database my_db ;
> use my_db; 
將sql文件上傳到linux上
> source  /opt/data/so_detail.sql ;

三、執行sqoop命令將訂單表表數據導入到hbase表中

bin/sqoop import --connect jdbc:mysql://centos01:3306/mydb --username root --password 123456 --table so_detail --columns "id, product_id, price" --hbase-table "sqoop" --hbase-create-table --column-family "info" --hbase-row-key "id" --num-mappers 1
HBase arguments:
   --column-family <family>    Sets the target column family for the
                               import
   --hbase-bulkload            Enables HBase bulk loading
   --hbase-create-table        If specified, create missing HBase tables
   --hbase-row-key <col>       Specifies which input column to use as the
                               row key
   --hbase-table <table>       Import to <table> in HBase

Caused by: java.lang.ClassNotFoundException: org.json.JSONObject

將java-json.jar包上傳到sqoop的lib目錄下

hbase與Hue集成使用

經過hue 的web 平臺實現對hbase表數據的增刪改查操做

一、啓動hbase 的thrift server服務進程

hue須要經過hbase的thrift server進行底層的信息交互 
$ bin/hbase-daemon.sh start thrift

二、修改hue的配置文件

$ vi desktop/conf/hue.ini
1241行 
  # If using Kerberos we assume GSSAPI SASL, not PLAIN.
  hbase_clusters=(Cluster|192.168.134.101:9090)

  # HBase configuration directory, where hbase-site.xml is located.
  hbase_conf_dir=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2/conf
啓動hue server 

針對表的操做 
    刪除表 
    建立表 
    啓動或禁用表 
針對表數據的操做 
    查看錶數據 
        篩選查看 
        排序查看 
    刪除cell或添加cell 
    修改cell值 
    刪除行或添加行 
    加載數據

hbase 表的設計

表的預分區的設計

默認建表時不進行預分區則表的region只有1個,而且該region沒有start 和 end key ,後續向該表中寫數據時不管rowkey如何設定則數據都會寫入到該表的惟一的region中 ,該region持有的數據量達到必定的閾值則會被動split分割。
此過程當中會有另個問題出現
    一、在region沒有split以前只有regionserver節點在響應客戶得讀寫請求(數據熱點、傾斜產生)  
        數據熱點、傾斜 =》某時刻大量的讀寫操做都集中在hbase集羣上某1臺或幾臺regionserver節點上
    二、region的被動split分割會消耗集羣的資源,而且會短暫的offline下線,致使region訪問不穩定

如何解決 
    在建立表對錶進行預分區操做,將表直接生成多個region ,而且指定每一個region的key的範圍

建立表預分區的方式1:

create 't11', 'info1', SPLITS => ['10', '20', '30', '40']

Name    Region Server    Start Key    End Key    Locality    Requests
ns1:t11,,1557480097230.eb7d269860267eb22376c716f6e68864.    centos01:60030        10    0.0    0
ns1:t11,10,1557480097230.268f79be12cd6a1f3307138180ed092e.    centos01:60030    10    20    0.0    0
ns1:t11,20,1557480097230.c1b7ba5c4b5be9f01511d624bfde39fc.    centos01:60030    20    30    0.0    0
ns1:t11,30,1557480097230.c3f164315567ab636f264601edc058f4.    centos01:60030    30    40    0.0    0
ns1:t11,40,1557480097230.2f8719d1b3c38f8ec83eec51921acd5a.    centos01:60030    40        0.0    0

插入查看效果

put 'ns1:t11', '2502', 'f1:age', '25' --> region3

結論:前綴匹配、左閉右開

建立表預分區的方式2:
$ vi splits.txt
create 't12', 'info1', SPLITS_FILE => '/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2/splits.txt'

表的rowkey的設計

hbase表數據的讀寫默認都是基於rowkey(hbase的二次索引)
hbase表的數據最終都是以rowkey的字典順序排序存儲  
一張hbase的表的rowkey的設計好壞直接影響到後續對此表的讀寫效率  


舉例說明 
    有一張t11,建表時已經進行預分區  
    有一批1千萬條的數據須要插入到t11表中   
    1千萬條的數據的rowkey設計:rowkey=時間戳_2位隨機數字 
            1544085846_26  xxx  xx  xx   
            1544085999_33  xxx  xx  xx  
            1544087902_62  xxx  xx  xx  
            ……  
    結果: 
        根據rowkey與region的key的前綴匹配結果數據都會寫入到region02 
        會出現數據熱點及被動的split分割問題 
        
    如何解決 
        rowkey設計 
            兩位隨機數字(00-50)_時間戳
            散列的分佈式的插入到每個region中  
            
            

rowkey設計原則 
    rowkey必須惟一  
    rowkey的長度官方建議10-100字節之間,實際使用 rowkey的長度 不超過16字節 
        rowkey值、列簇、列名存在與每個cell單元格中   
        rowkey過大的影響
            浪費存儲空間 
            將會致使索引數據變大,影響到hbase表的讀寫效率 
    rowkey設計時要考慮集羣在讀寫數據時避免數據熱點產生,不建議所有使用隨機數字
    最重要rowkey的設計要考慮實際的業務場景  
    
rowkey設計時能夠選擇的思路 
    生成隨機數  
        固定長度的隨機數字(crc32/md5)  
            一般不會將rowkey所有使用隨機數,會拼接一些與業務需求相關的數據 

    與業務需求相關的數據+固定長度的隨機數字 
        例如:日期(業務需求相關的數據)_固定長度的隨機數字  
            
        訂單數據的rowkey設計 
            ……
            2018101012_r4      55.0    4354664        2       
            2018111012_ry      55.0    4354664        2       
            2018111115_uu      55.0    4354664        2   
            2018111709_ii      55.0    4354664        2   
            2018120311_hu      55.0    4354664        2                   
            ……  
            
        能夠根據客戶提供的日期範圍快速查詢到本身的訂單或消費或話單數據等  
        
            客戶要查詢本身在11月份期間的訂單數據
            
                Scan san = new Scan () ; 
                scan.setStaryKey(20181111);
                scan.setStopKey(20181112);
            
    翻轉字符串  
        假如業務須要將一組連續的數字做爲rowkey  
            連續的數字的特色 
                低位變化快高位變化慢  
                好比時間戳、日期  
            
            翻轉前的rowkey 
                1544085846  
                1544085999  
                1544087902   
                ……

電信公司用戶話單記錄表的rowkey設計案例

表的數據量很是大     
    天天新增話單記錄 160億條  
        
業務需求: 
    要求客戶能夠根據本身提供的電話號碼及時間範圍快速查詢本身的話單記錄信息 
    若是爲全部用戶的話單記錄表設計rowkey? 
    
思路: 
    每一個用戶的話單記錄存在一個hbase的一個大表中  
        我的查詢的話單記錄信息量比較少(1我的1個月的話單記錄600條),而hbase大表的數據量 160億條*365天  
            但願每一個客戶的話單記錄在hbase大表中連續存儲(儘可能存儲在同一個region中)仍是散列在多個region中存儲呢?
            
        爲了減小regionserver節點的響應次數,減小regionserver節點檢索數據時的會話及檢索次數
        須要將用戶的數據儘量連續存儲在同一個region中
        若是要查詢100億條數據,最好是散列存儲以便分佈式查詢  
        
        又由於需求中須要以用戶提供的日期範圍查詢話單記錄,rowkey中須要包含日期數據以便進行前綴匹配查詢  
        
    rowkey最終設計 
        電話號碼_日期_隨機數字 
            電話號碼=》在前能夠保證每一個用戶的話單記錄在hbase表中連續存儲 
            日期=》放中間能夠知足用戶根據提供的日期範圍匹配查詢  
            隨機數字=》爲了不rowkey重複

13600000000_20180519_34 xx xx xx xx
13600000000_20180621_55 xx xx xx xx
13600000000_20180621_30 xx xx xx xx
13600000000_20180621_39 xx xx xx xx
13600000000_20180626_36 xx xx xx xx
13600000000_20180629_34 xx xx xx xx
13600000000_20180711_34 xx xx xx xx
13600000000_20180719_34 xx xx xx xx
13600000000_20180819_34 xx xx xx xx

例如電話號碼爲13600000000用戶要求查詢本身在6月份的話單記錄 
    
    例如電話號碼爲13600000000用戶要求查詢本身在6月21號的話單記錄

hbase 表的屬性(列簇的屬性)

{
NAME => 'info1', 列簇名稱
BLOOMFILTER => 'ROW', 過濾器類型
VERSIONS => '1', 該列簇下的cell最大可保留版本數量
KEEP_DELETED_CELLS => 'FALSE', 打上刪除標籤的cell在大合併被完全刪除前能夠被訪問,FALSE不能夠
DATA_BLOCK_ENCODING => 'NONE', 數據塊的編碼方式
TTL => 'FOREVER', 數據存活期,該列簇下的數據的有效期,到期的cell和被打上刪除標籤的cell會在大合併期間完全刪除
COMPRESSION => 'NONE', 針對該列簇下的Hfile文件的壓縮格式
MIN_VERSIONS => '0', cell中最少保留版本數量
BLOCKSIZE => '65536'(字節),

Hfile文件中數據塊的默認大小,默認大小是64kb,
不一樣的業務需求場景須要設置不一樣的數據塊大小以提升讀性能減小延遲率 
    對於以Get讀(某一行內)爲主的業務場景=》適當減少數據塊的默認大小
    對於以Scan讀(大範圍讀取)爲主的業務場景=》適當增大數據塊的默認大小    
請描述下Hfile文件中的數據塊的相關概念及結構????? 
hfile的block塊

REPLICATION_SCOPE => '0'
BLOCKCACHE => 'true',

讀緩存  
若是該列簇的BLOCKCACHE屬性的值爲true,則該列簇下的storeFile文件中的數據在被讀取後能夠進入到該讀緩存中 ,目的是爲了加快下次讀取一樣數據時的速度

IN_MEMORY => 'false',

blockcache中的三個分區:single、multi、inmemory
讀緩存中的激進內存
表示在blockcache讀緩存中享有較高的等級 
若是一個列簇的IN_MEMORY屬性值爲true,則該列簇下的數據會被持久加載到blockcache讀緩存區中的In-memory區中    
desc 'hbase:meta'   meta元數據表的該屬性值默認爲true

}

COMPRESSION壓縮

是針對某個表某個列簇下的Hfile文件進行的壓縮配置 
默認支持的壓縮格式有 
    Block Compressors
        none  -- 默認  
        Snappy
        LZO
        LZ4
        GZ
企業中最常使用的壓縮格式爲Snappy壓縮 
    在各類壓縮格式中Snappy壓縮的編碼和解碼的綜合效率是最高的,對cpu消耗最小的 
配置Hfile文件的壓縮好處: 
    節省hdfs的存儲空間
    節省磁盤io及網絡io

如何爲hbase的表數據文件Hfile文件配置Snappy壓縮

1)由於hbase的數據最終是存儲在hadoop上,因此須要先確保hadoop支持壓縮

$ bin/hadoop checknative // 檢查Hadoop支持的壓縮
/opt/modules/hadoop-2.5.0-cdh5.3.6/lib/native  //hadoop的壓縮依靠native包的支持

2)檢查當前hbase是否能夠引用Hadoop的壓縮格式

$ bin/hbase --config conf/ org.apache.hadoop.util.NativeLibraryChecker
    //http://hbase.apache.org/book.html   搜索NativeLi

3)配置hbase支持Snappy壓縮

配置hbase能夠引用hadoop的native庫

下載hadoop-snappy-0.0.1-SNAPSHOT.jar 包,上傳並放入$HBASE_HOME/lib下
$ export HBASE_HOME=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2
$ export HADOOP_HOME=/opt/cdh-5.14.2/hadoop-2.6.0-cdh5.14.2
$ mkdir $HBASE_HOME/lib/native
$ ln -s $HADOOP_HOME/lib/native $HBASE_HOME/lib/native/Linux-amd64-64

將Hadoop的native包建立連接到hbase的native下並命名爲Linux-amd64-64
其實hbase的native使用的就是Hadoop的native包

4)重啓服務進程

重啓hadoop及hbase服務進程

5)使用壓縮
create 't13' ,{NAME => 'f1', VERSIONS => 5,COMPRESSION=>'SNAPPY'} //若是報錯考慮Hadoop進程是否剛纔替換native後重啓過
put 't13','1001','f1:name','zhangsan'
flush 't13'

BLOCKCACHE讀緩存

總結每一個regionserver節點須要維護的內存空間 
    memstore  
        寫緩存,加快寫速度  
        每一個regionserver節點上須要維護多少個memstore空間=》n個  
        當個memstore的空間的閾值=》128M  
        整個regionserver節點上的總的memstore的空間的默認閾值=》regionserver-jvm-heap空間的40% 
                
    blockcache
        讀緩存,用來加快讀速度 
        每一個regionserver節點上須要維護多少個blockcache空間=》1個  
        單個regionserver節點上的blockcache的緩存空間的閾值 
             <name>hfile.block.cache.size</name> => 40%
<property>
    <name>hfile.block.cache.size</name>
    <value>0.4</value>
    <description>Percentage of maximum heap (-Xmx setting) to allocate to block cache
        used by HFile/StoreFile. Default of 0.4 means allocate 40%.
        Set to 0 to disable but it's not recommended; you need at least
        enough cache to hold the storefile indices.</description>
  </property>
blockcache空間的最大值爲regionserver-jvm-heap空間的40%   
            
    加入blockcache讀緩存後的讀數據流程
        向目標region下的 對應的store下的memstore中掃描數據
        再到blockcache中掃描數據  
        最終到storefile中讀取數據 
        若是該列簇的BLOCKCACHE屬性值爲true,則讀取的數據會被加載到blockcache  

根據讀寫要求能夠設置memstore和blockcache的大小,若注重讀,可將blockcache設大些,若注重寫,可將memstore設大些,總之blockcache+memstore要<=80%
        
LRU緩存淘汰機制(近期最少使用算法) 
    爲了保證blockcache讀緩存空間的高效使用 
        blockcache空間中的single區和multi區實行LRU緩存淘汰機制 
        當整個blockcache讀緩存空間被佔用量達到85%時纔會開始LRU緩存淘汰
            
        
blockcache讀緩存空間的分區分級  
保護各個區安全、相互不受影響
    single區  
        默認大小爲blockcache_size*25% 
        當某個列簇下的storeFile文件中的某些block塊進行被第一次讀取則該塊中的cell會被加載到blockcache的此single區中  
        此緩存區域中的數據參與LRU緩存淘汰機制
    multi區 
        默認大小爲blockcache_size*50% 
        當數據近期被屢次讀取則會被加載到multi區中 
        此緩存區域中的數據參與LRU緩存淘汰機制
    在整個blockcache空間佔到85%時,對single、multi採起LRU機制
    in-memory區 
        默認大小爲blockcache_size*25% 
        當某個列簇下的 IN_MEMORY => 'true',則該列簇下的數據會持久加載到blockcache的in-memory區 中,而且不會參與LRU緩存淘汰 
        能夠將一些重要的或讀取頻率很是高的列簇標記爲true 
        in-memory區等級最高
        不能夠隨便將某些列簇此屬性標記爲true,不然會影響到 meta元數據表的讀寫效率

compaction機制

當flush到store下的storefile文件過多太小將影響到hbase後續的讀效率
    hbase後啓動compaction合併機制,最終將每一個store下的全部的storeFile文件合併爲一個大的單一的storeFile文件 
        
    compaction機制 分割兩個合併過程
        minor compaction --小合併  
            系統後臺會有一個專用的線程監控每一個store下的storeFile文件的數量
            當數量超過3個時會進行小合併 
            小合併只是一個歸類合併無用掃描讀取文件內的內容也沒有進行排序操做 
            該過程較快而且不會消耗集羣資源 
        major compaction --大合併 
            全部的region每隔3.5天~10.5天之間會進行一次大合併 
            大合併過程當中會加載讀取一個store下全部的storefile文件並進行如下操做
                會依據cell中的rowkey值的字典順序進行排序 
                會對打上’刪除‘標籤的cell或者過時的cell進行完全的刪除  
                    執行的刪除cell的操做並無將cell當即從storeFile文件中刪除
                    只是打上一個’刪除‘標籤,在大合併期間cell纔會被完全的刪除
                    
            大合併過程會消耗大量的hbase集羣資源(IO,cpu,內存 )  
            大合併能夠看作是以短時間的集羣資源消耗換取之後長期的讀效率的提高 

    compaction機制相關的屬性配置 
    
        大合併 
            <name>hbase.hregion.majorcompaction</name>  
            <value>604800000</value>
                region進行大合併的間隔時間爲7天  
                
            <name>hbase.hregion.majorcompaction.jitter</name>
            <value>0.50</value>                    
                默認值爲0.5,是一個浮動值  
                最終同一個regionserver節點上region的大合併間隔時間爲 
                    7*(1-0.5)天~ 7*(1+0.5)天 
                    3.5天~10.5天  
                    
            <name>hbase.hstore.compactionThreshold</name>
            <value>3</value>

hbase 表的管理命令

hbase的一些表管理的hbase shell命令  

flush操做     
  hbase> flush 'TABLENAME'  將某張表下全部的region中的memstore中的數據flush成storeFile文件
  hbase> flush 'REGIONNAME'  將某個region中的memstore中的數據flush成storeFile文件
  hbase> flush 'ENCODED_REGIONNAME'  將某個region中的memstore中的數據flush成storeFile文件

compaction操做 
    compact  小合併 
    storefile個數>3時自動合併  
    
    major_compact        大合併        
            Examples:
            Compact all regions in a table:
            hbase> major_compact 't1'
            hbase> major_compact 'ns1:t1'
            Compact an entire region:
            hbase> major_compact 'r1'
            Compact a single column family within a region:
            hbase> major_compact 'r1', 'c1'
            Compact a single column family within a table:
            hbase> major_compact 't1', 'c1'  
        
split操做

Examples:

split 'tableName'
split 'namespace:tableName'
split 'regionName' # format: 'tableName,startKey,id'
split 'tableName', 'splitKey'
split 'regionName', 'splitKey' 

> split "sqoop"  
    當一個表的region下的store下的storeFile文件大小小於一個block_size(64kb)時將不能被split分割 
    
其餘操做

> move 'ENCODED_REGIONNAME'  
> move 'ENCODED_REGIONNAME', 'SERVER_NAME'        
    將一個region移動到其餘的regionserver節點上 
        
    
> balancer  查看當前hbase集羣的 負載均衡策略是否開啓,true表示開啓 
> balance_switch   false   關閉負載均衡 


> close_region 'REGIONNAME'
> close_region 'REGIONNAME', 'SERVER_NAME'
> close_region 'ENCODED_REGIONNAME'
> close_region 'ENCODED_REGIONNAME', 'SERVER_NAME'        
    
                                
……

什麼狀況下須要進行region的手動管理操做

更換regionserver節點服務器時  
    先對此臺節點上的全部的region進行flush,再使用move將region移動到其餘regionserver節點上 
針對寫入及讀取比較頻繁的業務場景  
    寫入數據過程當中可能會發生大合併及split機制,可能會影響到hbase集羣的穩定性 
        region的split過程會消耗集羣資源而且對應的region還會短暫的offline下線
        大合併過程短期內會消耗大量的集羣資源  
    如何解決
        須要將被動的大合併及split機制關閉
        改爲定時的用戶訪問底峯時段進行  
        
    如何關閉大合併及split的自動(被動)機制           
        大合併 
            <name>hbase.hregion.majorcompaction</name> =》0  
        split 
             <name>hbase.regionserver.region.split.policy</name> =》DisabledRegionSplitPolicy  
             <name>hbase.hregion.max.filesize</name> =>1000G 
             
    若是人爲控制在訪問底峯時段定時進行大合併及split  
        將hbase shell命令轉化linux shell命令  
        再將linux shell命令  定義到一個shell腳本中 
        在使用crontab 定時執行shell腳本  
        
        
    $ echo " hbase shell 命令  " | bin/hbase shell -n     
    $ echo " create 't15' ,'info'  "  |  bin/hbase shell -n
#!/bin/sh
# HBASE_HOME 
HBASE_HOME=/opt/cdh-5.14.2/hbase-1.2.0-cdh5.14.2 
/bin/echo " hbase shell 命令 "     |  ${HBASE_HOME}/bin/hbase shell -n

HBase調優

hbase場景的調優思路

【針對客戶端的查詢】

主要是體如今hbase java API中

1)批量寫和讀

table.put(Put)
table.put(List<Put>) --- 批量的寫入 

table.get(Get) 
table.get(List<Get>)  --- 批量的讀數據

2)多線程多併發讀寫

3)客戶端手動緩存查詢結果

scan.setCacheBlocks(true); -- 能夠將掃描讀到的結果數據緩存到blockcache中

4)關閉table釋放資源

table.close()

【針對服務端hbase集羣資源及表的設計】

1)合理設置預分區及Rowkey設計

根據實際的需求場景對錶的預分區與rowkey的設計綜合考慮  
    建議regiond的數量=regionserver節點數量*2
rowkey的長度小於16字節  
列簇名及列名都儘量短小

2)控制自動splitmajorcompact改成手動的訪問底峯時段進行

針對寫入同時查詢比較頻繁的在線業務場景

3)合理設置列簇的最大支持版本數和存活期

在知足業務需求的前提下儘量設置少的版本數及短的存活期

4)合理設置BlockCache緩存策略(setCaching)

能夠將一些重要的或讀取頻率很是高用戶表的某些列簇的in-memory屬性值標記爲true

5)設置RegionServer處理客戶端IO請求的線程數

<name>hbase.regionserver.handler.count</name>
    <value>30</value>
30=> 100左右

6)合理配置BlockCache和memstore的能夠佔用的regionserver-jvm-heap空間的閾值

針對寫數據爲主的業務場景  
        將一個regionserver節點上全部的memstore可佔用的regionserver-jvm-heap空間的最大值由 40% =》60% 
        將一個regionserver節點上的blockcache可佔用的regionserver-jvm-heap空間的最大值由 40% =》20%
    針對讀數據爲主的業務場景 
        將一個regionserver節點上全部的memstore可佔用的regionserver-jvm-heap空間的最大值由 40% =》20% 
        將一個regionserver節點上的blockcache可佔用的regionserver-jvm-heap空間的最大值由 40% =》60%

7)WAL預寫日誌機制設置

能夠將數據寫入到Hlog的機制關閉  
適合寫入的數據量較多而且數據運行丟失的業務場景 ( 用戶行爲日誌數據 )

8)合理使用Compression壓縮

合理使用壓縮
    節省hdfs的存儲空間
    節省網絡和磁盤io

bhase shell =》表屬性 { COMPRESSION => 'SNAPPY' }
相關文章
相關標籤/搜索