《HBase 不睡覺》第一章 - 初始 HBase
CAP 全稱 是Consistency Availability and Partition tolerance:
- Consistency (一致性):資料一致更新,所有資料變動都是同步的;
- Availability (可用性):良好的響應效能;
- Partition tolerance (分割槽容錯性):可靠性。
任何分散式系統只可同時滿足二點,沒法三者兼顧。架構師不要將精力浪費在如何設計能滿足三者的完美分散式系統,而是應該進行取捨。

2、NoSQL
很多人以 為 NoSQL 是非 SQL 的意思,其實它是 Not Only SQL 的縮寫,意思是不只是 SQL。與關係型資料庫正好相反,非關係型資料庫 NoSQL 對事務性的要求並不嚴格,甚至可以說是相當馬虎。
有些資料庫是保證最終一致性,資訊不會立即同步,而是經過了一段時間才達到一致性。比如你發了一篇文章,你的一部分朋友立馬看到了這篇文章,另一部分朋友卻要等到 5 分鐘之後才能刷出這篇文章。
雖然有延時,但是對於一個娛樂性質的 Web 2.0 網站又有誰會在乎這幾分鐘的延時呢?如果你用傳統關係型資料庫,網站可能早就宕掉了。
有些資料庫可以在部分機器宕機的情況下依然可以正常執行,其實原理就是把同一份資料複製成了好幾份放到了好幾個地方,正應了那句老話:不要把雞蛋同時放在一個籃子裡。

3、列式儲存與行式儲存
列式儲存(Column-based)是相對於傳統關係型資料庫的行式儲存(Row-based)來說的,簡單來說兩者的區別就是如何組織表。
將表放入儲存系統中有兩種方法,而我們絕大部分是採用行儲存的。行儲存法是將各行放入連續的物理位置,這很像傳統的記錄和檔案系統。列儲存法是將資料按照列儲存到資料庫中,與行儲存類似,下圖是兩種儲存方法的圖形化解釋。

應用行式儲存的資料庫系統稱為行式資料庫,同理應用列式儲存的資料庫系統稱為列式資料庫。

列式儲存的主要優點之一就是可以大幅降低系統的 I/O,尤其是在海量資料查詢時,通過下面這張圖,相信我們能夠徹底明白這一點。

二、什麼時候使用 HBase?
HBase 的儲存是基於 Hadoop 的,Hadoop 實現了一個分散式檔案系統(HDFS)。HDFS 有高容錯性的特點,被設計用來部署在低廉的硬體上,而且它提供高吞吐量以訪問應用程式的資料,適合那些有著超大資料集的應用程式。 基於 Hadoop 意味著 HBase 與生俱來的超強的擴充套件性和吞吐量 。
HBase 採用的是 Key/Value 的儲存方式,這意味著,即使隨著資料量增大,也幾乎不會導致查詢的效能下降。
HBase 又是一個列式資料庫,當你的表字段很多的時候,你甚至可以把其中幾個欄位放在叢集的一部分機器上,而另外幾個欄位放到另外一部分機器上,充分分散了負載壓力。
然而,如此複雜的儲存結構和分散式的儲存方式帶來的代價就是:哪怕只是儲存少量資料,它也不會很快。所以我常常跟人說: HBase 並不快,只是當資料量很大的時候它慢的不明顯 。
不適合使用 HBase 的場景:
- 主要需求是資料分析,比如做報表。
- 單表資料量不超過千萬。
適合使用 HBase 的場景:
- 單表資料量超千萬,而且併發還挺高。
- 資料分析需求較弱,或者 不需要那麼靈活或者實時 。
三、HBase 部署架構
1、部署架構
HBase 有兩種伺服器:Master 伺服器和 RegionServer 伺服器,一般一個 HBase 叢集有一個 Master 伺服器和多個 RegionServer 伺服器。
Master 伺服器負責維護表結構資訊,實際的資料都儲存在 RegionServer 伺服器上,RegionServer 是直接負責儲存資料的伺服器,RegionServer 儲存的表資料直接儲存在 Hadoop 的 HDFS 上。
HBase 有一點很特殊:客戶端獲取資料由客戶端直連 RegionServer 的,所以當 Master 掛掉之後你依然可以查詢資料,只是喪失了表管理相關的能力。
RegionServer 非常依賴 ZooKeeper 服務,可以說沒有 ZooKeeper 就沒有 HBase。ZooKeeper 管理了 HBase 所有 RegionServer 的資訊,包括具體的資料段存放在哪個 RegionServer 上。客戶端每次與 HBase 連線,其實都是先與 ZooKeeper 通訊,查詢出哪個 RegionServer 需要連線,然後再連線 RegionServer。

2、Region
Region 就是一段資料的集合,HBase 中的表一般擁有一個到多個 Region,Region 有以下特性:
- Region 不能跨伺服器,一個 RegionServer 上有一個或者多個 Region;
- 資料量小的時候,一個 Region 足以儲存所有資料;但是,當資料量大的時候,HBase 會拆分 Region;
- 當 HBase 在進行負載均衡的時候,也有可能會從一臺 RegionServer 上把 Region 移動到另一臺 RegionServer 上;
- Region 是基於 HDFS 的,它的所有資料存取操作都是呼叫了 HDFS 的客戶端介面來實現的。
3、RegionServer
RegionServer 就是存放 Region 的容器,直觀上說就是伺服器上的一個服務。一般來說,一個伺服器只會安裝一個 RegionServer 服務。當客戶端從 ZooKeeper 獲取 RegionServer 的地址後,它會直接從 RegionServer 獲取資料。
4、Master
HBase 中 Master 的角色不像領導,更像是打雜的。客戶端從 ZooKeeper 獲取了 RegionServer 的地址後,會直接從 RegionServer 獲取資料。其實 不光是獲取資料,包括插入、刪除等所有的資料操作 都是直接操作 RegionServer,而不需要經過 Master。
Master 只負責各種 協調工作 ,比如建表、刪表、移動 Region、合併等操作。它們的共性就是 需要跨 RegionServer ,這些操作由哪個 RegionServer 來執行都不合適,所以 HBase 就將這些操作放到了Master上了。
這種結構的好處是大大降低了叢集對 Master 的依賴,而 Master 節點一般只有一個到兩個,一旦宕機,如果叢集對 Master 的依賴度很大,那麼就會產生單點故障問題。在 HBase 中,即使 Master 宕機了,叢集依然可以正常地執行,依然可以儲存和刪除資料。
四、HBase 儲存架構
1、儲存架構
最基本的儲存單位是列(column),一個列或者多個列形成一行(row)。傳統資料庫是嚴格的行列對齊,比如這行有三個列 a、b、c,下一行肯定也有三個列 a、b、c。而在 HBase 中,這一行有三個列 a、b、c,下一個行也許是有 4 個列 a、e、f、g。
在 HBase 中,行跟行的列可以完全不一樣,這個行的資料跟另外一個行的資料也可以儲存在不同的機器上,甚至同一行內的列也可以儲存在完全不同的機器上!每個行(row)都擁有唯一的 行鍵 (row key)來標定這個行的唯一性。每個列都有多個版本,多個版本的值儲存在單元格(cell)中,若干個列又可以被歸類為一個 列族 。

2、行鍵(rowkey)
rowkey 是由使用者指定的一串不重複的字串,rowkey 會直接決定這個 row 的儲存位置的。HBase 中無法根據某個 column 來排序,系統永遠是根據 rowkey 來排序的(根據字典排序),rowkey 就是決定 row 儲存順序的唯一憑證。
如果插入 HBase 的時候,不小心用了之前已經存在的 rowkey,這會把之前存在的那個 row 更新掉。之前已經存在的值會被放到這個單元格的歷史記錄裡面, 並不會丟掉 ,只是你需要帶上版本引數才可以找到這個值。一個列上可以儲存多個版本的單元格(cell),單元格就是資料儲存的最小單元。
3、列族(column family)
若干列可以組成列族(column family),建表的時候有幾個列族是一開始就定好的。表的很多屬性,比如過期時間、資料塊快取以及是否壓縮等都是定義在列族上,而不是定義在表上或者列上。
同一個表裡的不同列族可以有完全不同的屬性配置,但是同一個列族內的所有列都會有相同的屬性,因為他們都在一個列族裡面,而屬性都是定義在列族上的。一個沒有列族的表是沒有意義的,因為列必須依賴列族而存在。
列名稱的規範是 列族:列名 ,比如 brother:age、brother:name。列族存在的意義是:HBase 會把相同列族的列儘量放在同一臺機器上,如果想讓某幾個列被放到一起,你就給他們定義相同的列族。
一個表要設定多少個列族比較合適?官方的建議是: 越少越好 (一般來說一個就夠用了),因為 HBase 並不希望大家指定太多的列族。列族太多會極大程度地降低資料庫效能;此外,列族定得太多,容易出 BUG。
4、單元格(cell)
一個列上可以儲存多個版本的值,多個版本的值被儲存在多個單元格里面,多個版本之間用版本號(Version)來區分,唯一確定一條結果的表示式應該是: 行鍵:列族:列:版本號(rowkey:column family:column:version)
。不過,版本號是可以省略的,如果你不寫版本號,HBase 預設返回最後一個版本的資料。

一個 Region 就是多個行(Row)的集合,在 Region 中行的排序按照行鍵(rowkey)字典排序。