リアルタイムシステムHBAse読み書き最適化:大量書き込みに支障なし
hbaseを使用する過程でhbaseに書き込まれるデータ量が大きい場合,書き込まれないことがしばしば発生することが分かった.一方,hbaseベースの応用はリアルタイム性に高い要求があり,hbaseが読み書きできないとシステムの使用に大きく影響する.hbase書き込み最適化の手順を次に記録します.
1.Major Compaction禁止
hbaseでMajor Compactionを実行すると、regionはすべてのstorefileをマージするため、region全体が読めず、このregionのクエリーはすべてブロックされます.HBAseでは1日に1回程度Major Compactionがデフォルトで実行されます.私たちはMajor Compactionをオフにし、Cronスクリプトを使用して毎日システムが空いている間にすべてのテーブルに対してmajor compactionを実行します.
Major Compactionの構成:
デフォルトは1日です.各regionは作成時に現在の時間でregionMajorCompactionTimeを初期化し、次のmajor compaction時間を1+-0.2日に設定します.この値を0に設定してmajor compactionを禁止します.
major_compactionのスクリプト:すべてのtableを取り出し、major_を1つずつ実行します.compact:
2.split禁止
hbaseはsplit regionによってレベルのshardingを実現しているが、splitの過程で古いregionがラインオフし、新しいregionがcompactionを行い、その間に大量のデータが読み書きできない時間があるので、私たちのようなonlineシステムには耐えられない.私たちは同じように自動splitを禁止し、夜のシステムが空いている間にsplitoolの手動splitを実行します.
splitの構成を禁止する:
コンフィギュレーション・アイテムは、regionのサイズが設定値より大きいとhbaseがsplitを開始することを意味し、この値を500 Gに設定します.昼間はシステムが忙しい場合、1つのregionがこのサイズを超えないと考え、夜はsplitoolを実行してregionを分割します.
splitoolの論理は比較的簡単です.すべてのregionの情報を遍歴し、regionサイズがある値(例えば1 G)より大きい場合、splitはregionであり、これは1ラウンドのsplitであり、1ラウンド後にある値より大きいregionがなければ終了し、ある値より大きいregionがあれば、regionがあるしきい値より大きいまで新しいsplitを継続する.ここでsplitが完了したかどうかを判断する方法として、hdfs上の古いregionのフォルダがクリアされているかどうかをチェックすることでsplitが終了したかどうかを判断します.
3.blockingStoreFilesの設定
このパラメータの重要性は我々の性能テストで発見された.我々はmajorを禁じたcompactionとsplit後は理論的に書き込みに支障はないはずですが、テストでは単一regionの書き込み速度が10 M/sより大きい場合でも長時間書き込みできない場合があることがわかりました.logを見ると、この行のlog"Waited 90314 ms on a compaction to clean up'too many store files'」と、コードを見てみるとblockingStoreFilesというパラメータがおかしいことがわかります.
flushRegionでは現在のstoreのhfileの数がこの値より大きいかどうかを検出し、それより大きい場合はblockデータの書き込みを行い、他のスレッドがhfile compactを落とすのを待つ.このように、書き込み速度がcompactの速度を超えると、hbaseはregionのデータ書き込みを阻止する.
デフォルトは7
私たちはこの値を大きな値に設定して、この問題が私たちの書き込みをブロックしないようにします.
1.Major Compaction禁止
hbaseでMajor Compactionを実行すると、regionはすべてのstorefileをマージするため、region全体が読めず、このregionのクエリーはすべてブロックされます.HBAseでは1日に1回程度Major Compactionがデフォルトで実行されます.私たちはMajor Compactionをオフにし、Cronスクリプトを使用して毎日システムが空いている間にすべてのテーブルに対してmajor compactionを実行します.
Major Compactionの構成:
<property>
<name>hbase.hregion.majorcompaction</name>
<value>0</value>
</property>
デフォルトは1日です.各regionは作成時に現在の時間でregionMajorCompactionTimeを初期化し、次のmajor compaction時間を1+-0.2日に設定します.この値を0に設定してmajor compactionを禁止します.
major_compactionのスクリプト:すべてのtableを取り出し、major_を1つずつ実行します.compact:
TMP_FILE=tmp_tables
TABLES_FILE=tables.txt
echo "list" | hbase shell > tmp_tables
sleep 2
sed '1,6d' $TMP_FILE | tac | sed '1,2d' | tac > $TABLES_FILE
sleep 2
for table in $(cat $TABLES_FILE); do
echo "major_compact '$table'" | hbase shell
sleep 10
done
2.split禁止
hbaseはsplit regionによってレベルのshardingを実現しているが、splitの過程で古いregionがラインオフし、新しいregionがcompactionを行い、その間に大量のデータが読み書きできない時間があるので、私たちのようなonlineシステムには耐えられない.私たちは同じように自動splitを禁止し、夜のシステムが空いている間にsplitoolの手動splitを実行します.
splitの構成を禁止する:
<property>
<name>hbase.hregion.max.filesize</name>
<value>536870912000</value>
</property>
コンフィギュレーション・アイテムは、regionのサイズが設定値より大きいとhbaseがsplitを開始することを意味し、この値を500 Gに設定します.昼間はシステムが忙しい場合、1つのregionがこのサイズを超えないと考え、夜はsplitoolを実行してregionを分割します.
splitoolの論理は比較的簡単です.すべてのregionの情報を遍歴し、regionサイズがある値(例えば1 G)より大きい場合、splitはregionであり、これは1ラウンドのsplitであり、1ラウンド後にある値より大きいregionがなければ終了し、ある値より大きいregionがあれば、regionがあるしきい値より大きいまで新しいsplitを継続する.ここでsplitが完了したかどうかを判断する方法として、hdfs上の古いregionのフォルダがクリアされているかどうかをチェックすることでsplitが終了したかどうかを判断します.
3.blockingStoreFilesの設定
このパラメータの重要性は我々の性能テストで発見された.我々はmajorを禁じたcompactionとsplit後は理論的に書き込みに支障はないはずですが、テストでは単一regionの書き込み速度が10 M/sより大きい場合でも長時間書き込みできない場合があることがわかりました.logを見ると、この行のlog"Waited 90314 ms on a compaction to clean up'too many store files'」と、コードを見てみるとblockingStoreFilesというパラメータがおかしいことがわかります.
flushRegionでは現在のstoreのhfileの数がこの値より大きいかどうかを検出し、それより大きい場合はblockデータの書き込みを行い、他のスレッドがhfile compactを落とすのを待つ.このように、書き込み速度がcompactの速度を超えると、hbaseはregionのデータ書き込みを阻止する.
private boolean flushRegion(final FlushRegionEntry fqe) {
HRegion region = fqe.region;
if (!fqe.region.getRegionInfo().isMetaRegion() &&
isTooManyStoreFiles(region)) {
if (fqe.isMaximumWait(this.blockingWaitTime)) {
LOG.info("Waited " + (System.currentTimeMillis() - fqe.createTime) +
"ms on a compaction to clean up 'too many store files'; waited " +
"long enough... proceeding with flush of " +
region.getRegionNameAsString());
}
デフォルトは7
this.blockingStoreFilesNumber =
conf.getInt("hbase.hstore.blockingStoreFiles", 7);
if (this.blockingStoreFilesNumber == -1) {
this.blockingStoreFilesNumber = 1 +
conf.getInt("hbase.hstore.compactionThreshold", 3);
}
私たちはこの値を大きな値に設定して、この問題が私たちの書き込みをブロックしないようにします.
<property>
<name>hbase.hstore.blockingStoreFiles</name>
<value>2100000000</value>
</property>