《HBase 不睡覺》第二章 - 讓 HBase 跑起來
(1)切換到root使用者,然後建立hadoop使用者。
# useradd hadoop # passwd hadoop 複製程式碼
(2)新增 hadoop 到sudoers 列表。
# chmod u+w /etc/sudoers # vi u+w /etc/sudoers -- 新增下面的程式碼 -- hadoop ALL=NOPASSWD:ALL 複製程式碼
2、Hadoop 環境變數設定
切換到 hadoop 使用者,並編輯 ~/.bashrc
檔案,新增以下環境變數:
export HADOOP_HOME=/usr/local/hadoop export HADOOP_PREFIX=$HADOOP_HOME export HADOOP_MAPRED_HOME=$HADOOP_HOME expOrt HADOOP_COMMON_HOME=$HADOOP_HOME export HADOOP_HDES_HOME=$HADOOP_HOME eXpOrt YARN_HOME=$HADOOP_HOME export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin export HADOOP_INSTALL=$HADOOP_HOME 複製程式碼
有的教程提到配置 HADOOP_HOME
,而官方教程說是配置 HADOOP_PREFIX
,那麼究竟 Hadoop 是用哪個環境變數來標定 Hadoop 的程式資料夾位置?實際上,早期 Hadoop 主要用 HADOOP_HOME
來標定程式資料夾位置,後來改成了 HADOOP_PREFIX
,所以為了相容性,乾脆都設定上,並且保持一樣的值吧。
3、配置hadoop-env.sh
編輯 hadoop 的 $HADOOP_PREFIX/etc/hadoop/hadoop-env.sh
檔案,在檔案開頭新增以下變數:
export HADOOP_NAMENODE_OPTS="-Xms1024m -Xmx1024m -XX:+UseParallelGC" export HADOOP_DATANODE_OPTS="-Xms1024m-Xmx1024m" export HADOOP_LOG_DIR=/data/1ogs/hadoop 複製程式碼
- JVM 執行的記憶體如果不設定佔用大小的話,要麼不夠,要麼就把機器的記憶體都佔滿了。只要用到 JVM 的地方都加入記憶體引數,至少記憶體多少自己心裡有數,讓情況可控。
- 日誌檔案路徑如果不設定的話,多半後期會遇到放日誌的分割槽滿了,各種奇怪故障層出不窮。
4、把 hbase 新增到 supergroup 組
由於在偽分散式和完全分散式的情況下 HBase 會直接在 HDFS 的根目錄下建立 /hbase
資料夾,在根目錄下要建立資料夾需要超級使用者組許可權。超級使用者組許可權由 hdfs-site.xml
中的 dfs.permissions.supergroup
來定義,如果你不設定這個引數,預設的超級使用者組組名是 supergroup。假定大家都沒有設定 dfs.permissions.supergroup
屬性,現在需要把 hbase 新增到 Linux 的 supergroup 組去。CentOS 系統可執行下面的語句:
# groupadd supergroup # groupmems -g supergroup -a hbase 複製程式碼
5、特別注意
HBase 自帶了一個 ZooKeeper,而且會預設啟動自己的 ZooKeeper,如果 HBase 用的是自己的 ZooKeeper,那你在 jps 中看到的 ZooKeeper 名字是 HQuorumPeer。如果你使用的是外部的 ZooKeeper 叢集,那麼它的名字叫 QuorumPeer 或者 QuorumPeerMain。
是否開啟自帶的 ZooKeeper 由 conf/hbase-env.sh
中定義的 HBASE_MANAGES_ZK
變數定義。這個變數預設為 true,如果不想使用自帶的 ZK 你可以將值改為 false。
# Tell HBase whether it should manage it's own instance of Zookeeper or not. export HBASE_MANAGES_ZK=false 複製程式碼
6、HBase 讀取到 HDFS 的配置有三種方式
- 把
HADOOP_CONF_DIR
新增到HBASE_CLASSPATH
中(推薦); - 把 HDFS 的配置檔案複製一份到 HBase 的 conf 資料夾下,或者直接建一個
hdfs-site.xml
的軟連結到hbase/conf
下; - 把 HDFS 的幾個配置項直接寫到 hbase-site.xml 檔案裡面去。
二、HBase 的基本架構
- HBase 中有一個 Master 用來管理元資料,它就像 Hadoop 中的 namenode;
- RegionServer 是用來儲存資料的,相當於 Hadoop 中的 datanode;
- ZooKeeper 負責維護 HBase 的所有節點,如果 ZooKeeper 宕掉了,你一個節點都連不上;
- 生產環境下的完全部署模式是基於 HDFS 的,使用 HDFS 來儲存資料,但是在單機模式下 HBase 可以直接使用普通檔案系統來儲存資料;
- 在使用中就算把 Master 關掉了,依舊可以從 HBase 中讀取資料和寫入資料,只是不能建表或者修改表。這是因為客戶端讀取資料的時候只是跟 ZooKeeper 和 RegionServer 互動,所以,ZooKeeper 甚至比 Master 還重要。

三、啟用資料塊編碼
1、資料塊編碼
資料塊編碼主要是 針對 Key/Value 中的 Key 進行編碼,減少 Key 儲存所佔用的空間 ,因為很多 Key 的字首都是重複的。
假設有這樣一個表,它的行鍵(Rowkey)、列族(Column Family)、列(Column)的定義規則是:行鍵以 myrow 字首打頭,後面跟上數字來組成行鍵,比如 myrow001、myrow002、myrow003 等,擁有一個列族叫 mycf,mycf 列族中有 5 個列,分別名叫 col1、col2、col3、col4、col5,它們的儲存結構如下所示。

可以看到這麼多行的 Key 其實有很大一部分的字元是重複的,如果我們只儲存遞進值,就可以避免儲存重複的字首,這就是字首編碼(Prefix)。
2、字首編碼(Prefix)
如果使用字首編碼作為資料塊編碼方式,那麼它只會儲存第一個 Key 的完整字串,後面的 key 只儲存跟第一個 key 的 差異字元 ,重新編碼過的資料如下所示。

可以看到 Key 的儲存空間極大地縮小了,編碼後的 Key 總儲存空間只用了 37 個字元,而未編碼前是 180 個字元,空間佔用減少了 79%。
3、差異編碼(Diff)
差異編碼(Diff)比字首編碼更進一步,差異編碼甚至把以下欄位也一起進行了差異化的編碼。
- 鍵長度(KeyLen);
- 值長度(ValueLen);
- 時間戳(Timestamp),也即是Version;
- 型別(Type),也即是鍵型別。
採用了差異編碼後的 KeyValue 結構為:
- 1 byte:標誌位;
- 1-5 bytes:Key 長度(KeyLen);
- 1-5 bytes:Value 長度(ValLen);
- 1-5 bytes:字首長度(Prefix Len);
- ... bytes:剩餘的部分;
- ... bytes:真正的 Key 或者只是有差異的 key 字尾部分;
- 1-8 bytes:時間戳(timestamp)或者時間戳的差異部分;
- 1 byte:Key 型別(type);
- ... bytes:值(value)。
字首長度(Prefix Len)欄位表示當前的 Key 跟與之相比的 Key 的相同字首的長度。

標誌位(Flag)
它是一個二進位制數。比如,5=11,7=111。它的作用就是記錄當前這個 KeyValue 跟上一個 KeyValue 之間有哪幾個欄位有差異,以下是產生標誌位的部分規則:
- 如果當前 KeyValue 中的 KeyLen(Key的長度)跟上一個 KeyValue相等,則標誌碼為 1。
- 如果當前 KeyValue 中的 ValLen(Value長度)跟上一個 ValLen 相等,則標誌碼為10。
- 如果當前 KeyValue 中的 Type 跟上一個 Type 相等,則標誌碼為100。
只需要把 flag 跟標誌碼做一個與(&)計算就可以快速地知道這個欄位跟上一個欄位的差異在哪裡,即 相同的位置標記為 1 。
這樣編碼幾乎是最大程度地對資料進行了編碼壓縮,但是這個編碼方式 預設是不啟用的 。為什麼?因為 太慢了 ,每條資料都要這樣計算一下,獲取資料的速度很慢。除非你要追求極致的壓縮比,但是不考慮讀取效能的時候可以使用它,比如你想要把這部分資料當作歸檔資料的時候,可以考慮使用差異編碼。
4、快速差異編碼(Fast Diff)
快速差異編碼(Fast Diff)借鑑了 Diff 編碼的思路,也考慮到了差異編碼速度慢的致命缺陷。快速差異編碼的 KeyValue 結構跟差異編碼一模一樣,只有 Flag 的儲存規則不一樣,並且優化了 Timestamp 的計算。Fast Diff 的實現比 Diff 更快,也是比較推薦的演算法。
如果你想用差異演算法來壓縮你的資料,那麼最好用快速差異編碼,不過這個“快速”只是相對本來的差異演算法而言的,由於還是有很多計算過程存在,所以 快速差異演算法的速度依然屬於比較慢的 。
5、字首樹編碼(Prefix Tree)
字首樹編碼(Prefix Tree)是字首演算法的變體,它是 0.96 版本之後才加入的特性。字首樹編碼最大的作用就是提高了隨機讀的能力,但是其複雜的演算法相對地降低了寫入的速度,消耗了更多的 CPU 資源,使用時需要在資源的消耗和隨機讀的效能之間進行取捨。
綜上, 字首編碼與快速差異編碼 (Kylin 預設使用該方式)應該算是比較常用的兩種資料塊編碼方式了。
四、啟用壓縮器
1、壓縮器
壓縮器的作用是可以把 HBase 的資料按壓縮的格式儲存,這樣可以更節省磁碟空間。當然這完全是可選的,不過推薦大家還是安裝 Snappy 壓縮器,這是 HBase 官方目前排名比較高的壓縮器。
可以通過修改列族描述啟用壓縮器:
hbase> alter 'mytable',{NAME =>'mycf',COMPRESSION=>'snappy'} 複製程式碼
2、共享 Hadoop 內建的壓縮器
由於 Hadoop 的共享庫(shared Library)擁有很多資源,包括壓縮器,所以可以直接將它們用在 HBase中。可以通過以下命令檢查 Hadoop 目前有用的壓縮器:
$ hbase --config $HBASE_HOME/conf org.apache.hadoop.util.NativeLibraryChecker 複製程式碼
如果遇到下面的報錯資訊,則表示 NativeLibraryChecker 無法讀取到 Hadoop 的 native 庫。
util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable Native library checking: hadoop: false zlib: false snappy: false 1z4: false bzip2: false 複製程式碼
常規的解決方法是在 hbase-env.sh
加入下面的語句:
export HBASE_LIBRARY_PATH=Hadoop的Native包所在路徑 複製程式碼
3、Snappy 壓縮器
Snappy 是 Google 開發的壓縮器,有以下特點:
- 快速:壓縮速度達到 250MB/s;
- 穩定:已經用於 Google 多個產品長達數年;
- 健壯:Snappy 的解壓器可以保證在資料被損壞的時候也不會太糟;
- 免費開源。
安裝完成後,需要在 hbase-env.sh
加入下面的語句:
export HBASE_LIBRARY_PATH=編碼器so檔案所在路徑:$HBASE_LIBRARY_PATH 複製程式碼
4、GZ 壓縮器
一般情況下如果不是對速度要求很低的歸檔檔案,一般不建議使用GZ壓縮器,GZ 壓縮器的特點:
- GZ 壓縮器擁有最高的壓縮比;
- 速度較慢,佔用較多CPU;
- 安裝簡單。
Java 已經自帶了一個 GZ 壓縮器,所以 GZ 壓縮器雖然不是效能最好的,但是卻是最容易使用的,你什麼都不需要設定,只需要直接修改列族的 COMPRESSION 屬性為 GZ 即可。
alter test1',{NAME=>'mycf',COMPRESSION=>'GZ'} 複製程式碼
5、LZO 壓縮器
在 Snappy 推出之前,LZO 是 HBase 官方推薦的壓縮演算法。主要原因是 GZ 壓縮的速度太慢了,而 LZO 正好就是專注於速度,所以相比起來使用 LZO 會比 GZ 更好,不過自從 Snappy 出了之後,LZO 就沒有什麼優勢了。
6、LZ4 壓縮器
LZ4 的特點:
- 擁有低丟失率;
- 速度很快,可以達到400M/s每核。
LZ4 比 Snappy 更快,LZ4 壓縮器已經整合在libhadoop.so 中,所以只需要讓 HBase 載入Hadoop 自帶的原生庫即可。
五、總結
使用資料塊編碼還是壓縮器取決於你儲存的資料中是限定符佔的空間較大還是值佔的空間較大。
- 如果是限定符佔的空間較大,建議使用資料塊編碼。
- 如果是值佔的空間較大,建議使用編碼器。
最開始學習 HBase 的時候,大多都是直接使用 Java API 去進行表操作,很少去關注 HBase 安裝相關的內容;通過上述的介紹,至少資料塊編碼和壓縮器在以後建表時候還是可以考慮的,官方推薦的 Snappy 壓縮器以及字首編碼都是即簡單又有效的調優方法。
Any Code,Code Any!
掃碼關注『AnyCode』,程式設計路上,一起前行。
