1. مقدمه
در این کد لبه، شما با استفاده از Cloud Bigtable با سرویس گیرنده Java HBase آشنا می شوید.
شما یاد خواهید گرفت که چگونه
- از اشتباهات رایج در طراحی طرحواره اجتناب کنید
- داده ها را در یک فایل دنباله وارد کنید
- داده های خود را پرس و جو کنید
وقتی کارتان تمام شد، چندین نقشه خواهید داشت که داده های اتوبوس شهر نیویورک را نشان می دهد. به عنوان مثال، شما این نقشه حرارتی از سفرهای اتوبوس در منهتن را ایجاد خواهید کرد:
تجربه خود را در استفاده از Google Cloud Platform چگونه ارزیابی می کنید؟
چگونه از این آموزش استفاده خواهید کرد؟
2. درباره مجموعه داده
شما به مجموعه داده ای در مورد اتوبوس های شهر نیویورک نگاه خواهید کرد. بیش از 300 مسیر اتوبوس و 5800 وسیله نقلیه این مسیرها را دنبال می کنند. مجموعه داده ما گزارشی است که شامل نام مقصد، شناسه وسیله نقلیه، طول جغرافیایی، طول جغرافیایی، زمان مورد انتظار رسیدن و زمان رسیدن برنامه ریزی شده است. مجموعه داده از عکس های فوری هر 10 دقیقه برای ژوئن 2017 گرفته شده است.
3. طراحی طرحواره
برای دریافت بهترین عملکرد از Cloud Bigtable، باید هنگام طراحی طرحواره خود متفکر باشید. دادهها در Cloud Bigtable بهطور خودکار از نظر واژگانی مرتب میشوند، بنابراین اگر طرحواره خود را به خوبی طراحی کنید، جستجو برای دادههای مرتبط بسیار کارآمد است. Cloud Bigtable با استفاده از جستجوی نقطه توسط کلید ردیف یا اسکنهای محدوده ردیفی که مجموعهای از ردیفهای پیوسته را برمیگرداند، امکان پرسوجوها را میدهد. با این حال، اگر طرح واره شما به خوبی طراحی نشده باشد، ممکن است متوجه شوید که چندین ردیف جستجو را کنار هم میگذارید، یا بدتر از آن، اسکن جدول کامل را انجام میدهید، که عملیات بسیار کندی هستند.
پرس و جوها را برنامه ریزی کنید
داده های ما دارای اطلاعات متنوعی هستند، اما برای این کد لبه، از مکان و مقصد اتوبوس استفاده خواهید کرد.
با این اطلاعات، میتوانید این پرسشها را انجام دهید:
- مکان یک اتوبوس را در یک ساعت معین بدست آورید.
- برای یک خط اتوبوس یا اتوبوس خاص، داده های یک روز را دریافت کنید.
- تمام اتوبوس های مستطیلی را روی نقشه پیدا کنید.
- مکانهای فعلی همه اتوبوسها را دریافت کنید (اگر این دادهها را در زمان واقعی دریافت میکردید).
این مجموعه پرس و جوها را نمی توان همه با هم به طور بهینه انجام داد. برای مثال، اگر بر اساس زمان مرتبسازی میکنید، نمیتوانید اسکن را بر اساس یک مکان بدون اسکن کامل جدول انجام دهید. شما باید بر اساس پرس و جوهایی که بیشتر اجرا می کنید اولویت بندی کنید.
برای این کد لبه، شما بر روی بهینه سازی و اجرای مجموعه پرس و جوهای زیر تمرکز خواهید کرد:
- مکان یک وسیله نقلیه خاص را بیش از یک ساعت دریافت کنید.
- مکان کل یک خط اتوبوس را در طول یک ساعت دریافت کنید.
- مکان تمام اتوبوس های منهتن را در یک ساعت دریافت کنید.
- جدیدترین مکانهای همه اتوبوسهای منهتن را در یک ساعت دریافت کنید.
- مکان کل یک خط اتوبوس را در طول ماه دریافت کنید.
- مکان های کل یک خط اتوبوس را با یک مقصد مشخص در طول یک ساعت دریافت کنید.
کلید ردیف را طراحی کنید
برای این کد لبه، شما با یک مجموعه داده ایستا کار خواهید کرد، اما یک طرح واره برای مقیاس پذیری طراحی خواهید کرد. شما طرحی طراحی خواهید کرد که به شما امکان می دهد داده های اتوبوس بیشتری را در جدول پخش کنید و همچنان عملکرد خوبی داشته باشید.
در اینجا طرح پیشنهادی برای کلید ردیف است:
[شرکت اتوبوس/خط اتوبوس/مهر زمان گرد شده به ساعت/شناسه خودرو]. هر ردیف دارای یک ساعت داده است و هر سلول چندین نسخه دارای مهر زمانی از داده ها را در خود نگه می دارد.
برای این کد لبه، شما از یک خانواده ستون برای ساده نگه داشتن کارها استفاده خواهید کرد. در اینجا یک نمای نمونه از آنچه که داده ها به نظر می رسد آورده شده است. داده ها بر اساس کلید ردیف مرتب شده اند.
کلید ردیف | cf:VehicleLocation.Latitude | cf:VehicleLocation.Longitude | ... |
MTA/M86-SBS/1496275200000/NYCT_5824 | 40.781212 @20:52:54.00 40.776163 @20:43:19.00 40.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.00 40.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.00 40.779961 @20:43:15.00 40.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 داخلی استفاده کنید، که می توانید با کلیک کردن روی دکمه "فعال کردن پوسته ابری" در گوشه سمت راست بالا، آن را باز کنید.
متغیرهای محیطی زیر را تنظیم کنید تا کپی و چسباندن دستورات Codelab آسانتر شود:
INSTANCE_ID="bus-instance" CLUSTER_ID="bus-cluster" TABLE_ID="bus-data" CLUSTER_NUM_NODES=3 CLUSTER_ZONE="us-central1-c"
Cloud Shell همراه با ابزارهایی است که در این کد لبه استفاده خواهید کرد، ابزار خط فرمان gcloud ، رابط خط فرمان cbt و Maven که قبلاً نصب شدهاند.
با اجرای این دستور، API های Cloud Bigtable را فعال کنید.
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. داده ها را وارد کنید
مجموعه ای از فایل های دنباله ای را برای این کد لبه از 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 نظارت کنید. همچنین، میتوانید بار را در نمونه Cloud Bigtable خود با رابط کاربری نظارتی آن مشاهده کنید. کل واردات باید 5 دقیقه طول بکشد.
6. کد را دریافت کنید
git clone https://github.com/googlecodelabs/cbt-intro-java.git cd cbt-intro-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 از ساعت 12: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، دستور زیر را اجرا کنید تا لیستی از طول و عرض جغرافیایی برای اتوبوس در طول ساعت دریافت کنید:
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=lookupVehicleInGivenHour
برای تجسم نتایج، می توانید طول و عرض جغرافیایی را کپی و در برنامه MapMaker جایگذاری کنید. بعد از چند لایه به شما می گوید که یک حساب کاربری رایگان بسازید. می توانید یک حساب کاربری ایجاد کنید یا فقط لایه های موجود را که دارید حذف کنید. اگر میخواهید آن را دنبال کنید، این نرمافزار برای هر مرحله یک تصویرسازی دارد. در اینجا نتیجه این پرس و جو اول است:
8. یک اسکن انجام دهید
اکنون، بیایید تمام داده های خط اتوبوس را برای آن ساعت مشاهده کنیم. کد اسکن بسیار شبیه به کد دریافت است. شما به اسکنر یک موقعیت شروع می دهید و سپس نشان می دهید که فقط ردیف هایی را برای خط اتوبوس 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
اتوبوس هایی که به سمت شرق حرکت می کنند
اتوبوس ها به سمت غرب حرکت می کنند
با مقایسه دو نقشه حرارتی، می توانید تفاوت مسیرها را مشاهده کنید و همچنین تفاوت در سرعت حرکت را مشاهده کنید. یک تفسیر از داده ها این است که در مسیری که به سمت غرب حرکت می کند، اتوبوس ها بیشتر متوقف می شوند، به خصوص هنگام ورود به پارک مرکزی. و در اتوبوسهایی که به سمت شرق میروند، واقعاً نقاط خفگی زیادی نمیبینید.
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 برای منابع استفاده شده در این کد، باید نمونه خود را حذف کنید.
gcloud bigtable instances delete $INSTANCE_ID
آنچه را پوشش داده ایم
- طراحی طرحواره
- تنظیم یک نمونه، جدول و خانواده
- وارد کردن فایل های دنباله ای با جریان داده
- پرس و جو با جستجو، اسکن، اسکن با فیلتر و اسکن چند دامنه
مراحل بعدی
- درباره Cloud Bigtable در مستندات بیشتر بیاموزید.
- سایر ویژگی های Google Cloud Platform را برای خودتان امتحان کنید. نگاهی به آموزش های ما بیندازید.
- نحوه نظارت بر داده های سری زمانی با ادغام OpenTSDB را بیاموزید