ビッグデータ:Hbase
- Hbaseとは
Hbaseは、大規模なデータストレージ、物理構造ストレージ構造(KV)をサポートする分散型の拡張可能なNoSQLデータベースです。
- Hbaseがない場合
ビッグデータシナリオで数億のデータを数秒で返す方法。(条件付き:単一データ、範囲データ)
1 Hbase構造とデータ型
- 論理構造
- 物理的構造
ロウ全体(地域)に合わせて時計全体が横方向にカットされます。次に、ColumnFamilyを押して垂直方向にカット(保存)します。
-
名前空間:名前空間
- リレーショナルデータベースのデータベースの概念と同様に、各ネームスペースの下に複数のテーブルを配置できます。デフォルトでは、hbaseとdefaultの2つのネームスペースがあります。HbaseはHbaseの組み込みテーブルを格納します。デフォルトのテーブルは、ユーザーが使用するデフォルトのネームスペースです。(たとえば、名前空間testは、test:orderと書くことができる注文テーブルに割り当てられます)
-
行:行
- Hbaseの各データ行は、RowKeyと複数の列で構成されています。
-
列:列
- Hbaseの各列は、ColumnFamily(列ファミリー)およびColumnQualifier(列修飾子)によって修飾されます(例:personal_info:name、personal_info:city)
-
セル:セル
- {RowKey、ColumnFamily、ColumnQualifier、TimeStamp}によって一意に決定される単位、Cell内のデータは型指定されず、すべてバイトコードで格納されます。
-
行キー:行キー
- 行キーはテーブル内で一意であり、存在している必要があります。
- 行キーは、辞書式順序に従って配置されます(1つの値は、値がないことよりも大きくなります)。たとえば、row_key11は、row_key1とrow_ley2の間に配置されます。
- テーブルへのすべてのアクセスは、行キーを経由する必要があります。(単一のRowKeyアクセス、またはRowKey範囲アクセス、または全表スキャン)
-
ColumnFamily:列ファミリー
- Hbaseテーブルを作成するときはCFを指定するだけでよく、データを挿入するときに、必要に応じて列(フィールド)を動的に増やすことができます。
- 各CFには1つ以上の列メンバー(ColumnQualifier)を含めることができます。
- 異なる列ファミリーは、hdfsの異なるフォルダーに格納されます。
-
TimeStamp:タイムスタンプ
- さまざまなバージョンのデータを識別するために使用されます。タイムスタンプを指定しない場合、Hbaseはデータの書き込み時に現在のシステムタイムスタンプをこのフィールド値に自動的に追加します。
2 Hbaseアーキテクチャ
上の図のコンポーネントの機能を、小さいものから大きいものへと説明します。
-
StoreFile
- StoreFileはHBaseが実際に保存するファイルであり、最終的にHDFSクライアントを介してDataNodeに保存されます。(つまり、Linuxディスク内)
-
お店
- スライスされた領域内の列ファミリーのセットとして理解できます。(上記のように、リージョンには複数の店舗があります)
- ストアには、Mem Store(メモリストレージ)、StoreFile(メモリからフラッシュされたデータ、より多くがマージされ、より大きなデータが分割されます)が含まれます
-
領域
- リージョンはテーブルのスライスとして理解でき、データサイズのしきい値と行キーに従ってリージョンが分割されます。
- HBaseは自動的にテーブルを水平に(行ごとに)複数の領域(領域)に分割し、各領域は連続したデータをテーブルに格納します。
- 各テーブルの最初には、リージョンは1つしかありません。データの継続的な挿入により、リージョンは増加し続けます。しきい値に達すると、リージョンは行キーに従って2つの新しいリージョンに分割されます。
- テーブルの行数が増えると、リージョンが増え、1つのテーブルのデータが複数のリージョンに保存されます。
-
愛する
- Hbaseの事前書き込みログは、特別な状況下でのデータ損失を防ぎます。
-
RegionServer
- データ操作(DML):get、put、delete
- 管理リージョン:SplitRegion(分割)、CompactRegion(マージ)
-
主人
- テーブルレベルの操作(DDL):作成、削除、変更
- RegionServerの管理:RegionServerのステータスを監視し、RegionServerにリージョンを割り当てます(マシンrs1、rs2、rs3がある場合、データはrs1のリージョンに書き込まれ、rs2、r3はアイドル状態です--->次に、rs1はリージョンの上限に達するために大量のデータを書き込まれますrs1は領域を均等に分割した後、それらの1つをrs3に送信して管理するようマスターに通知します。
3コマンドライン操作
3.1 hbaseをリンクする
- リンクhbase
hbase shell
- ヘルプコマンドの表示またはコマンドの詳細な使用
help
help '命令'
3.2名前空間の操作
3.2.1名前空間をクエリする
list_namespace
3.2.2ネームスペースの下のテーブルをクエリする
list_namespace_tables '命名空间名'
3.2.3名前空間の作成
create_namespace '命名空间名'
3.2.4名前空間の削除(名前空間を空にする必要があります)
drop_namespace '命名空间名'
3.3 DDL操作
3.3.1すべてのユーザーテーブルのクエリ
list
3.3.2テーブルの作成
create '命名空间:表', '列族1', '列族2', '列族3','列族4'...
図に示すように、一連の順序が狂っているフォルダがあります。この一連の順序が狂っているフォルダは、リージョン番号を表します
3.3.3テーブルの詳細を表示する
describe '命名空间:表'
VERSIONSが1であることがわかります。これは、このテーブルに格納できるデータのバージョンは1つだけであることを意味します。
3.3.4テーブル情報の変更
主にテーブルのバージョン保存情報を変更するために使用され、テーブルの作成時に指定することもできますが、シェルコマンドは複雑であるため、一般的にはchangeコマンドが使用されます。
alter '命名空间:表',{NAME=>'列族名',VERSIONS=>3}
3.3.5テーブルのステータスを変更する(テーブルは削除する前に無効にする必要があります)
- 故障表
disable '表'
- テーブルを有効にする
enable '表'
3.3.6テーブルの削除
delete '表'
3.4 DML操作
3.4.1データの挿入
put '命名空间:表','RowKey','列族:列','值'
put '命名空间:表','RowKey','列族:列','值',时间戳(版本控制)
図に示すように、データがメモリ内にあるため、生成されたデータファイルはありません。「テーブル」をフラッシュする必要があります。その後、データの着陸を確認できます。(フラッシュは、StoreFileを1回生成することです)
3.4.2スキャンテーブル
#全表扫描
scan '命名空间:表'
#范围扫描(左闭右开)
scan '命名空间:表',{STARTROW => 'RowKey',STOPROW=>'RowKey'} #扫描N个版本的数据 scan '命名空间:表',{RAW=>true,VERSIONS=>10}
3.4.3フラッシュ
flush '命名空间:表'
- データバージョン保持メカニズム
上記から、フラッシュはStoreFileを1回生成することであることがわかっており、データはテーブル予約のバージョンの数に応じて最新のデータを格納します。
例:予約済みバージョンの数が2の場合、v1、v2、v3の3つのデータを挿入すると、フラッシュ後に2つのデータv2、v3のみが残り、v4、v5、v6の3つのデータをフラッシュ後に挿入します。次のデータは、v2、v3、v5、v6の4つのバージョンです(この場合、2つのStoreFileファイル)。リージョンのマージまたは分割が発生すると、StoreFileファイルがマージされ、対応するリージョンに配置されます。このとき、データ予約バージョン数に応じて削除され、v2、v3、v5、v6はv5、v6となります。(手動フラッシュがない場合、または設定された自動フラッシュ時間がない場合、バージョンの数に応じてデータは削除されません)(デフォルトでは、3つ以上のStoreFileファイルがマージされます)
- 1つの列ファミリーは1つのMemStoreに対応します
- 各MemStoreは、HDFSにフラッシュするときに独立したStoreFileを生成します
- RegionServerグローバルMemStore更新時間:hbase.regionserver.global.memstore.size
- 単一のMemstore更新時間:hbase.hregion.memstore.flush.size
3.4.3データのクエリ
get '命名空间:表','RowKey'
get '命名空间:表','RowKey','列族' get '命名空间:表','RowKey','列族:列' #获取N个版本的数据 get '命名空间:表','RowKey',{COLUMN=>'列族:列',VERSIONS=>10}
3.4.4テーブルを空にする
truncate '命名空间:表'
3.4.5データを削除する
#delete '命名空间:表','RowKey','列族'(此命令行删除有问题,但是API可以)
delete '命名空间:表','RowKey','列族:列'
deleteall '命名空间:表','RowKey'
4読み書きプロセス
4.1書き込みプロセス
- クライアントは、ZKを介してメタデータストレージテーブルが配置されているRegionServerの場所をクエリして返します。
- メタデータをクエリし、テーブルを必要とするRegionServerを返します
-
クライアントは次回簡単に使用できるように情報をキャッシュします
-
PUTリクエストをRegionServerに送信し、操作ログ(WAL)を書き込み、次にメモリに書き込み、次にwalをHDFSに同期すると、それが終了します。(このステップでは、ログとメモリが正常に書き込まれるように、トランザクションがロールバックされます)
4.2読み取りプロセス
データを読み取るとき、MemStoreとStoreFileは一緒に読み取り、StoreFileのデータをBlockCacheに入れてから、メモリデータとBlockCacheタイムスタンプをマージし、最新のデータをフェッチして返します。
5マージと分割
- 圧縮
Memstoreはフラッシュされるたびに新しいHFileを生成し、同じバージョンの異なるバージョンと異なるタイプが異なるHFileに分散される可能性があるため、クエリを実行するときにすべてのHFileをトラバースする必要があります。HFileの数を減らし、期限切れのデータと削除されたデータをクリーンアップするために、StoreFileマージが実行されます。
圧縮は、マイナー圧縮とメジャー圧縮に分けられます。
マイナーコンパクションでは、隣接するいくつかの小さなHFileを1つの大きなHFileにマージしますが、期限切れのデータや削除されたデータはクリーンアップしません。
メジャーコンパクションは、ストア内のすべてのHFileを1つの大きなHFileにマージし、期限切れおよび削除されたデータをクリーンアップします。
パラメータ設定:
hbase.hregion.majorcompaction = 0
hbase.hregion.majorcompaction.jitter = 0
hbase.hstore.compactionThreshold = 3
- 分割
デフォルトでは、各テーブルの先頭にあるリージョンは1つだけです。データが書き込まれ続けると、リージョンは自動的に分割されます。分割されると、2つのサブリージョンが現在のリージョンサーバーに配置されますが、負荷分散の考慮事項として、HMasterリージョンは別のリージョンサーバーに転送できます。
パラメータ設定:
hbase.hregion.max.filesize = 5G(次の式ではMax1)(この値を減らして同時実行性を高めることができます)
hbase.hregion.memstore.flush.size = 258M(次の式のMax2)
各分割は、Max1とMax2のどちらか小さい方の値を比較します。[min(Max1、Max2 *リージョンの数* 2)]、ここでリージョンの数は、現在のリージョンサーバー内のテーブルのリージョンの数です。
自動セグメンテーションではホットスポットを回避できないため、プロダクションでホットスポットを回避するために、RowKeyを事前にパーティション化して設計することがよくあります。
6最適化
6.1複数の列ファミリーを使用しないようにする
フラッシュ中に複数の小さなファイルを生成しないようにするため。
6.2メモリの最適化
主な機能はテーブルデータのキャッシュですが、GCはフラッシュ時に使用されますが、大きすぎないため、クラスターリソースに応じて、通常、Hbaseクラスターメモリ全体の70%を割り当てます。16-> 48Gで十分です
6.3 HDFSで追加コンテンツを許可する
dfs.support.append = true(hdfs-site.xml、hbase-site.xml)
6.4 Optimize DataNodeは最大数の開いているファイルを許可します
dfs.datanode.max.transfer.threads = 4096(HDFS構成)
リージョンサーバーのレベルでのマージ操作では、リージョンサーバーは使用できません。クラスターリソースに応じてこの値を調整して、同時実行性を高めることができます。
6.5 RPCモニターの数を増やす
hbase.regionserver.handler.count = 30
クラスターの状況に応じて、この値を適切に増やすことができます。主な決定は、クライアント要求の数です。
6.6クライアントキャッシュの最適化
hbase.client.write.buffer = 100M(書き込みバッファー)
この値を増やすと、RPC呼び出しの数を減らすことができます。単一の場合、より多くのメモリが消費され、クラスターリソースの状況に応じて設定されます。
6.7マージとセグメンテーションの最適化
参照5マージおよび分割
6.8プレパーティション
- テーブル作成時にパラメータSPLITSを追加
create '命名空间:表', '列族1', '列族2', '列族3','列族4'...,SPLITS=>['分区号','分区号','分区号','分区号']
プレパーティションの数は、半年から1年までの推定データ量とリージョンの最大値に基づいて選択されます。
6.9 RowKey
- ハッシュ可能性:異なる領域に均等に分割
- 一意性:繰り返されません
- 長さ:70-100
オプション1:乱数、ハッシュ値。ただし、これを範囲クエリすることはできず、データの集中はありません。
オプション2:文字列の反転。たとえば、タイムスタンプが反転した後にハッシュ可能性が達成されますが、表示時の集中度は最初のものよりも優れています。
- 推奨生産計画:
#设计预分区键(如比如200个区) | ASCLL码为124只有 } 和 ~ 比它大,那么不管以后的RowKey使用什么字符,都是小于这个字符的,所以可以有效的得到RowKey规律
000|
001|
......
199|
# 1 设计RowKey键_ASCLL码为95
000_
001_
......
199_
# 2 根据业务唯一标识(如用户ID,手机号,身份证)和时间维度(比如按月:202004)计算后根据分区数取余(13408657784^202004)%199=分区号
# 想以什么时间进行查询就把什么往前提,如下数据需要查1月数据范围就是 000_13408657784_2020-04 -> 000_13408657784_2020-04|
000_13408657784_2020-04-01 12:12:12
......
199_13408657784_2020-04-01 24:12:12