一、進行遷移的原因
由於業務的發展,使用mysql進行建立索引進行搜索已經造成數據流的瓶頸卡在了數據庫io,例如每次dump全表的時候,會造成壓力過大,造成耗時很長,並且當前的數據量基本上已經達到了億級別的數據量,如果希望mysql能更好的提供服務,下一步必須考慮分庫分表才可以;基於這種情況下,考慮使用hbase用來進行數據的存儲,因為hbase所能承受的數據量遠大於mysql,並且對列的擴展也很方便
二、關系型數據庫與Nosql的一些區別
(1)存儲方式的區別
在類似mysql,sqlserver,oracle等關系型數據庫,數據的存儲是按照行進行存儲的,如下圖所示:

但是在hbase里面,所有的數據是基於列進行存儲的,如下所示:

其中hbase的邏輯模型如下所示:

其中:com.cnn.ww對應的是rowkey,相當於mysql的主鍵的概念
contents,anchor:這兩個對應的是列族的概念,在物理的存儲上,同一個列族的數據存儲在相同文件
cnnsi.com,mylook.ca:對應的是列族下面的列,在hbase中列是可以動態增加的
對應的方格數據表示的是單元數據,即對應rowkey,cf:column下面的具體的值
其中tn:表示的是時間戳,單元數據的不同版本
其中有一張存儲結構如下:

(2)CRUD一些區別
CRUD是數據庫的最基本也是最常用的操作,在hbase里面也有對應的命令,例如建表語句對於mysql的在此不詳述,對於hbase shell的如下所示
create ‘table’,‘columnfamily’
即可以創建一個名為table,列族為columnfamily的表,其他的一些blocksize,version數據為默認
讀取數據的時候,在hbase語句如:get ‘table’,'row',‘cf:column’即可得到對應的數據
更新數據的時候,在hbase中沒有對應更新的概念,只是會有一個新的版本,從時間戳上可以體現出來,所用的語句為
put ‘table’,‘row’,‘cf:name’,‘value’
即可將value的值賦給對應cf列族,name的列
刪除數據的區別,在mysql中刪除數據只能是直接刪除一行,或者將某一列置為空,在hbase里面可以直接刪除某一列
(3)索引的區別
在mysql中可以建立索引,或者過濾查詢,但是在hbase中,只支持按照rowkey進行查詢速率最快
(4)從mysql到nosql的發展的思考
關系型數據庫的歷史已經很久,但是當數據量膨脹之后,例如對於mysql數據庫,當數據量為上億或者更多的時候,如果按照索引進行查詢,可能效果 也不是特別的明顯,最后只能按照主鍵進行查詢,或者逐漸發展為分庫分表的模式,但是分庫分表又給運維以及使用帶來了很大的麻煩;於是這個時候,nosql數據庫主鍵發展,nosql簡稱not only sql,是在數據量暴增的當前逐漸發展壯大起來,以nosql里面的hbase作為例子,支持TB以及PB的數據,並且列的擴展特別的靈活
(5)hbase為什么可以存儲海量的數據呢
其實hbase可以看做是mysql分庫分表后的結果,只是不同的是mysql分庫分表后支持索引等,但是對於hbase僅僅支持rowkey作為主鍵索引,從書中可以知道,hbase的數據是按照列進行存儲的,並且當數據過大的時候,會按照行進行分裂,如下如所示:

把不同的region放到了不同的機器,並且最后還有master進行管理,即相當於對行列進行了一個划分,從而存儲大量的數據
三、數據遷移遇到的一些問題
(1)聯合索引的問題
在mysql中會有一些聯合索引的情況,例如存在一個商品與分類對應關系的表,需要得到某一個商品的所有分類,也希望可以得到某一個分類的所有商品,在mysql中直接按照聯合索引可以達到要求,但是在hbase的時候只能按照rowkey查詢如何辦呢
經過閱讀相關的數據得到有如下兩種的解決辦法
1、構建寬表
在hbase中,允許行跟行之間的列是不同的,只要有共同的列族即可,那么對於上述的情況,可以構建一個按照分類為rowkey的寬表,如下所示
分類id,作為rowkey
product_id,作為列名字
value存儲為是否刪除

上述即可rowkey為分類id,可以直接從row得到所有的product_id,然后自己過濾是否刪除
2、構建高表
什么是構建高表呢,也就是說不需要那么多的列,只是存儲多行,因為在hbase里面是按照字典順序排序的,因此可以進行如下的設計
分類id_商品id,作為rowkey

只要scan以1開頭的行,就可以得到所有的數據
上述兩種辦法從本質上來說,都是構建了一個二級索引來存儲數據
【github開源地址:
https://github.com/molong1208,歡迎關注,指點交流】