ApsaraDB for HBase パフォーマンス強化版では、ホット データとコールド データを異なる種類のストレージ メディアに個別に保存できます。これにより、ホット データ クエリの効率が向上し、データ ストレージ コストが削減されます。
背景情報
ビッグデータのシナリオでは、注文データや監視データなどのビジネス データは時間の経過とともに増加し、大容量のストレージ スペースが必要になります。同時に、大量の履歴データがアーカイブされ、ほとんど使用されません。企業は、コストを削減するために、この種のデータを保存するための費用対効果の高いストレージ方法を必要としています。そのため、ApsaraDB for HBase パフォーマンス強化版では、コールド データとホット データの分離機能が導入され、簡素化された O&M 構成を使用してストレージ コストを最小限に抑えることができます。ApsaraDB for HBase パフォーマンス強化版では、コールド データを保存するために新しいメディア(コールド ストレージ)を使用します。これにより、ウルトラ ディスクを使用する場合と比較して、ストレージ コストを 3 分の 2 削減できます。
ApsaraDB for HBase パフォーマンス強化版では、指定した時間境界に基づいて、同じテーブルに保存されているコールド データとホット データを自動的に分離できます。コールド データはコールド ストレージに自動的にアーカイブされます。コールド データとホット データを個別に保存するテーブルには、標準テーブルにアクセスするのと同じ方法でアクセスできます。コールド データとホット データを個別に保存するテーブルをクエリする場合、システムがコールド データとホット データのどちらをスキャンするかを判断するために、クエリ ヒントまたは時間範囲を指定するだけで済みます。
仕組み
ApsaraDB for HBase パフォーマンス強化版では、テーブルに書き込まれるデータがコールド データかホット データかは、データのタイムスタンプと指定された時間境界に基づいて判断されます。タイムスタンプはミリ秒単位です。新しいデータはホット ストレージに保存されます。データは時間の経過とともにコールド ストレージに移動されます。ビジネス要件に基づいて、コールド データとホット データを分離するための時間境界を変更できます。データは、コールド ストレージからホット ストレージに、またはホット ストレージからコールド ストレージに移動できます。
使用上の注意
使用上の注意については、「コールド ストレージ」をご参照ください。
使用方法
コールド ストレージを使用するには、ApsaraDB for HBase パフォーマンス強化版を V2.1.8 以降にアップグレードする必要があります。データの読み取りと書き込みのためにクライアントの依存関係を変更する必要はありません。次のいずれかの方法を使用して、テーブル スキーマを変更するだけで済みます。
Java API を使用する場合は、AliHBase-Connector 1.x のバージョンが 1.0.7 以降、AliHBase-Connector 2.x のバージョンが 2.0.7 以降である必要があります。ApsaraDB for HBase Java API を使用して ApsaraDB for HBase パフォーマンス強化版インスタンスにアクセスするの手順に従って、Java 用 SDK をインストールし、パラメータを構成します。
HBase Shell を使用する場合は、HBase Shell のバージョンが alihbase-2.0.7-bin.tar.gz 以降である必要があります。HBase Shell を使用して ApsaraDB for HBase パフォーマンス強化版インスタンスにアクセスするの手順に従って、HBase Shell をダウンロードして構成します。
コールド ストレージを有効にする
クラスターのコールド ストレージを有効にする方法については、「コールド ストレージ」をご参照ください。
テーブルの時間境界を指定する
COLD_BOUNDARY パラメータを変更して、コールド データとホット データを分離するための時間境界を変更できます。時間境界は秒単位で測定されます。たとえば、COLD_BOUNDARY の値が 86400 以上の場合、新しいデータは 86,400 秒(1 日に相当)後にコールド データとしてアーカイブされます。
コールド データとホット データの分離のために、列ファミリのプロパティを COLD に設定する必要はありません。プロパティを COLD に設定している場合は、プロパティを削除します。詳細については、「コールド ストレージ」をご参照ください。
[shell]
// コールド データとホット データを個別に保存するテーブルを作成します。
hbase(main):002:0> create 'chsTable', {NAME=>'f', COLD_BOUNDARY=>'86400'}
// コールド データとホット データの分離を無効にします。
hbase(main):004:0> alter 'chsTable', {NAME=>'f', COLD_BOUNDARY=>""}
// テーブルのコールド データとホット データの分離を有効にするか、時間境界を変更します。時間境界は秒単位で測定されます。
hbase(main):005:0> alter 'chsTable', {NAME=>'f', COLD_BOUNDARY=>'86400'}[java API]
// コールド データとホット データを個別に保存するテーブルを作成します。
Admin admin = connection.getAdmin();
TableName tableName = TableName.valueOf("chsTable");
HTableDescriptor descriptor = new HTableDescriptor(tableName);
HColumnDescriptor cf = new HColumnDescriptor("f");
// COLD_BOUNDARY パラメータは、コールド データとホット データを分離するための時間境界を指定します。単位:秒。この例では、新しいデータは 1 日後にコールド データとしてアーカイブされます。
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, "86400");
descriptor.addFamily(cf);
admin.createTable(descriptor);
// コールド データとホット データの分離を無効にします。
// 注:コールド ストレージからホット ストレージにデータを移動する前に、メジャー コンパクション操作を実行する必要があります。
HTableDescriptor descriptor = admin
.getTableDescriptor(tableName);
HColumnDescriptor cf = descriptor.getFamily("f".getBytes());
// コールド データとホット データの分離を無効にします。
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, null);
admin.modifyTable(tableName, descriptor);
// テーブルのコールド データとホット データの分離を有効にするか、時間境界を変更します。
HTableDescriptor descriptor = admin
.getTableDescriptor(tableName);
HColumnDescriptor cf = descriptor.getFamily("f".getBytes());
// COLD_BOUNDARY パラメータは、コールド データとホット データを分離するための時間境界を指定します。単位:秒。この例では、新しいデータは 1 日後にコールド データとしてアーカイブされます。
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, "86400");
admin.modifyTable(tableName, descriptor);データの書き込み
コールド データとホット データを個別に保存するテーブルには、標準テーブルにデータを書き込むのと同じ方法でデータを書き込むことができます。詳細については、「HBase Java API を使用して ApsaraDB for HBase パフォーマンス強化版クラスターにアクセスする」または「複数言語 API を使用して ApsaraDB for HBase パフォーマンス強化版クラスターにアクセスする」をご参照ください。データのタイムスタンプは、データがテーブルに書き込まれたtime です。新しいデータはホット ストレージ(標準ディスク)に保存されます。データの保存期間が COLD_BOUNDARY パラメータで指定された値を超えると、システムはメジャー コンパクション プロセス中にデータをコールド ストレージに自動的に移動します。このプロセスはユーザーにとって完全に透過的です。
データのクエリ
ApsaraDB for HBase パフォーマンス強化版では、1 つのテーブルを使用してコールド データとホット データを保存できます。1 つのテーブルからのみデータをクエリできます。保存期間が COLD_BOUNDARY パラメータで指定された値よりも短いデータをクエリする場合、GET または SCAN ステートメントで HOT_ONLY ヒントを構成して、ホット データのみをクエリできます。また、GET または SCAN ステートメントで TimeRange パラメータを構成して、クエリするデータの時間範囲を指定することもできます。システムは、指定した時間範囲に基づいて、クエリするデータがホット データかコールド データかを自動的に判断します。コールド データのクエリに必要な時間は、ホット データのクエリに必要な時間よりも長くなります。[コールド データの読み取りスループットは、ホット データの読み取りスループットよりも低くなります。]
例
Get
Shell
// この例では、HOT_ONLY ヒントは使用されていません。システムはコールド データをスキャンする場合があります。 hbase(main):013:0> get 'chsTable', 'row1' // この例では、HOT_ONLY ヒントが使用されています。システムはホット データのみをスキャンします。row1 がコールド ストレージに保存されている場合、クエリ結果は返されません。 hbase(main):015:0> get 'chsTable', 'row1', {HOT_ONLY=>true} // この例では、TimeRange パラメータが指定されています。システムは、TimeRange と COLD_BOUNDARY の値に基づいて、スキャンする必要があるデータのスコープを判断します。TIMERANGE の値はミリ秒単位で測定されます。 hbase(main):016:0> get 'chsTable', 'row1', {TIMERANGE => [0, 1568203111265]}Java
Table table = connection.getTable("chsTable"); // この例では、HOT_ONLY ヒントは使用されていません。システムはコールド データをスキャンする場合があります。 Get get = new Get("row1".getBytes()); System.out.println("result: " + table.get(get)); // この例では、HOT_ONLY ヒントが使用されています。システムはホット データのみをスキャンします。row1 がコールド ストレージに保存されている場合、クエリ結果は返されません。 get = new Get("row1".getBytes()); get.setAttribute(AliHBaseConstants.HOT_ONLY, Bytes.toBytes(true)); // この例では、TimeRange パラメータが指定されています。システムは、TimeRange と COLD_BOUNDARY の値に基づいて、スキャンする必要があるデータのスコープを判断します。TIMERANGE の値はミリ秒単位で測定されます。 get = new Get("row1".getBytes()); get.setTimeRange(0, 1568203111265)
Scan
SCAN ステートメントに HOT_ONLY ヒントまたは時間範囲を構成しない場合、コールド データとホット データの両方がクエリされます。クエリ結果は、ApsaraDB for HBase の SCAN 操作の仕組みに基づいてマージされ、返されます。
Shell
// この例では、HOT_ONLY ヒントは使用されていません。システムはホット データとコールド データの両方をスキャンします。 hbase(main):017:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9'} // この例では、HOT_ONLY ヒントが使用されています。システムはホット データのみをスキャンします。 hbase(main):018:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9', HOT_ONLY=>true} // この例では、TimeRange パラメータが指定されています。システムは、TimeRange と COLD_BOUNDARY の値に基づいて、スキャンする必要があるデータのスコープを判断します。TIMERANGE の値はミリ秒単位で測定されます。 hbase(main):019:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9', TIMERANGE => [0, 1568203111265]}
Java
TableName tableName = TableName.valueOf("chsTable"); Table table = connection.getTable(tableName); // この例では、HOT_ONLY ヒントは使用されていません。システムはホット データとコールド データの両方をスキャンします。 Scan scan = new Scan(); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println("scan result:" + result); } // この例では、HOT_ONLY ヒントが使用されています。システムはホット データのみをスキャンします。 scan = new Scan(); scan.setAttribute(AliHBaseConstants.HOT_ONLY, Bytes.toBytes(true)); // この例では、TimeRange パラメータが指定されています。システムは、TimeRange と COLD_BOUNDARY の値に基づいて、スキャンする必要があるデータのスコープを判断します。TIMERANGE の値はミリ秒単位で測定されます。 scan = new Scan(); scan.setTimeRange(0, 1568203111265);
コールド ストレージは、アクセス頻度の低いデータをアーカイブするためにのみ使用されます。ほとんどの場合、HOT_ONLY ヒントまたは時間範囲を指定して、ホット データのみをクエリすることをお勧めします。クラスターがコールド データにヒットする大量のクエリを受信する場合は、時間境界が適切な値に設定されているかどうかを確認できます。
コールド ストレージに保存されている行のフィールドを更新すると、更新後にフィールドはホット ストレージに移動されます。この行が HOT_ONLY ヒントまたはホット データにヒットするように構成された時間範囲を含むクエリにヒットすると、ホット ストレージ内の更新されたフィールドのみが返されます。行全体を返すようにするには、クエリ ステートメントから HOT_ONLY ヒントを削除するか、この行が挿入された時刻から最後に更新された時刻までの期間が指定された時間範囲内にあることを確認する必要があります。コールド ストレージに保存されているデータは更新しないことをお勧めします。コールド データを頻繁に更新する必要がある場合は、時間境界を調整してデータをホット ストレージに移動することをお勧めします。
コールド データとホット データのサイズをクエリする
[ClusterManager] の [ユーザー テーブル] タブで、テーブル内のコールド データとホット データのサイズを確認できます。詳細については、「Lindorm Insight でのクラスタ管理」をご参照ください。
コールド ストレージにデータが保存されていない場合、テーブル内のデータはランダム アクセス メモリ(RAM)に保存されている可能性があります。flush コマンドを実行してデータをディスクにフラッシュし、メジャー コンパクション操作を実行できます。メジャー コンパクション操作が完了したら、コールド データのサイズを確認します。
ホット データ選択の優先順位付け
SCAN クエリを実行して顧客のすべての注文やチャット記録などの情報をクエリするシナリオでは、システムはホット データとコールド データをスキャンして必要なデータをクエリする場合があります。クエリ結果は、データ行がテーブルに書き込まれたタイムスタンプに基づいて降順にページ分割されます。ほとんどの場合、ホット データはコールド データの前に表示されます。SCAN クエリで HOT_ONLY ヒントを使用しない場合、システムはホット データとコールド データをスキャンします。その結果、クエリ応答時間が長くなります。クエリでホット データ選択を優先する場合、システムは優先的にホット データをスキャンします。コールド データは、さらにクエリ結果を表示する場合にのみクエリされます。たとえば、さらに結果を返すようにシステムに指示する場合は、ページの [次のページ] アイコンをクリックできます。これにより、コールド データ アクセスの頻度と応答時間が短縮されます。
ホット データ選択を優先するには、SCAN クエリで COLD_HOT_MERGE パラメータの値を true に設定するだけで済みます。これは、システムが最初にホット データをスキャンすることを示します。さらにクエリ結果を表示する場合、システムはコールド データをスキャンします。
Shell
hbase(main):002:0> scan 'chsTable', {COLD_HOT_MERGE=>true}Java
scan = new Scan();
scan.setAttribute(AliHBaseConstants.COLD_HOT_MERGE, Bytes.toBytes(true));
scanner = table.getScanner(scan);行の特定のフィールドのデータが更新されるシナリオでは、行にはホット データとコールド データが保存されます。ホット データ優先機能を有効にすると、クエリ結果は 2 つのバッチで返されます。結果セットには、同じ行キーの 2 つの結果があります。
ホット データ優先機能が有効になると、システムはコールド データの前にホット データを返すため、指定されたコールド データの戻り行の行キー値は、指定されたホット データの戻り行の行キー値よりも小さくなる場合があります。SCAN クエリで返される結果は順番にソートされません。ホット データの行とコールド データの行は、行キー値に基づいて個別にソートされます。返される行のソート方法については、次のサンプル結果を参照してください。シナリオによっては、行キーを指定して、SCAN クエリの結果の順序を確保できます。たとえば、テーブルを使用して注文に関する情報を保存します。顧客 ID を保存する列と注文作成時刻を保存する列で構成される行キーを指定できます。これにより、顧客の注文をクエリすると、返される注文は注文作成時刻に基づいてソートされます。
// この例では、行キー値が coldRow の行はコールド データを保存し、行キー値が hotRow の行はホット データを保存します。
// ほとんどの場合、ApsaraDB for HBase の行は辞書順にソートされるため、行キー値が coldRow の行は、行キー値が hotRow の行の前に返されます。
hbase(main):001:0> scan 'chsTable'
ROW COLUMN+CELL
coldRow column=f:value, timestamp=1560578400000, value=cold_value
hotRow column=f:value, timestamp=1565848800000, value=hot_value
2 row(s)
// COLD_HOT_MERGE を true に設定すると、システムは最初に hotRow の行キー値を持つ行をスキャンします。その結果、行キー値が hotRow の行は、行キー値が coldRow の行の前に返されます。
hbase(main):002:0> scan 'chsTable', {COLD_HOT_MERGE=>true}
ROW COLUMN+CELL
hotRow column=f:value, timestamp=1565848800000, value=hot_value
coldRow column=f:value, timestamp=1560578400000, value=cold_value
2 row(s)