1. Introduction
Dans cet atelier de programmation, vous allez découvrir comment utiliser Cloud Bigtable avec le client Java HBase.
Vous apprendrez à effectuer les tâches suivantes :
- Éviter les erreurs courantes lors de la conception de schémas
- Importer des données dans un fichier séquentiel
- Interroger les données
Lorsque vous aurez terminé, vous aurez plusieurs cartes affichant des données sur les bus à New York. Par exemple, vous allez créer cette carte de densité des trajets en bus à Manhattan:
Comment évalueriez-vous votre expérience de l'utilisation de Google Cloud Platform ?
Comment allez-vous utiliser ce tutoriel ?
<ph type="x-smartling-placeholder">2. À propos de l'ensemble de données
Vous allez voir un jeu de données sur les bus de la ville de New York. Ils comptent plus de 300 lignes de bus et 5 800 véhicules. Notre ensemble de données est un journal qui inclut le nom de la destination, l'identifiant du véhicule, la latitude, la longitude, l'heure d'arrivée prévue et l'heure d'arrivée prévue. L'ensemble de données est composé d'instantanés réalisés environ toutes les 10 minutes pour juin 2017.
3. Conception de schémas
Pour tirer le meilleur parti de Cloud Bigtable, vous devez concevoir votre schéma de manière réfléchie. Dans Cloud Bigtable, les données sont triées automatiquement de manière lexicographique. Par conséquent, si vous concevez bien votre schéma, l'interrogation des données associées s'avère très efficace. Cloud Bigtable permet d'effectuer des requêtes à l'aide de recherches de points par clé de ligne ou d'analyses de plages de lignes qui renvoient un ensemble de lignes contiguës. Toutefois, si votre schéma n'est pas bien conçu, vous pourriez vous retrouver à assembler plusieurs recherches de lignes ou, pire, à effectuer des analyses complètes de table, qui sont des opérations extrêmement lentes.
Planifier les requêtes
Nos données sont diverses, mais pour cet atelier de programmation, vous utiliserez la position et la destination du bus.
Avec ces informations, vous pouvez effectuer les requêtes suivantes:
- Obtenez la position d'un bus sur une heure donnée.
- Obtenez l'équivalent des données d'une journée pour une ligne de bus ou un bus spécifique.
- Trouvez tous les bus dans un rectangle sur une carte.
- Obtenez la position actuelle de tous les bus (si vous avez ingéré ces données en temps réel).
Cet ensemble de requêtes ne peut pas être effectué ensemble de manière optimale. Par exemple, si vous effectuez un tri par heure, vous ne pouvez pas effectuer d'analyse basée sur un lieu sans effectuer une analyse complète du tableau. Vous devez établir des priorités en fonction des requêtes que vous exécutez le plus souvent.
Dans cet atelier de programmation, vous allez vous concentrer sur l'optimisation et l'exécution de l'ensemble de requêtes suivant:
- Obtenez la position d'un véhicule spécifique sur une heure.
- Obtenez l'emplacement d'une ligne de bus complète sur une heure.
- Obtenez la position de tous les bus de Manhattan en une heure.
- Obtenez la position la plus récente de tous les bus à Manhattan en une heure.
- Obtenez la position géographique d'une ligne de bus complète au cours du mois.
- Obtenez l'emplacement d'une ligne de bus complète avec une destination spécifique en une heure.
Concevoir la clé de ligne
Pour cet atelier de programmation, vous travaillerez avec un ensemble de données statique, mais vous concevrez un schéma évolutif. Vous allez concevoir un schéma qui vous permettra de diffuser davantage de données de bus dans la table tout en continuant de fonctionner correctement.
Voici le schéma proposé pour la clé de ligne:
[Entreprise de bus/Ligne de bus/Code temporel arrondi à l'heure/ID du véhicule]. Chaque ligne contient une heure de données et chaque cellule contient plusieurs versions horodatées des données.
Pour cet atelier de programmation, vous allez utiliser une famille de colonnes pour simplifier les choses. Voici un exemple d'affichage des données. Les données sont triées par clé de ligne.
Clé de ligne | cf:VehicleLocation.Latitude | cf:VehicleLocation.Longitude | … |
MTA/M86-SBS/1496275200000/NYCT_5824 | 40.781212 @20:52:54.0040.776163 @20:43:19.0040.778714 @20:33:46.00 | -73.961942 @20:52:54.00-73.946949 @20:43:19.00-73.953731 @20:33:46.00 | … |
MTA/M86-SBS/1496275200000/NYCT_5840 | 40.780664 @20:13:51.0040.788416 @20:03:40.00 | -73.958357 @20:13:51.00 -73.976748 @20:03:40.00 | … |
MTA/M86-SBS/1496275200000/NYCT_5867 | 40.780281 @20:51:45.0040.779961 @20:43:15.0040.788416 @20:33:44.00 | -73.946890 @20:51:45.00-73.959465 @20:43:15.00-73.976748 @20:33:44.00 | … |
... | ... | ... | … |
4. Créer une instance, une table et une famille
Vous allez maintenant créer une table Cloud Bigtable.
Commencez par créer un projet. Utiliser la fenêtre Cloud Shell intégrée, que vous pouvez ouvrir en cliquant sur "Activer Cloud Shell" dans le coin supérieur droit.
Définissez les variables d'environnement suivantes pour faciliter la copie et le collage des commandes de l'atelier de programmation:
INSTANCE_ID="bus-instance" CLUSTER_ID="bus-cluster" TABLE_ID="bus-data" CLUSTER_NUM_NODES=3 CLUSTER_ZONE="us-central1-c"
Cloud Shell est fourni avec les outils que vous utiliserez dans cet atelier de programmation : l'outil de ligne de commande gcloud, l'interface de ligne de commande cbt et Maven, qui sont déjà installés.
Activez les API Cloud Bigtable en exécutant cette commande.
gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com
Créez une instance en exécutant la commande suivante:
gcloud bigtable instances create $INSTANCE_ID \ --cluster=$CLUSTER_ID \ --cluster-zone=$CLUSTER_ZONE \ --cluster-num-nodes=$CLUSTER_NUM_NODES \ --display-name=$INSTANCE_ID
Une fois l'instance créée, remplissez le fichier de configuration cbt, puis créez une table et une famille de colonnes en exécutant les commandes suivantes:
echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc echo instance = $INSTANCE_ID >> ~/.cbtrc cbt createtable $TABLE_ID cbt createfamily $TABLE_ID cf
5. Importer des données
Importez un ensemble de fichiers séquentiels à partir de gs://cloud-bigtable-public-datasets/bus-data
pour cet atelier de programmation en procédant comme suit:
Activez l'API Cloud Dataflow en exécutant cette commande.
gcloud services enable dataflow.googleapis.com
Exécutez les commandes suivantes pour importer la table.
NUM_WORKERS=$(expr 3 \* $CLUSTER_NUM_NODES) gcloud beta dataflow jobs run import-bus-data-$(date +%s) \ --gcs-location gs://dataflow-templates/latest/GCS_SequenceFile_to_Cloud_Bigtable \ --num-workers=$NUM_WORKERS --max-workers=$NUM_WORKERS \ --parameters bigtableProject=$GOOGLE_CLOUD_PROJECT,bigtableInstanceId=$INSTANCE_ID,bigtableTableId=$TABLE_ID,sourcePattern=gs://cloud-bigtable-public-datasets/bus-data/*
Surveiller l'importation
Vous pouvez surveiller la tâche dans l'interface utilisateur de Cloud Dataflow. Vous pouvez également afficher la charge sur votre instance Cloud Bigtable avec son UI de surveillance. L'ensemble de l'importation devrait prendre cinq minutes.
6. Obtenir le code
git clone https://github.com/googlecodelabs/cbt-intro-java.git cd cbt-intro-java
Passez à Java 11 en exécutant les commandes suivantes:
sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 && export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
7. Effectuer une recherche
La première requête que vous allez exécuter
est une simple recherche de lignes. Vous obtiendrez les données concernant un bus sur la ligne M86-SBS le 1er juin 2017 de minuit à 1h du matin. Un véhicule associé à l'identifiant NYCT_5824
se trouve sur la ligne de bus à cette date.
Avec ces informations et la conception du schéma (entreprise de bus/ligne de bus/horodatage arrondi à l'heure/ID du véhicule), vous pouvez en déduire que la clé de ligne est:
MTA/M86-SBS/1496275200000/NYCT_5824
BusQueries.java
private static final byte[] COLUMN_FAMILY_NAME = Bytes.toBytes("cf");
private static final byte[] LAT_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Latitude");
private static final byte[] LONG_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Longitude");
String rowKey = "MTA/M86-SBS/1496275200000/NYCT_5824";
Result getResult =
table.get(
new Get(Bytes.toBytes(rowKey))
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));
Le résultat devrait contenir la position la plus récente du bus pour cette heure. Mais comme vous souhaitez voir tous les emplacements, définissez le nombre maximal de versions dans la requête get.
BusQueries.java
Result getResult =
table.get(
new Get(Bytes.toBytes(rowKey))
.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));
Dans Cloud Shell, exécutez la commande suivante pour obtenir la liste des latitudes et longitudes de ce bus sur une heure donnée:
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=lookupVehicleInGivenHour
Vous pouvez copier et coller les latitudes et les longitudes dans l'application Map Maker pour visualiser les résultats. Après quelques couches, vous serez invité à créer un compte sans frais. Vous pouvez créer un compte ou simplement supprimer les calques existants. Cet atelier de programmation comprend une visualisation pour chaque étape, si vous souhaitez simplement suivre la procédure. Voici le résultat de cette première requête:
8. Effectuer une analyse
Examinons maintenant toutes les données de la ligne de bus pour cette heure. Le code de numérisation ressemble beaucoup à celui du code GET. Vous indiquez une position de départ au scanner, puis vous indiquez que vous ne voulez que les lignes de la ligne de bus M86-SBS dans l'heure indiquée par le code temporel 1496275200000.
BusQueries.java
Scan scan;
scan = new Scan();
scan.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME)
.withStartRow(Bytes.toBytes("MTA/M86-SBS/1496275200000"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/1496275200000"));
ResultScanner scanner = table.getScanner(scan);
Exécutez la commande suivante pour obtenir les résultats.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanBusLineInGivenHour
L'application Map Maker peut afficher plusieurs listes à la fois, ce qui vous permet de voir quel bus est le véhicule de la première requête que vous avez exécutée.
Une modification intéressante de cette requête consiste à afficher le mois entier de données pour la ligne de bus M86-SBS, ce qui est très facile à faire. Supprimez l'horodatage de la ligne de début et du filtre de préfixe pour obtenir le résultat.
BusQueries.java
scan.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));
// Optionally, reduce the results to receive one version per column
// since there are so many data points.
scan.setMaxVersions(1);
Exécutez la commande suivante pour obtenir les résultats. (Une longue liste de résultats s'affiche.)
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanEntireBusLine
Si vous copiez les résultats dans Map Maker, vous pouvez afficher une carte de densité de l'itinéraire de bus. Les blobs orange indiquent les arrêts, tandis que les blobs rouge vif indiquent le début et la fin de l'itinéraire.
9. Intégrer des filtres
Ensuite, vous filtrerez les bus allant vers l'est et les bus vers l'ouest et créerez une carte de densité distincte pour chacun d'eux.
BusQueries.java
Scan scan;
ResultScanner scanner;
scan = new Scan();
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Yorkville East End AV"));
scan.setMaxVersions(1)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));
scan.setFilter(valueFilter);
scanner = table.getScanner(scan);
Exécutez la commande suivante pour obtenir les résultats des bus qui vont vers l'est.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingEast
Pour faire en sorte que les bus aillent vers l'ouest, modifiez la chaîne dans le paramètre valueFilter:
BusQueries.java
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Westside West End AV"));
Exécutez la commande suivante pour obtenir les résultats pour les bus allant vers l'ouest.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingWest
Bus allant vers l'est
Bus allant vers l'ouest
En comparant les deux cartes de densité, vous pouvez observer les différences entre les itinéraires et le rythme. L'une des interprétations des données est que sur l'itinéraire allant vers l'ouest, les bus s'arrêtent davantage, surtout à l'entrée de Central Park. Et dans les bus en direction de l'est, il n'y a pas beaucoup d'étranglements.
10. Effectuer une analyse multiplage
Pour la dernière requête, vous répondrez au cas où vous vous souciez de nombreuses lignes de bus dans une zone:
BusQueries.java
private static final String[] MANHATTAN_BUS_LINES = {"M1","M2","M3",...
Scan scan;
ResultScanner scanner;
List<RowRange> ranges = new ArrayList<>();
for (String busLine : MANHATTAN_BUS_LINES) {
ranges.add(
new RowRange(
Bytes.toBytes("MTA/" + busLine + "/1496275200000"), true,
Bytes.toBytes("MTA/" + busLine + "/1496275200001"), false));
}
Filter filter = new MultiRowRangeFilter(ranges);
scan = new Scan();
scan.setFilter(filter);
scan.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan.withStartRow(Bytes.toBytes("MTA/M")).setRowPrefixFilter(Bytes.toBytes("MTA/M"));
scanner = table.getScanner(scan);
Exécutez la commande suivante pour obtenir les résultats.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanManhattanBusesInGivenHour
11. Finaliser
Effectuer un nettoyage pour éviter que des frais ne vous soient facturés
Pour éviter que les ressources utilisées dans cet atelier de programmation soient facturées sur votre compte Google Cloud Platform, vous devez supprimer votre instance.
gcloud bigtable instances delete $INSTANCE_ID
Points abordés
- Conception de schémas
- Configurer une instance, une table et une famille
- Importer des fichiers séquentiels avec Dataflow
- Interroger avec une recherche, une analyse, une analyse avec un filtre et une analyse multiplage
Étapes suivantes
- Pour en savoir plus sur Cloud Bigtable, consultez la documentation.
- Testez d'autres fonctionnalités de Google Cloud Platform. en consultant nos tutoriels.
- Découvrez comment surveiller les données de séries temporelles avec l'intégration d'OpenTSDB.