1. บทนำ
ใน Codelab นี้ คุณจะได้รับคำแนะนำเกี่ยวกับการใช้ Cloud Bigtable กับไคลเอ็นต์ Java HBase
คุณจะได้เรียนรู้วิธีการ
- หลีกเลี่ยงข้อผิดพลาดที่พบบ่อยด้วยการออกแบบสคีมา
- นำเข้าข้อมูลในไฟล์ลำดับ
- ค้นหาข้อมูล
เมื่อดำเนินการเสร็จแล้ว คุณจะมีแผนที่หลายแผนที่ที่แสดงข้อมูลรถประจำทางในนิวยอร์กซิตี้ ตัวอย่างเช่น คุณจะสร้างแผนที่ความนิยมของการเดินทางด้วยรถประจำทางในแมนฮัตตัน:
คุณจะให้คะแนนความพึงพอใจสำหรับประสบการณ์ในการใช้ Google Cloud Platform อย่างไร
คุณจะใช้บทแนะนำนี้อย่างไร
2. เกี่ยวกับชุดข้อมูล
คุณจะเห็นชุดข้อมูลเกี่ยวกับรถโดยสารในนิวยอร์กซิตี้ มีรถประจำทางมากกว่า 300 เส้นทางและยานพาหนะกว่า 5,800 คันไปตามเส้นทางเหล่านั้น ชุดข้อมูลของเราคือบันทึกที่มีชื่อจุดหมาย รหัสยานพาหนะ ละติจูด ลองจิจูด เวลาที่คาดว่าจะมาถึง และเวลาถึงตามกำหนดการ ชุดข้อมูลนี้ประกอบด้วยสแนปชอตที่ถ่ายทุกๆ 10 นาทีในเดือนมิถุนายน 2017
3. การออกแบบสคีมา
หากต้องการประสิทธิภาพที่ดีที่สุดจาก Cloud Bigtable คุณต้องใช้ความรอบคอบเมื่อออกแบบสคีมา ข้อมูลใน Cloud Bigtable จะได้รับการจัดเรียงโดยอัตโนมัติแบบพจนานุกรม ดังนั้นหากคุณออกแบบสคีมาได้ดี การค้นหาข้อมูลที่เกี่ยวข้องจะมีประสิทธิภาพมาก Cloud Bigtable อนุญาตให้มีการค้นหาโดยใช้การค้นหาจุดตามคีย์แถวหรือการสแกนช่วงแถวซึ่งแสดงผลชุดแถวที่ต่อเนื่องกัน อย่างไรก็ตาม หากคุณออกแบบสคีมามาอย่างถี่ถ้วนแล้ว คุณอาจพบว่าตัวเองต้องการค้นหาแถวหลายแถวต่อกัน หรือถ้าแย่กว่านั้นคือการสแกนทั้งตาราง ซึ่งการดำเนินการช้ามาก
วางแผนการค้นหา
ข้อมูลของเรามีข้อมูลที่หลากหลาย แต่สำหรับ Codelab นี้ คุณจะใช้ตำแหน่งและปลายทางของรถบัส
ด้วยข้อมูลดังกล่าว คุณสามารถดำเนินการค้นหาต่อไปนี้
- ดูตำแหน่งของรถประจำทาง 1 คันใน 1 ชั่วโมง
- รับข้อมูลที่ตลอดทั้งวันสำหรับสายรถประจำทางหรือรถประจำทางเฉพาะ
- หาป้ายรถประจำทางทุกคันที่อยู่ในรูปสี่เหลี่ยมผืนผ้าบนแผนที่
- ดูตำแหน่งปัจจุบันของรถประจำทางทั้งหมด (หากคุณนำเข้าข้อมูลนี้แบบเรียลไทม์)
การสืบค้นชุดนี้ไม่สามารถทำงานร่วมกันได้อย่างมีประสิทธิภาพ เช่น หากจัดเรียงตามเวลา คุณจะสแกนตามตำแหน่งไม่ได้หากไม่สแกนตารางแบบเต็ม คุณต้องจัดลำดับความสำคัญตามคำค้นหาที่ใช้บ่อยที่สุด
สำหรับ Codelab นี้ คุณจะมุ่งเน้นที่การเพิ่มประสิทธิภาพและเรียกใช้ชุดข้อความค้นหาต่อไปนี้
- รับข้อมูลตำแหน่งของยานพาหนะคันหนึ่งๆ ในช่วง 1 ชั่วโมงขึ้นไป
- ดูตำแหน่งของรถประจำทางทั้งสายนานกว่า 1 ชั่วโมง
- ดูตำแหน่งของรถเมล์ทุกคันในแมนฮัตตันภายใน 1 ชั่วโมง
- ดูตำแหน่งล่าสุดของรถประจำทางทั้งหมดในแมนฮัตตันใน 1 ชั่วโมง
- ดูตำแหน่งของรถประจำทางทั้งสายในเดือนต่างๆ
- ดูตำแหน่งของรถบัสทั้งสายที่มีปลายทางนั้นๆ ใน 1 ชั่วโมง
ออกแบบคีย์ประจำแถว
สำหรับ Codelab นี้ คุณจะทำงานกับชุดข้อมูลแบบคงที่ แต่จะออกแบบสคีมาสำหรับความสามารถในการปรับขนาด คุณจะต้องออกแบบสคีมาที่ให้คุณสามารถสตรีมข้อมูลรถประจำทางมากขึ้นลงในตารางและยังคงทำงานได้ดี
สคีมาที่เสนอสําหรับคีย์แถวมีดังนี้
[บริษัทเดินรถประจำทาง/สายรถประจำทาง/การประทับเวลาปัดเศษเป็นชั่วโมง/รหัสยานพาหนะ] แต่ละแถวจะมีข้อมูล 1 ชั่วโมง และแต่ละเซลล์มีข้อมูลเวอร์ชันที่มีการประทับเวลาหลายเวอร์ชัน
สำหรับ Codelab นี้ คุณจะใช้กลุ่มคอลัมน์เดียวเพื่อทำให้ทุกอย่างเรียบง่าย ต่อไปนี้เป็นตัวอย่างมุมมองของข้อมูล ข้อมูลจะจัดเรียงตามคีย์ของแถว
คีย์ประจำแถว | 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. สร้างอินสแตนซ์ ตาราง และครอบครัว
ถัดไป คุณจะสร้างตาราง Cloud Bigtable
ก่อนอื่นให้สร้างโปรเจ็กต์ใหม่ ใช้ Cloud Shell ในตัว ซึ่งเปิดได้โดยคลิก "เปิดใช้งาน Cloud Shell" ที่มุมบนขวา
ตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้เพื่อให้คัดลอกและวางคำสั่ง Codelab ได้ง่ายขึ้น
INSTANCE_ID="bus-instance" CLUSTER_ID="bus-cluster" TABLE_ID="bus-data" CLUSTER_NUM_NODES=3 CLUSTER_ZONE="us-central1-c"
Cloud Shell มาพร้อมกับเครื่องมือที่คุณจะใช้ใน Codelab นี้ เครื่องมือบรรทัดคำสั่ง gcloud อินเทอร์เฟซบรรทัดคำสั่ง cbt และ Maven ที่ติดตั้งไว้แล้ว
เปิดใช้ Cloud Bigtable API โดยการเรียกใช้คำสั่งนี้
gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com
สร้างอินสแตนซ์โดยการเรียกใช้คำสั่งต่อไปนี้
gcloud bigtable instances create $INSTANCE_ID \ --cluster=$CLUSTER_ID \ --cluster-zone=$CLUSTER_ZONE \ --cluster-num-nodes=$CLUSTER_NUM_NODES \ --display-name=$INSTANCE_ID
หลังจากสร้างอินสแตนซ์แล้ว ให้สร้างไฟล์การกำหนดค่า cbt แล้วสร้างกลุ่มตารางและคอลัมน์โดยเรียกใช้คำสั่งต่อไปนี้
echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc echo instance = $INSTANCE_ID >> ~/.cbtrc cbt createtable $TABLE_ID cbt createfamily $TABLE_ID cf
5. นำเข้าข้อมูล
นำเข้าชุดไฟล์ลำดับสำหรับ Codelab นี้จาก gs://cloud-bigtable-public-datasets/bus-data
โดยทำตามขั้นตอนต่อไปนี้
เปิดใช้ Cloud Dataflow API โดยเรียกใช้คำสั่งนี้
gcloud services enable dataflow.googleapis.com
เรียกใช้คำสั่งต่อไปนี้เพื่อนำเข้าตาราง
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/*
ตรวจสอบการนำเข้า
คุณตรวจสอบงานได้ใน Cloud Dataflow UI นอกจากนี้ คุณยังดูโหลดบนอินสแตนซ์ Cloud Bigtable ได้ด้วย UI การตรวจสอบ การนำเข้าทั้งหมดอาจใช้เวลา 5 นาที
6. รับโค้ด
git clone https://github.com/googlecodelabs/cbt-intro-java.git cd cbt-intro-java
เปลี่ยนไปใช้ Java 11 โดยเรียกใช้คำสั่งต่อไปนี้
sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 && export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
7. ทำการค้นหา
คำค้นหาแรกที่คุณจะดำเนินการคือการค้นหาแถวอย่างง่าย คุณจะได้รับข้อมูลของรถประจำทางบนสาย M86-SBS ในวันที่ 1 มิถุนายน 2017 ตั้งแต่เวลา 00:00 น. ถึง 1:00 น. ยานพาหนะที่มีรหัส NYCT_5824
อยู่บนสายรถประจำทางในเวลาดังกล่าว
เมื่อทราบข้อมูลและทราบถึงการออกแบบสคีมา (บริษัทรถประจำทาง/สายรถประจำทาง/การประทับเวลาที่ปัดเศษเป็นชั่วโมง/รหัสยานพาหนะ) คุณจะอนุมานได้ว่าคีย์ประจำแถวมีลักษณะดังนี้
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));
ผลการค้นหาควรระบุตำแหน่งล่าสุดของรถบัสภายในชั่วโมงนั้น แต่คุณต้องการเห็นตำแหน่งทั้งหมด ดังนั้นให้กำหนดจำนวนเวอร์ชันสูงสุดในคำขอรับ
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));
เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อรับรายการละติจูดและลองจิจูดของรถบัสดังกล่าวในช่วง 1 ชั่วโมง
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=lookupVehicleInGivenHour
คุณสามารถคัดลอกและวางละติจูดและลองจิจูดลงในแอป MapMaker เพื่อแสดงภาพผลลัพธ์ได้ เมื่อผ่านไป 2-3 เลเยอร์แล้ว คุณจะได้รับแจ้งให้สร้างบัญชีฟรี คุณสามารถสร้างบัญชีหรือลบเลเยอร์ที่มีอยู่ได้เลย Codelab นี้มีการแสดงข้อมูลผ่านภาพสำหรับแต่ละขั้นตอน หากคุณเพียงแค่ต้องการทำตาม ผลลัพธ์ของคำค้นหาแรกมีดังนี้
8. ดำเนินการสแกน
ทีนี้เรามาดูข้อมูลทั้งหมดของสายรถประจำทางในชั่วโมงนั้นกัน โค้ดสแกนดูค่อนข้างคล้ายกับโค้ด Get เพียงให้ตำแหน่งเริ่มต้นแก่เครื่องสแกน จากนั้นระบุว่าต้องการให้แสดงเฉพาะแถวสำหรับสายรถประจำทาง M86-SBS ภายในชั่วโมงที่มีการประทับเวลา 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);
เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanBusLineInGivenHour
แอป Map Maker สามารถแสดงรายการหลายรายการในครั้งเดียว คุณจึงสามารถดูได้ว่ารถบัสคันไหนเป็นยานพาหนะจากข้อความค้นหาแรกที่คุณวิ่ง
การแก้ไขที่น่าสนใจสำหรับคำค้นหานี้คือการดูข้อมูลทั้งเดือนสำหรับสายรถประจำทาง M86-SBS ซึ่งทำได้ง่ายมาก นําการประทับเวลาออกจากตัวกรองแถวเริ่มต้นและคํานําหน้าเพื่อให้ได้ผลลัพธ์
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);
เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ (จะมีรายการผลลัพธ์จำนวนมาก)
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanEntireBusLine
หากคุณคัดลอกผลลัพธ์ลงใน MapMaker คุณสามารถดูแผนที่ความหนาแน่นของเส้นทางรถประจำทางได้ หยดน้ำสีส้มแสดงถึงจุดหยุด และหยดน้ำสีแดงสดคือจุดเริ่มต้นและจุดสิ้นสุดของเส้นทาง
9. ใช้ตัวกรอง
จากนั้น คุณจะกรองรถประจำทางที่มุ่งหน้าไปทางทิศตะวันออกและรถประจำทางที่มุ่งหน้าไปทางตะวันตก และสร้างแผนที่ความหนาแน่นของแต่ละคันแยกกัน
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);
เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ของรถประจำทางที่ไปทางตะวันออก
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingEast
หากต้องการรถเมล์ไปทางทิศตะวันตก ให้เปลี่ยนสตริงใน valueFilter:
BusQueries.java
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Westside West End AV"));
เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ของรถประจำทางที่ไปทางทิศตะวันตก
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingWest
รถประจำทางมุ่งหน้าไปทางตะวันออก
รถประจำทางกำลังมุ่งหน้าทิศตะวันตก
เมื่อเปรียบเทียบแผนที่ความหนาแน่น 2 แบบ คุณจะเห็นความแตกต่างของเส้นทาง รวมถึงเห็นความแตกต่างของอัตราความเร็ว การตีความข้อมูลอย่างหนึ่งคือระหว่างเส้นทางที่มุ่งหน้าไปทางตะวันตก รถเมล์หยุดวิ่งมากกว่านี้ โดยเฉพาะเมื่อเข้าสู่สวนเซ็นทรัลพาร์ก บนรถประจำทางที่มุ่งหน้าไปทางตะวันออก คุณไม่ค่อยเห็นจุดสตาร์ทรถมากนัก
10. ทำการสแกนหลายช่วง
สำหรับคำค้นหาสุดท้าย คุณจะต้องจัดการกับกรณีของกรณีที่คุณสนใจเกี่ยวกับสายรถเมล์หลายสายในพื้นที่
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);
เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanManhattanBusesInGivenHour
11. ดำเนินการให้เสร็จสิ้น
ล้างข้อมูลเพื่อหลีกเลี่ยงการเรียกเก็บเงิน
คุณควรลบอินสแตนซ์เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud Platform สำหรับทรัพยากรที่ใช้ใน Codelab นี้
gcloud bigtable instances delete $INSTANCE_ID
หัวข้อที่ครอบคลุม
- การออกแบบสคีมา
- การตั้งค่าอินสแตนซ์ ตาราง และครอบครัว
- การนำเข้าไฟล์ลำดับด้วยโฟลว์ข้อมูล
- การค้นหาด้วยการค้นหา การสแกน การสแกนด้วยตัวกรอง และการสแกนแบบหลายช่วง
ขั้นตอนถัดไป
- ดูข้อมูลเพิ่มเติมเกี่ยวกับ Cloud Bigtable ในเอกสารประกอบ
- ลองใช้ฟีเจอร์อื่นๆ ของ Google Cloud Platform ด้วยตัวคุณเอง ดูวิดีโอบทแนะนำ
- ดูวิธีตรวจสอบข้อมูลอนุกรมเวลาด้วยการผสานรวม OpenTSDB