1. Introducción
En este codelab, aprenderás a usar Cloud Bigtable con el cliente de HBase de Java.
Obtendrás información para hacer las siguientes acciones
- Cómo evitar errores comunes con el diseño del esquema
- Importa datos en un archivo de secuencias
- Consulta tus datos
Cuando termines, tendrás varios mapas con datos de autobuses de la ciudad de Nueva York. Por ejemplo, crearás este mapa de calor de los viajes en autobús en Manhattan:
¿Cómo calificarías tu experiencia en el uso de Google Cloud Platform?
¿Cómo usarás este instructivo?
2. Acerca del conjunto de datos
Observarás un conjunto de datos sobre los autobuses de la ciudad de Nueva York. Hay más de 300 rutas de autobuses y 5,800 vehículos que siguen esas rutas. Nuestro conjunto de datos es un registro que incluye el nombre del destino, el ID del vehículo, la latitud, la longitud, la hora de llegada esperada y la hora de llegada programada. El conjunto de datos se compone de instantáneas tomadas cada 10 minutos aproximadamente en junio de 2017.
3. Diseño de esquemas
Para obtener el mejor rendimiento de Cloud Bigtable, debes diseñar tu esquema con cuidado. En Cloud Bigtable, los datos se ordenan automáticamente de forma lexicográfica, por lo que, si diseñas bien tu esquema, es muy eficiente consultar datos relacionados. Cloud Bigtable permite realizar consultas con búsquedas de puntos por clave de fila o análisis de rangos de filas que muestran un conjunto contiguo de filas. Sin embargo, si tu esquema no está bien pensado, podrías tener que unir varias búsquedas de filas o, peor aún, realizar análisis completos de tablas, que son operaciones extremadamente lentas.
Planifica las consultas
Nuestros datos contienen una gran variedad de información, pero, en este codelab, usarás la ubicación y el destino del autobús.
Con esa información, podrías realizar las siguientes consultas:
- Obtener la ubicación de un solo autobús durante una hora determinada
- Obtén los datos correspondientes a un día completo para una línea de autobús o un autobús específico.
- Encuentra todos los autobuses en un rectángulo en un mapa.
- Obtener las ubicaciones actuales de todos los autobuses (si estabas transfiriendo estos datos en tiempo real)
Este conjunto de consultas no se puede realizar juntas de forma óptima. Por ejemplo, si ordenas por tiempo, no puedes realizar un análisis basado en una ubicación sin hacer un análisis completo de la tabla. Debes establecer prioridades según las consultas que ejecutas con mayor frecuencia.
En este codelab, te enfocarás en optimizar y ejecutar el siguiente conjunto de consultas:
- Obtener las ubicaciones de un vehículo específico en un plazo de una hora
- Obtén las ubicaciones de toda una línea de autobús en un plazo de una hora.
- Obtén la ubicación de todos los autobuses de Manhattan en una hora.
- Obtén las ubicaciones más recientes de todos los autobuses de Manhattan en una hora.
- Obtener las ubicaciones de toda una línea de autobuses durante el mes
- Obtén las ubicaciones de toda una línea de autobús con un destino determinado en un plazo de una hora.
Cómo diseñar la clave de fila
En este codelab, trabajarás con un conjunto de datos estático, pero diseñarás un esquema para la escalabilidad. Diseñarás un esquema que te permita transmitir más datos de bus en la tabla y que, aun así, tenga un buen rendimiento.
Este es el esquema propuesto para la clave de fila:
[Empresa de autobús/Línea de autobús/Marca de tiempo redondeada hacia abajo a la hora/ID del vehículo]. Cada fila tiene una hora de datos y cada celda contiene varias versiones de los datos con marca de tiempo.
En este codelab, usarás una familia de columnas para evitar complicaciones. Esta es una vista de ejemplo de cómo se ven los datos. Los datos se ordenan por clave de fila.
Clave de fila | 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. Crear instancia, tabla y familia
A continuación, crearás una tabla de Cloud Bigtable.
Primero, crea un proyecto nuevo. Usar Cloud Shell integrado, que puedes abrir haciendo clic en "Activar Cloud Shell" en la esquina superior derecha.
Configura las siguientes variables de entorno para facilitar la copia y el pegado de los comandos del codelab:
INSTANCE_ID="bus-instance" CLUSTER_ID="bus-cluster" TABLE_ID="bus-data" CLUSTER_NUM_NODES=3 CLUSTER_ZONE="us-central1-c"
Cloud Shell ya incluye las herramientas que usarás en este codelab, la herramienta de línea de comandos de gcloud, la interfaz de línea de comandos de cbt y Maven, ya instalados.
Habilita las API de Cloud Bigtable mediante la ejecución de este comando.
gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com
Ejecuta el siguiente comando para crear una instancia:
gcloud bigtable instances create $INSTANCE_ID \ --cluster=$CLUSTER_ID \ --cluster-zone=$CLUSTER_ZONE \ --cluster-num-nodes=$CLUSTER_NUM_NODES \ --display-name=$INSTANCE_ID
Después de crear la instancia, propaga el archivo de configuración de cbt y, luego, crea una tabla y una familia de columnas con los siguientes comandos:
echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc echo instance = $INSTANCE_ID >> ~/.cbtrc cbt createtable $TABLE_ID cbt createfamily $TABLE_ID cf
5. Importar datos
Importa un conjunto de archivos de secuencias para este codelab desde gs://cloud-bigtable-public-datasets/bus-data
siguiendo estos pasos:
Habilita la API de Cloud Dataflow mediante la ejecución de este comando.
gcloud services enable dataflow.googleapis.com
Ejecuta los siguientes comandos para importar la tabla.
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/*
Supervisa la importación
Puedes supervisar el trabajo en la IU de Cloud Dataflow. Además, puedes ver la carga en tu instancia de Cloud Bigtable con su IU de supervisión. La importación completa debería tardar 5 minutos.
6. Obtén el código
git clone https://github.com/googlecodelabs/cbt-intro-java.git cd cbt-intro-java
Para cambiar a Java 11, ejecuta los siguientes comandos:
sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 && export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
7. Realiza una búsqueda
La primera consulta que realizarás es una búsqueda simple de filas. Recibirás los datos de un autobús de la línea M86-SBS el 1 de junio de 2017, de 12:00 a.m. a 1:00 a.m. En ese momento, hay un vehículo con el ID NYCT_5824
en la línea de autobús.
Con esa información y conociendo el diseño del esquema (empresa de autobús/línea de autobús/marca de tiempo redondeada hacia abajo a la hora/ID del vehículo), puedes deducir que la clave de fila es:
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));
El resultado debería contener la ubicación más reciente del autobús en esa hora. Pero deseas ver todas las ubicaciones, por lo que debes establecer el número máximo de versiones en la solicitud 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));
En Cloud Shell, ejecuta el siguiente comando para obtener una lista de las latitudes y longitudes de ese autobús durante la hora:
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=lookupVehicleInGivenHour
Puedes copiar y pegar las latitudes y longitudes en la aplicación de MapMaker para visualizar los resultados. Después de algunas capas, se te indicará que crees una cuenta gratuita. Puedes crear una cuenta o simplemente eliminar las capas existentes que tengas. En este codelab, se incluye una visualización de cada paso, si solo deseas continuar. Este es el resultado de la primera consulta:
8. Realiza un análisis
Ahora, veamos todos los datos de la línea de autobuses para esa hora. El código de escaneo es bastante similar al código get. Le das al escáner una posición inicial y, luego, le indicas que solo quieres filas para la línea de autobús M86-SBS dentro de la hora indicada por la marca de tiempo 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);
Ejecuta el siguiente comando para obtener los resultados.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanBusLineInGivenHour
La app de Map Maker puede mostrar varias listas a la vez para que puedas ver cuáles de los autobuses son el vehículo en la primera consulta que realizaste.
Una modificación interesante de esta consulta es ver todo el mes de datos para la línea de autobús M86-SBS, y esto es muy fácil de hacer. Quita la marca de tiempo de la fila de inicio y el filtro de prefijo para obtener el resultado.
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);
Ejecuta el siguiente comando para obtener los resultados. (Habrá una lista larga de resultados).
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanEntireBusLine
Si copias los resultados en MapMaker, puedes ver un mapa de calor de la ruta del autobús. Las manchas de color naranja indican las paradas, y las manchas de color rojo brillante indican el comienzo y el final de la ruta.
9. Incorporar filtros
A continuación, filtrarás los autobuses que van hacia el este y los que van hacia el oeste, y crearás un mapa de calor separado para cada uno.
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);
Ejecuta el siguiente comando para obtener los resultados de los autobuses que van hacia el este.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingEast
Para obtener los autobuses que van hacia el oeste, cambia la cadena en valueFilter:
BusQueries.java
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Westside West End AV"));
Ejecuta el siguiente comando para obtener los resultados de los autobuses que van hacia el oeste.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingWest
Autobuses rumbo al este
Autobuses rumbo al oeste
Al comparar los dos mapas de calor, puedes ver las diferencias en las rutas, así como las diferencias en el ritmo. Una interpretación de los datos es que, en la ruta hacia el oeste, los autobuses están más detenidos, especialmente cuando entran en Central Park. Y en los autobuses que van hacia el este, realmente no hay muchos puntos de estrangulamiento.
10. Realiza un análisis de varios rangos
En la última consulta, abordarás el caso en el que te interesan muchas líneas de autobús en un área:
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);
Ejecuta el siguiente comando para obtener los resultados.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanManhattanBusesInGivenHour
11. Terminar
Realiza una limpieza para evitar cargos
Para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en este codelab, debes borrar tu instancia.
gcloud bigtable instances delete $INSTANCE_ID
Temas abordados
- Diseño de esquemas
- Configura una instancia, una tabla y una familia
- Importa archivos de secuencias con Dataflow
- Realizar consultas con una búsqueda, un análisis, un análisis con un filtro y un análisis de varios rangos
Próximos pasos
- Obtén más información sobre Cloud Bigtable en la documentación.
- Prueba otras características de Google Cloud Platform tú mismo. Revisa nuestros instructivos.
- Obtén información sobre cómo supervisar los datos de series temporales con la integración de OpenTSDB.