2. HBase安裝
HBase = Hadoop database
1. Zookeeper正常部署
首先保證Zookeeper集羣的正常部署,並啓動之:
[atguigu@hadoop102 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop103 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop104 zookeeper-3.4.10]$ bin/zkServer.sh start
2 Hadoop正常部署
Hadoop集羣的正常部署並啓動:
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh
[atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
3. HBase的解壓
解壓HBase到指定目錄:
[atguigu@hadoop102 software]$ tar -zxvf hbase-1.3.1-bin.tar.gz -C /opt/module
4. HBase的配置文件
修改HBase對應的配置文件。
- hbase-env.sh修改內容:
export JAVA_HOME=/opt/module/jdk1.8.0_144
export HBASE_MANAGES_ZK=false # 不用HBase自帶的zk關聯機制
- hbase-site.xml修改內容:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop102:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 0.98後的新變動,之前版本沒有.port,默認端口爲60000 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/module/zookeeper-3.4.10/zkData</value>
</property>
</configuration>
- 修改regionservers跟HDFS中slaves類似:
hadoop102
hadoop103
hadoop104
- 軟連接hadoop配置文件到hbase:
[atguigu@hadoop102 module]$ ln -s /opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml
/opt/module/hbase/conf/core-site.xml
[atguigu@hadoop102 module]$ ln -s /opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
/opt/module/hbase/conf/hdfs-site.xml
5. HBase遠程發送到其他集羣
[atguigu@hadoop102 module]$ xsync hbase/
6 HBase服務的啓動
1.啓動方式1
[atguigu@hadoop102 hbase]$ bin/hbase-daemon.sh start master
[atguigu@hadoop102 hbase]$ bin/hbase-daemon.sh start regionserver
提示
:如果集羣之間的節點時間不同步,會導致regionserver無法啓動,拋出ClockOutOfSyncException異常。
修復提示:
a、同步時間服務
請參看幫助文檔:《Hadoop入門》
b、屬性:hbase.master.maxclockskew設置更大的值
<property>
<name>hbase.master.maxclockskew</name>
<value>180000</value>
<description>Time difference of regionserver from master</description>
</property>
2.啓動方式2推薦
[atguigu@hadoop102 hbase]$ bin/start-hbase.sh
對應的停止服務:
[atguigu@hadoop102 hbase]$ bin/stop-hbase.sh
7. 查看HBase頁面
啓動成功後,可以通過“host:port”的方式來訪問HBase管理頁面,例如:
http://hadoop102:16010
3. HBase Shell 操作
Shell基本操作 指南
命名 | 描述 | 語法 |
---|---|---|
help ‘命名名’ | 查看命令的使用描述 | help ‘命令名’ |
whoami | 我是誰 | whoami |
version | 返回hbase版本信息 | version |
status | 返回hbase集羣的狀態信息 | status |
table_help | 查看如何操作表 | table_help |
create | 創建表 | create ‘表名’, ‘列族名1’, ‘列族名2’, ‘列族名N’ |
alter | 修改列族 | 添加一個列族:alter ‘表名’, ‘列族名’ ;刪除列族:alter ‘表名’, {NAME=> ‘列族名’, METHOD=> ‘delete’} |
describe | 顯示錶相關的詳細信息 | describe ‘表名’ |
list | 列出hbase中存在的所有表 | list |
exists | 測試表是否存在 | exists ‘表名’ |
put | 添加或修改的表的值 | put ‘表名’, ‘行鍵’, ‘列族名’, ‘列值’ ; put ‘表名’, ‘行鍵’, ‘列族名:列名’, ‘列值’ |
scan | 通過對錶的掃描來獲取對用的值 | scan ‘表名’ ; 掃描某個列族: scan ‘表名’, {COLUMN=>‘列族名’} 掃描某個列族的某個列: scan ‘表名’, {COLUMN=>‘列族名:列名’} ; 查詢同一個列族的多個列: scan ‘表名’, {COLUMNS => [ ‘列族名1:列名1’, ‘列族名1:列名2’, …]} |
get | 獲取行或單元(cell)的值 | get ‘表名’, ‘行鍵’ get ‘表名’, ‘行鍵’, ‘列族名’ |
count | 統計表中行的數量 | count ‘表名’ |
incr | 增加指定錶行或列的值 | incr ‘表名’, ‘行鍵’, ‘列族:列名’, 步長值 |
get_counter | 獲取計數器 | get_counter ‘表名’, ‘行鍵’, ‘列族:列名’ |
delete | 刪除指定對象的值(可以爲表,行,列對應的值,另外也可以指定時間戳的值) | 刪除列族的某個列: delete ‘表名’, ‘行鍵’, ‘列族名:列名’ |
deleteall | 刪除指定行的所有元素值 | deleteall ‘表名’, ‘行鍵’ |
truncate | 重新創建指定表 | truncate ‘表名’ |
enable | 使表有效 | enable ‘表名’ |
is_enabled | 是否啓用 | is_enabled ‘表名’ |
disable | 使表無效 | disable ‘表名’ |
is_disabled | 是否無效 | is_disabled ‘表名’ |
drop | 刪除表 | drop的表必須是disable的 disable |
shutdown | 關閉hbase集羣(與exit不同) | |
tools | 列出hbase所支持的工具 | |
exit | 退出hbase shell |
基本操作
- 進入HBase客戶端命令行
[atguigu@hadoop102 hbase]$ bin/hbase shell
- 查看幫助命令
hbase(main):092:0> help 'delete'
Put a delete cell value at specified table/row/column and optionally
timestamp coordinates. Deletes must match the deleted cell's
coordinates exactly. When scanning, a delete cell suppresses older
versions. To delete a cell from 't1' at row 'r1' under column 'c1'
marked with the time 'ts1', do:
hbase> delete 'ns1:t1', 'r1', 'c1', ts1
hbase> delete 't1', 'r1', 'c1', ts1
hbase> delete 't1', 'r1', 'c1', ts1, {VISIBILITY=>'PRIVATE|SECRET'}
The same command can also be run on a table reference. Suppose you had a reference
t to table 't1', the corresponding command would be:
hbase> t.delete 'r1', 'c1', ts1
hbase> t.delete 'r1', 'c1', ts1, {VISIBILITY=>'PRIVATE|SECRET'}
hbase(main):093:0>
hbase(main):001:0> help
COMMAND GROUPS:
Group name: general
Commands: processlist, status, table_help, version, whoami
Group name: ddl 數據庫的增刪改查操作
Commands: alter, alter_async, alter_status, clone_table_schema, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, get_table, is_disabled, is_enabled, list, list_regions, locate_region, show_filters
Group name: namespace 類似與mysql中的database操作
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
.......
For more on the HBase Shell, see http://hbase.apache.org/book.html
- 查看當前數據庫中有哪些表
hbase(main):002:0> list
TABLE
sowhat
mygraph
user
表的操作
- 創建表
注意:創建表時只需要指定列族名稱,不需要指定列名。
# 語法
create '表名', {NAME => '列族名1'}, {NAME => '列族名2'}, {NAME => '列族名3'}
# 此種方式是上上面的簡寫方式,使用上面方式可以爲列族指定更多的屬性,如VERSIONS、TTL、BLOCKCACHE、CONFIGURATION等屬性
create '表名', '列族名1', '列族名2', '列族名3'
create '表名', {NAME => '列族名1', VERSIONS => 版本號, TTL => 過期時間, BLOCKCACHE => true}
# 示例
create 'tbl_user', 'info', 'detail'
create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}
create 'sowhat','info'
- 插入數據到表
put 表名,序列號key,列族:列名,字段值
hbase(main):003:0> put 'sowhat','1001','info:sex','male'
hbase(main):004:0> put 'sowhat','1001','info:age','18'
hbase(main):005:0> put 'sowhat','1002','info:name','Janna'
hbase(main):006:0> put 'sowhat','1002','info:sex','female'
hbase(main):007:0> put 'sowhat','1002','info:age','20'
- 掃描查看錶數據
hbase(main):008:0> scan 'sowhat'
hbase(main):012:0> scan 'sowhat'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
---
hbase(main):009:0> scan 'sowhat',{STARTROW => '1001', STOPROW => '1001'} 指定範圍 左閉右開[start,end)這樣的格式,必須大寫!
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
---
hbase(main):010:0> scan 'sowhat',{STARTROW => '1001'}
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592444447588, value=18
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
---
- 查看錶結構
hbase(main):011:0> describe 'sowhat' desc 'sowhat' 也可以
Table sowhat is ENABLED
sowhat
COLUMN FAMILIES DESCRIPTION
{NAME => 'info', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'fal
se', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_
MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
- 更新指定字段的數據
hbase(main):012:0> put 'sowhat','1001','info:name','Nick'
hbase(main):013:0> put 'sowhat','1001','info:age','100'
hbase(main):013:0> scan 'sowhat'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1592445694183, value=100
1001 column=info:name, timestamp=1592445681869, value=Nick
1001 column=info:sex, timestamp=1592444439067, value=male
1002 column=info:age, timestamp=1592444470614, value=20
1002 column=info:name, timestamp=1592444462987, value=Janna
1002 column=info:sex, timestamp=1592444466848, value=female
2 row(s)
- 查看“指定行”或“指定列族:列”的數據
hbase(main):025:0> get 'sowhat','1001'
COLUMN CELL
info:age timestamp=1592445694183, value=100
info:name timestamp=1592445681869, value=Nick
info:sex timestamp=1592444439067, value=male
1 row(s)
Took 0.0215 seconds
hbase(main):026:0> get 'sowhat','1001','info:name'
COLUMN CELL
info:name timestamp=1592445681869, value=Nick
1 row(s)
Took 0.0146 seconds
- 統計表數據行數
hbase(main):027:0> count 'sowhat'
2 row(s)
Took 0.0558 seconds
=> 2
- 刪除數據
刪除某rowkey的全部數據:
hbase(main):016:0> deleteall 'sowhat','1001'
刪除某rowkey的某一列數據:
hbase(main):017:0> delete 'sowhat','1002','info:sex'
- 清空表數據
hbase(main):032:0> truncate 'sowhat'
Truncating 'sowhat' table (it may take a while):
Disabling table...
Truncating table...
Took 2.0702 seconds
hbase(main):033:0> scan 'sowhat'
ROW COLUMN+CELL
0 row(s)
提示:清空表的操作順序爲先disable
,然後再truncate,在HBase 2.2版本上操作時候沒顯示必須disable。
10. 刪除表
首先需要先讓該表爲disable
狀態:
hbase(main):019:0> disable 'sowhat'
然後才能drop這個表:
hbase(main):020:0> drop 'sowhat'
提示:如果直接drop表,會報錯:ERROR: Table sowhat is enabled. Disable it first
.
11. 變更表信息
默認情況下,列族只存儲一個版本的數據
,如果需要存儲多個版本的數據,則需要修改列族的屬性。修改後可通過desc命令查看。
put 'sowhat','1001','info:name','Nick'
put 'sowhat','1001','info:name','Nick1'
put 'sowhat','1001','info:name','Nick2'
put 'sowhat','1001','info:name','Nick3'
put 'sowhat','1001','info:name','Nick4'
hbase(main):022:0> alter 'sowhat',{NAME=>'info',VERSIONS=>3}
hbase(main):022:0> get 'sowhat','1001',{COLUMN=>'info:name',VERSIONS=>3}
COLUMN CELL
info:name timestamp=1592446266614, value=Nick4
info:name timestamp=1592446264202, value=Nick3
info:name timestamp=1592446262438, value=Nick2
1 row(s)
put 'sowhat','1001','info:name', 'Nick0', 1592446266615 put數據的時候指定時間
- alter 增刪列族
# 語法
alter '表名', '列族名'
# 示例
alter 'tbl_user', 'address'
# 語法
alter '表名', {NAME=> '列族名', METHOD=> 'delete'}
# 示例
alter 'tbl_user', {NAME=> 'address', METHOD=> 'delete'}
# 修改f1列族的版本爲5
alter 't1', NAME => 'f1', VERSIONS => 5
# 修改多個列族,修改f2爲內存,版本號爲5
alter 't1', 'f1', {NAME => 'f2', IN_MEMORY => true}, {NAME => 'f3', VERSIONS => 5}
# 也可以修改table-scope屬性,例如MAX_FILESIZE, READONLY,MEMSTORE_FLUSHSIZE, DEFERRED_LOG_FLUSH等。
# 例如,修改region的最大大小爲128MB:
alter 't1', MAX_FILESIZE => '134217728'
- 查看所有數據類型
scan 'sowhat',{RAW=>TRUE,VERSIONS=>10}
4. HBase數據結構
1. RowKey
跟nosql數據庫一樣RowKey
就是用來檢索記錄的主鍵,訪問HBase 表中的行只有如下三種方式。
- 通過單個RowKey訪問
get 'sowhat','1001'
- 通過RowKey的range訪問
scan 'sowhat',{STARTROW => '1001', STOPROW => '1003'}
- 全表掃描
RowKey行鍵 (RowKey)可以是任意字符串(最大長度是64KB,實際應用中長度一般爲 10-100bytes),在HBASE內部,RowKey保存爲字節數組。存儲時,數據按照RowKey的字典序(byte order)排序存儲。設計RowKey時,要充分排序存儲這個特性,將經常一起讀取的行存儲放到一起。(位置相關性)
scan 'sowhat'
2. Column Family
列族:HBASE表中的每個列,都歸屬於某個列族
。列族是表的schema的一部分(而列不是),必須在使用表之前定義。列名都以列族作爲前綴。例如 courses:history
,courses:math
都屬於courses 這個列族。
3. Cell
由{rowkey, column Family:columu, version} 唯一確定的單元。cell中的數據是沒有類型
的,全部是字節碼
形式存貯。
關鍵字:無類型
、字節碼
。
4. Time Stamp
HBase 中通過rowkey
和columns
確定的爲一個存貯單元稱爲cell。每個 cell都保存 着同一份數據的多個版本
。版本通過時間戳
來索引。時間戳的類型是 64位整型。時間戳可以由HBase(在數據寫入時自動 )賦值,此時時間戳是精確到毫秒 的當前系統時間。時間戳也可以由客戶顯式賦值。如果應用程序要避免數據版 本衝突,就必須自己生成具有唯一性的時間戳。每個 cell中,不同版本的數據按照時間倒序排序,即最新的數據排在最前面。
爲了避免數據存在過多版本造成的的管理 (包括存貯和索引)負擔,HBase提供 了兩種數據版本回收方式。一是保存數據的最後n個版本,二是保存最近一段 時間內的版本(比如最近七天)。用戶可以針對每個列族進行設置。
5. 命名空間
命名空間的結構:
- Table:表,所有的表都是命名空間的成員,即表必屬於某個命名空間,如果沒有指定,則在default默認的命名空間中。
- RegionServer group:一個命名空間包含了默認的RegionServer Group。
- Permission:權限,命名空間能夠讓我們來定義訪問控制列表ACL(Access Control List)。例如,創建表,讀取表,刪除,更新等等操作。
- Quota:限額,可以強制一個命名空間可包含的region的數量。
4. HBase 原理
HBase是一個寫比讀快的 框架
寫原理
比如執行給table1裏面rowkey=11050的數據插入數據則看如下操作。
- 先跟ZK 詢問
/hbase/meta-region-server
裏面的 meta數據存儲位置。 - 客戶1找到的位置到對應的機器上查找regions數據存儲概要。一般一行就是存儲該數據的
表明,rowkey開始位置,rowkey結束位置
,根據合適的範圍查找到對應的 regionServer,然後再根據數據信息 找到對應的region,然後數據寫到WAL中,再到MemCache,再到HFile(KV格式存儲
)。
寫流程:
- Client 先訪問 zookeeper,獲取 hbase:meta 表位於哪個 Region Server。
- 訪問對應的 Region Server,獲取 hbase:meta 表,根據讀請求的 namespace:table/rowkey,查詢出目標數據位於哪個 Region Server 中的哪個 Region 中。並將該 table 的 region 信息以及 meta 表的位置信息
緩存
在客戶端的 meta cache,方便下次訪問。 - 與目標 Region Server 進行通訊;
- 將數據順序寫入(追加)到 WAL
- 將數據寫入對應的 MemStore,數據會在 MemStore 進行排序
- 向客戶端發送 ack;
- 等達到 MemStore 的刷寫時機後,將數據刷寫到 HFile
- 在web頁面查看的時候會隨機的給每一個region生成一個隨機編號。
PS ZK數據查找跟更新的 流程:
zk ==> meta ==> regionserver ==> RegionIP
HBase0.9版本前 meta數據又要被切分 -root-
zk ==> -root- ==> meta ==> regionserver ==> RegionIP
讀原理
- Client 先訪問 zookeeper,獲取 hbase:meta 表位於哪個 Region Server。
- 訪問對應的 Region Server,獲取 hbase:meta 表,根據讀請求的 namespace:table/rowkey, 查詢出目標數據位於哪個 Region Server 中的哪個 Region 中。並將該 table 的 region 信息以 及 meta 表的位置信息緩存在客戶端的 meta cache,方便下次訪問。
- 與目標 Region Server 進行通訊;
- 分別在 Block Cache(讀緩存),MemStore 和 Store File(HFile)中查詢目標數據,並將 查到的所有數據進行合併。此處所有數據是指同一條數據的不同版本(time stamp)或者不 同的類型(Put/Delete)。
- 將從文件HFile中查詢到的數據塊(Block,HFile 數據存儲單元,默認大小爲 64KB)緩存到 Block Cache。
- 將合併後的最終結果,然後返回時間最新的數據返回給客戶端。
- hbase中兩種緩存機制 memstore和blockcache詳解
重點
:不要理解爲讀數據先從MemStore中讀取,然後讀BlockCache中,如果沒有再從HFile中讀取,然後將數據寫入到BlockCache中。因爲如果下面這樣的操作怎麼辦?
- 創建表,寫入數據,刷新到磁盤中,
create stu ‘info’
put ‘stu’,‘info:name’,‘sowhat’
flush
bin/hbase org.apache.hadoop.hbase.io.hfile.HFile -a -b -e -k -p -f 列族文件在HDFS中路徑, 目的確保數據刷新到本地了
- 插入一個比
sowhat
時間早的數據,
put ‘stu’,‘info:name’,‘sowhat1412’,早點的時間戳。
- 直接scan查詢可以看到 結果還是
sowhat
,說明數據每次都是把磁盤數據讀取了放到BlockCache中,然後跟MemCache數據合併!比較時間戳,返回時間戳最新的數據。也就是每次都要涉及到磁盤到讀取。
結論:HBase 把磁盤跟內存數據一起讀,然後把磁盤數據放到BlockCache中
,BlockCache是磁盤數據的緩存。讀比寫慢的工具。
Scanner
查詢流程的形象圖
Flush
一般情況下一個Region中有多個列族,而整個region中有列族跟store是一 一對應的。對於用戶來說數據寫到MemStore
中就算完成了,但是對於底層代碼來說只有數據刷到硬盤中才算徹底搞定了!因爲數據是要寫入到WAL(Hlog)中再寫入到MemStore
中的,所以刷寫的時候,也有WAL個數的配置。配置文件
- WAL 個數 .
當 WAL 文件的數量超過 hbase.regionserver.max.logs,region 會按照時間順序依次進行刷寫,直到 WAL 文件數量減小到 hbase.regionserver.max.log 以下(
該屬性名已經廢棄
,
現無需手動設置,最大值爲 32)。比如我的堆內存0.4= 1T,那麼我的Hlog文件可能也是大小1T,這樣如果一個HLog文件大小爲512M 則可能出現 10242個,所以需合理配置。
- hbase.
regionserver
.global.memstore.size
regionServer的
全局memstore
的大小,超過該大小會觸發flush到磁盤的操作,默認是堆大小的40%,而且regionserver級別的 , flush會阻塞客戶端讀寫。
- hbase.
regionserver
.global.memstore.size.lower.limit
可以理解爲一個安全的設置,有時候集羣的“寫負載”非常高,寫入量一直超過flush的量,這時,我們就希望memstore不要超過一定的安全設置。 在這種情況下,寫操作就要被阻塞一直到memstore恢復到一個“可管理”的大小, 這個大小就是默認值是堆大小 * 0.4 * 0.95,也就是當regionserver級別的flush操作發送後,會阻塞客戶端寫,一直阻塞到整個regionserver級別的memstore的大小爲 堆大小 * 0.4 *0.95爲止
- hbase.
regionserver
.optionalcacheflushinterval
內存中的文件在自動刷新之前能夠存活的最長時間,默認是1h,表示最後一條數據後的1小時。
- hbase.hregion.memstore.flush.size
單個region裏memstore的緩存大小,超過那麼整個HRegion就會flush,
默認128M
StoreFile Compaction
由於 memstore 每次刷寫都會生成一個新的 HFile,且同一個字段的不同版本(timestamp) 和不同類型(Put/Delete)有可能會分佈在不同的 HFile 中,因此查詢時需要遍歷所有的 HFile。 爲了減少 HFile 的個數,以及清理掉過期和刪除的數據,會進行 StoreFile Compaction。
Compaction 分爲兩種,分別是 Minor Compaction
和 Major Compaction
。Minor Compaction會將臨近的若干個較小的 HFile 合併成一個較大的 HFile,但不會
清理過期和刪除的數據。 Major Compaction 會將一個 Store 下的所有的 HFile 合併成一個大 HFile,並且會清理掉過期和刪除的數據。
數據刪除時間
create ‘stu4’,‘info’
put ‘stu4’,‘1001’,‘info:name’,‘xianyi’
put ‘stu4’,‘1001’,‘info:name’,‘yuyang’
flush ‘stu4’ 刷新一個文件
put ‘stu4’,‘1001’,‘info:name’,‘xianyu’ 顯示
flush ‘stu4’ 增加個文件
put ‘stu4’,‘1002’,‘info:name’,‘xianyi’ 顯示
flush ‘stu4’
compact 三個以上的文件調用小文件合併會自動觸發大文件合併,
scan ‘stu4’,{RAW=>TRUE,VERSIONS=>10}
只會顯示兩個文件
數據刪除只有在flush 跟上面的大合併(Major compaction
)的時候執行。
- flush 可以刪除在同一個內存中的數據,flush只會操作當前內存。並且寫入本地後 內存數據會丟失。
- Major compaction 大合併時候會自動把所以數據排序刪除舊數據。
put ‘stu4’,‘1001’,‘info:name’,‘zhangsan’
put ‘stu4’,‘1001’,‘info:name’,‘lisi’
put ‘stu4’,‘1001’,‘info:name’,‘wangwu’
flush ‘stu4’
put ‘stu4’,‘1001’,‘info:name’,‘zhaoliu’ 此時查看可以看到zhaoliu
delete ‘stu4’,‘1001’,‘info:name’目的
是刪除1001的 name屬性!
scan ‘stu4’,{ROW=>TRUE,VERSIONS=>10} 會顯示zhaoliu 但顯示已經刪除了。此時flush ‘stu4’ 再查看數據,會發現Type=DeleteColumn還存在。沒有刪除掉,因爲這個DeleteColumn還要用來刪除flush 磁盤裏的zhangsan,lisi,wangwu這三個數據。 而刪除的標準就是調用大合併的時候!
Region Split
默認情況下,每個 Table 起初只有一個 Region,隨着數據的不斷寫Region 會自動進 行拆分。剛拆分時,兩個子 Region 都位於當前的 Region Server,但出於負載均衡的考慮, HMaster 有可能會將某個 Region 轉移給其他的 Region Server。
Region Split 時機:
- 當 1 個 region 中的某個 Store 下所有 StoreFile 的總大小超過 hbase.hregion.max.filesize(默認10G), 該 Region 就會進行拆分(0.94 版本
之前
)。 - 當 1 個 region 中的某個 Store 下所有 StoreFile 的總大小超過 Min(R^2 * “hbase.hregion.memstore.flush.size”,hbase.hregion.max.filesize"),該 Region 就會進行拆分,其 中 R 爲當前 Region Server 中屬於該 Table 的個數(0.94 版本之後)。hbase.hregion.memstore.flush.size=128M
第一次的閾值是128,
切分後結果64 , 64
第二次閾值512M
64,512 ⇒ 54 + 256 + 256
最後會形成一個 64M…10G 的這樣Region隊列,會產生數據傾斜
問題。
解決方法
:提前做好Region組的規劃,0-1k,1k-2k,2k-3k這樣的。
官方不建議用多個列族,比如有CF1,CF2,CF3,但是 CF1數據很多而CF2跟CF3數據很少,那麼當觸發了region切分的時候,會把CF2跟CF3分成若干小份,不利於系統維護。