ApsaraDB for HBase Performance-enhanced Edition sépare automatiquement les données chaudes et froides sur différents niveaux de stockage, selon une limite temporelle que vous définissez. Les données chaudes restent sur un stockage rapide pour un accès immédiat, tandis que les données froides sont transférées vers un stockage économique. Cette approche réduit les coûts de stockage des deux tiers par rapport aux disques ultra.
Quand utiliser cette fonctionnalité
La séparation des données chaudes et froides est idéale pour :
Les charges de travail de séries chronologiques où les données récentes sont fréquemment consultées, mais les données plus anciennes le sont rarement (par exemple, les historiques de commandes ou les métriques de surveillance).
Les cas d'utilisation nécessitant l'interrogation des données chaudes et froides à partir d'une seule table, sans avoir à maintenir des tables distinctes.
Évitez cette fonctionnalité si :
Votre charge de travail implique des mises à jour fréquentes des données historiques. La mise à jour d'un champ stocké en tant que donnée froide le fait revenir dans le stockage chaud, ce qui peut entraîner des résultats de requête inattendus.
Fonctionnement
Lorsque des données sont écrites dans une table, ApsaraDB for HBase Performance-enhanced Edition compare l'horodatage des données à la valeur COLD_BOUNDARY que vous avez configurée. L'horodatage de chaque enregistrement correspond à l'heure d'écriture des données dans la table. Les nouvelles données sont stockées dans le stockage chaud (disques standard). Au fil du temps, lorsque les données dépassent la limite définie, le système les déplace automatiquement vers le stockage froid lors de la prochaine compaction majeure, de manière transparente pour votre application.
Le déplacement des données s'effectue dans les deux sens : du froid vers le chaud et du chaud vers le froid.
Le débit du stockage froid est inférieur à celui du stockage chaud. Concevez vos requêtes de manière à cibler les données chaudes lorsque le temps de réponse est critique.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
ApsaraDB for HBase Performance-enhanced Edition mis à niveau vers la version V2.1.8 ou ultérieure.
Le stockage froid activé sur votre cluster. Consultez la section Stockage froid.
Si vous utilisez l'API Java : AliHBase-Connector 1.x supérieur à 1.0.7, ou AliHBase-Connector 2.x supérieur à 2.0.7. Consultez la section Utilisation de l'API Java ApsaraDB for HBase pour accéder à une instance ApsaraDB for HBase Performance-enhanced Edition.
Si vous utilisez HBase Shell : version supérieure à alihbase-2.0.7-bin.tar.gz. Consultez la section Utilisation de HBase Shell pour accéder à une instance ApsaraDB for HBase Performance-enhanced Edition.
Configuration de la limite temporelle
Le paramètre COLD_BOUNDARY spécifie la durée pendant laquelle les données restent dans le stockage chaud avant d'être déplacées vers le stockage froid. La valeur est exprimée en secondes.
Par exemple, COLD_BOUNDARY=86400 signifie que les données écrites il y a plus de 86 400 secondes (un jour) sont traitées comme des données froides.
Utilisez HBase Shell ou l'API Java pour créer une table avec séparation des données chaudes et froides, ou pour modifier la limite sur une table existante.
HBase Shell
// Create a table with cold and hot data separation.
hbase(main):002:0> create 'chsTable', {NAME=>'f', COLD_BOUNDARY=>'86400'}
// Change the time boundary on an existing table.
hbase(main):005:0> alter 'chsTable', {NAME=>'f', COLD_BOUNDARY=>'86400'}
// Disable cold and hot data separation.
hbase(main):004:0> alter 'chsTable', {NAME=>'f', COLD_BOUNDARY=>""}
Avant de déplacer les données du stockage froid vers le stockage chaud, exécutez une compaction majeure sur la table.
Java API
Admin admin = connection.getAdmin();
TableName tableName = TableName.valueOf("chsTable");
// Create a table with cold and hot data separation.
// COLD_BOUNDARY is in seconds. This example archives data as cold after one day.
HTableDescriptor descriptor = new HTableDescriptor(tableName);
HColumnDescriptor cf = new HColumnDescriptor("f");
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, "86400");
descriptor.addFamily(cf);
admin.createTable(descriptor);
// Change the time boundary on an existing table.
HTableDescriptor descriptor = admin.getTableDescriptor(tableName);
HColumnDescriptor cf = descriptor.getFamily("f".getBytes());
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, "86400");
admin.modifyTable(tableName, descriptor);
// Disable cold and hot data separation.
// Run a major compaction before moving cold data back to hot storage.
HTableDescriptor descriptor = admin.getTableDescriptor(tableName);
HColumnDescriptor cf = descriptor.getFamily("f".getBytes());
cf.setValue(AliHBaseConstants.COLD_BOUNDARY, null);
admin.modifyTable(tableName, descriptor);
Ne définissez pas la propriété de la famille de colonnes sur COLD . Si elle est déjà définie, supprimez-la. Pour plus de détails, consultez la section Stockage froid .
Écriture des données
Écrivez les données de la même manière que pour une table standard ; aucune modification de votre code client n'est nécessaire. L'horodatage de chaque enregistrement détermine le niveau de stockage dans lequel il est placé. Consultez les sections Utilisation de l'API Java HBase pour accéder aux clusters ApsaraDB for HBase Performance-enhanced Edition et Utilisation de l'API multilingue pour accéder aux clusters ApsaraDB for HBase Performance-enhanced Edition.
Interrogation des données
Toutes les requêtes ciblent une seule table ; il n'est pas nécessaire d'interroger séparément les stockages chaud et froid. Le système achemine automatiquement chaque requête.
Trois modèles de requête sont disponibles :
| Modèle | Fonctionnement | Cas d'utilisation |
|---|---|---|
| Par défaut (sans indicateur) | Analyse les données chaudes et froides, puis fusionne les résultats. | Vous avez besoin de résultats complets, quel que soit le niveau de stockage. |
HOT_ONLY=true |
Analyse uniquement le stockage chaud ; aucun résultat n'est renvoyé si la ligne se trouve dans le stockage froid. | Vous souhaitez des réponses rapides et n'avez besoin que des données récentes. |
TimeRange |
Le système détermine le niveau de stockage à partir de la plage de temps et de la valeur COLD_BOUNDARY ; il analyse uniquement le niveau pertinent. |
Vous connaissez la plage de temps des données dont vous avez besoin. |
Les valeurs TIMERANGE dans les opérations GET et Scan sont exprimées en millisecondes .
Exemples Get
HBase Shell
// Default: may scan cold data.
hbase(main):013:0> get 'chsTable', 'row1'
// HOT_ONLY: scans only hot storage. No result is returned if the row is in cold storage.
hbase(main):015:0> get 'chsTable', 'row1', {HOT_ONLY=>true}
// TimeRange: system determines scope from TimeRange and COLD_BOUNDARY. Value is in milliseconds.
hbase(main):016:0> get 'chsTable', 'row1', {TIMERANGE => [0, 1568203111265]}
Java API
Table table = connection.getTable("chsTable");
// Default: may scan cold data.
Get get = new Get("row1".getBytes());
System.out.println("result: " + table.get(get));
// HOT_ONLY: scans only hot storage. No result is returned if the row is in cold storage.
get = new Get("row1".getBytes());
get.setAttribute(AliHBaseConstants.HOT_ONLY, Bytes.toBytes(true));
// TimeRange: system determines scope from TimeRange and COLD_BOUNDARY. Value is in milliseconds.
get = new Get("row1".getBytes());
get.setTimeRange(0, 1568203111265);
Exemples Scan
Sans l'indicateur HOT_ONLY ni plage de temps, une opération Scan lit à la fois les données chaudes et froides, puis fusionne les résultats.
HBase Shell
// Default: scans both hot and cold data.
hbase(main):017:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9'}
// HOT_ONLY: scans only hot storage.
hbase(main):018:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9', HOT_ONLY=>true}
// TimeRange: system determines scope from TimeRange and COLD_BOUNDARY. Value is in milliseconds.
hbase(main):019:0> scan 'chsTable', {STARTROW =>'row1', STOPROW=>'row9', TIMERANGE => [0, 1568203111265]}
Java API
TableName tableName = TableName.valueOf("chsTable");
Table table = connection.getTable(tableName);
// Default: scans both hot and cold data.
Scan scan = new Scan();
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
System.out.println("scan result:" + result);
}
// HOT_ONLY: scans only hot storage.
scan = new Scan();
scan.setAttribute(AliHBaseConstants.HOT_ONLY, Bytes.toBytes(true));
// TimeRange: system determines scope from TimeRange and COLD_BOUNDARY. Value is in milliseconds.
scan = new Scan();
scan.setTimeRange(0, 1568203111265);
Priorisation des données chaudes dans les résultats de scan
Pour les charges de travail telles que la consultation de toutes les commandes ou messages de chat d'un client, les résultats sont généralement triés par horodatage décroissant, de sorte que les données récentes (chaudes) apparaissent en premier. Par défaut, le système analyse toujours les deux niveaux, ce qui augmente la latence des requêtes lorsque des données froides sont impliquées.
La définition de COLD_HOT_MERGE=true indique au système d'analyser d'abord le stockage chaud. Les données froides ne sont récupérées que si davantage de résultats sont nécessaires (par exemple, lorsqu'un utilisateur parcourt les pages précédentes des résultats). Cela réduit l'accès aux données froides et améliore le temps de réponse initial.
HBase Shell
hbase(main):002:0> scan 'chsTable', {COLD_HOT_MERGE=>true}
Java API
scan = new Scan();
scan.setAttribute(AliHBaseConstants.COLD_HOT_MERGE, Bytes.toBytes(true));
scanner = table.getScanner(scan);
Lorsque COLD_HOT_MERGE=true, les résultats pour les données chaudes et froides sont renvoyés séparément, chacun étant trié par clé de ligne. L'ensemble de résultats global n'est pas trié globalement. L'exemple suivant illustre cette différence :
// Default scan: rows sorted lexicographically. coldRow appears before 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: hot data is returned first, then cold data.
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)
Si une ligne a été partiellement mise à jour (certains champs sont revenus dans le stockage chaud), COLD_HOT_MERGE=true renvoie deux entrées pour cette clé de ligne : une provenant du stockage chaud et une du stockage froid. Pour garantir un ordre cohérent au sein d'un niveau, utilisez une clé de ligne composite. Par exemple, pour une table de commandes, combinez l'ID client et l'heure de création de la commande dans la clé de ligne afin que les commandes d'un client donné soient triées par heure.
Remarques d'utilisation
Utilisez
HOT_ONLYouTimeRangepour la plupart des requêtes. Le stockage froid est conçu pour l'archivage, non pour un accès fréquent. Si votre cluster reçoit de nombreuses requêtes touchant des données froides, vérifiez si la valeurCOLD_BOUNDARYest appropriée.Évitez de mettre à jour les données froides. La mise à jour d'un champ dans une ligne de stockage froid fait revenir ce champ dans le stockage chaud. Les requêtes suivantes utilisant
HOT_ONLYou une plage de temps ciblant les données chaudes ne renvoient que le champ mis à jour, et non la ligne complète. Si vous devez renvoyer la ligne complète, supprimez l'indicateurHOT_ONLYou définissez une plage de temps couvrant l'heure d'écriture initiale jusqu'à la dernière heure de mise à jour. Si des mises à jour fréquentes des données froides sont inévitables, ajustezCOLD_BOUNDARYpour faire revenir les données concernées dans le stockage chaud.
Vérification des tailles des données chaudes et froides
Consultez les tailles des données chaudes et froides par table dans l'onglet User tables de ClusterManager. Pour plus de détails, consultez la section Système de gestion de cluster.
Si aucune donnée n'apparaît dans le stockage froid, cela signifie peut-être qu'elle se trouve encore dans la mémoire vive (RAM). Exécutez la commande flush pour écrire les données sur le disque, puis effectuez une compaction majeure et vérifiez à nouveau.