1. 简介
在此 Codelab 中,您将使用 Cloud Bigtable 的监控工具,通过使用 Cloud Dataflow 和 Java HBase 客户端写入和读取数据,来创作各种艺术作品。
您将了解如何
- 使用 Cloud Dataflow 将大量数据加载到 Bigtable 中
- 在提取数据时监控 Bigtable 实例和表
- 使用 Dataflow 作业查询 Bigtable
- 探索 Key Visualizer 工具,该工具可用于根据您的架构设计找出热点
- 使用 Key Visualizer 打造艺术作品
您如何评价自己使用 Cloud Bigtable 的体验?
您打算如何使用本教程?
<ph type="x-smartling-placeholder">2. 创建 Bigtable 数据库
Cloud Bigtable 是 Google 面向大数据领域的 NoSQL 数据库服务。它也是为 Google 搜索、Google Analytics、Google 地图和 Gmail 等众多核心 Google 服务提供支撑的数据库。它非常适合运行大型分析工作负载和构建低延迟应用。查看 Cloud Bigtable 简介 Codelab 以获取深入介绍。
创建项目
首先,创建一个新项目。使用内置的 Cloud Shell(点击“激活 Cloud Shell”即可打开)按钮。
设置以下环境变量,以便更轻松地复制和粘贴 Codelab 命令:
BIGTABLE_PROJECT=$GOOGLE_CLOUD_PROJECT INSTANCE_ID="keyviz-art-instance" CLUSTER_ID="keyviz-art-cluster" TABLE_ID="art" CLUSTER_NUM_NODES=1 CLUSTER_ZONE="us-central1-c" # You can choose a zone closer to you
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
3. 学习:使用 Dataflow 向 Bigtable 写入数据
写作基础知识
向 Cloud Bigtable 写入数据时,您必须提供一个 CloudBigtableTableConfiguration
配置对象。此对象指定了表的项目 ID 和实例 ID,以及表本身的名称:
CloudBigtableTableConfiguration bigtableTableConfig = new CloudBigtableTableConfiguration.Builder() .withProjectId(PROJECT_ID) .withInstanceId(INSTANCE_ID) .withTableId(TABLE_ID) .build();
然后,流水线可以传递 HBase Mutation
对象,其中可能包括 Put 和 Delete。
p.apply(Create.of("hello", "world")) .apply( ParDo.of( new DoFn<String, Mutation>() { @ProcessElement public void processElement(@Element String rowkey, OutputReceiver<Mutation> out) { long timestamp = System.currentTimeMillis(); Put row = new Put(Bytes.toBytes(rowkey)); row.addColumn(...); out.output(row); } })) .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));
LoadData Dataflow 作业
下一页将介绍如何运行 LoadData 作业,但我在这里只介绍流水线的重要部分。
要生成数据,您需要创建一个使用 GenerateSequence 类(类似于 for 循环)的流水线,以写入若干行(包含几兆字节的随机数据)。rowkey 将是填充和反转的序列号,因此 250
会变为 0000000052
。
LoadData.java
String numberFormat = "%0" + maxLength + "d"; p.apply(GenerateSequence.from(0).to(max)) .apply( ParDo.of( new DoFn<Long, Mutation>() { @ProcessElement public void processElement(@Element Long rowkey, OutputReceiver<Mutation> out) { String paddedRowkey = String.format(numberFormat, rowkey); // Reverse the rowkey for more efficient writing String reversedRowkey = new StringBuilder(paddedRowkey).reverse().toString(); Put row = new Put(Bytes.toBytes(reversedRowkey)); // Generate random bytes byte[] b = new byte[(int) rowSize]; new Random().nextBytes(b); long timestamp = System.currentTimeMillis(); row.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("C"), timestamp, b); out.output(row); } })) .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));
4. 将数据生成到 Bigtable 中并监控流入
以下命令将运行一个 Dataflow 作业,该作业向表中生成 40GB 的数据,这足以让 Key Visualizer 激活它:
启用 Cloud Dataflow API
gcloud services enable dataflow.googleapis.com
从 GitHub 获取代码并切换到该目录
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git cd java-docs-samples/bigtable/beam/keyviz-art
生成数据(脚本大约需要 15 分钟)
mvn compile exec:java -Dexec.mainClass=keyviz.LoadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"
监控导入
您可以在 Cloud Dataflow 界面中监控该作业。此外,您还可以通过 Cloud Bigtable 实例的监控界面查看其负载。
在 Dataflow 界面中,您可以看到作业图和各种作业指标,包括已处理的元素、当前 vCPU 和吞吐量。
Bigtable 提供标准监控工具,可用于监控实例级、集群级和表级读写操作、已使用的存储空间、错误率等。除此之外,Bigtable 还具有 Key Visualizer,它会根据行键细分您的使用情况,当至少生成 30GB 的数据后,我们就会使用该行键。
5. 学习:使用 Dataflow 从 Bigtable 读取数据
阅读基础知识
从 Cloud Bigtable 读取数据时,您必须提供一个 CloudBigtableTableScanConfiguration
配置对象。它与 CloudBigtableTableConfiguration
类似,但您可以指定要扫描和读取的行。
Scan scan = new Scan(); scan.setCacheBlocks(false); scan.setFilter(new FirstKeyOnlyFilter()); CloudBigtableScanConfiguration config = new CloudBigtableScanConfiguration.Builder() .withProjectId(options.getBigtableProjectId()) .withInstanceId(options.getBigtableInstanceId()) .withTableId(options.getBigtableTableId()) .withScan(scan) .build();
然后使用它来启动流水线:
p.apply(Read.from(CloudBigtableIO.read(config))) .apply(...
不过,如果您想在流水线中执行读取操作,可以将 CloudBigtableTableConfiguration
传递给扩展 AbstractCloudBigtableTableDoFn
的 doFn
。
p.apply(GenerateSequence.from(0).to(10)) .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));
然后,使用您的配置调用 super()
和 getConnection()
,以获取分布式连接。
public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> { public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) { super(config); } @ProcessElement public void processElement(PipelineOptions po) { Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId())); ResultScanner imageData = table.getScanner(scan); } }
ReadData Dataflow 作业
在此 Codelab 中,您需要每秒从表中读取数据,因此您可以使用生成的序列启动流水线,该序列根据输入的 CSV 文件的时间触发多个读取范围。
要确定在指定时间内扫描哪些行范围,需要完成一些数学运算,但如果您想了解详情,可以点击文件名来查看源代码。
ReadData.java
p.apply(GenerateSequence.from(0).withRate(1, new Duration(1000))) .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));
ReadData.java
public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> { List<List<Float>> imageData = new ArrayList<>(); String[] keys; public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) { super(config); keys = new String[Math.toIntExact(getNumRows(readDataOptions))]; downloadImageData(readDataOptions.getFilePath()); generateRowkeys(getNumRows(readDataOptions)); } @ProcessElement public void processElement(PipelineOptions po) { // Determine which column will be drawn based on runtime of job. long timestampDiff = System.currentTimeMillis() - START_TIME; long minutes = (timestampDiff / 1000) / 60; int timeOffsetIndex = Math.toIntExact(minutes / KEY_VIZ_WINDOW_MINUTES); ReadDataOptions options = po.as(ReadDataOptions.class); long count = 0; List<RowRange> ranges = getRangesForTimeIndex(timeOffsetIndex, getNumRows(options)); if (ranges.size() == 0) { return; } try { // Scan with a filter that will only return the first key from each row. This filter is used // to more efficiently perform row count operations. Filter rangeFilters = new MultiRowRangeFilter(ranges); FilterList firstKeyFilterWithRanges = new FilterList( rangeFilters, new FirstKeyOnlyFilter(), new KeyOnlyFilter()); Scan scan = new Scan() .addFamily(Bytes.toBytes(COLUMN_FAMILY)) .setFilter(firstKeyFilterWithRanges); Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId())); ResultScanner imageData = table.getScanner(scan); } catch (Exception e) { System.out.println("Error reading."); e.printStackTrace(); } } /** * Download the image data as a grid of weights and store them in a 2D array. */ private void downloadImageData(String artUrl) { ... } /** * Generates an array with the rowkeys that were loaded into the specified Bigtable. This is * used to create the correct intervals for scanning equal sections of rowkeys. Since Bigtable * sorts keys lexicographically if we just used standard intervals, each section would have * different sizes. */ private void generateRowkeys(long maxInput) { ... } /** * Get the ranges to scan for the given time index. */ private List<RowRange> getRangesForTimeIndex(@Element Integer timeOffsetIndex, long maxInput) { ... } }
6. 创作精彩作品
现在,您已了解如何将数据加载到 Bigtable 中并使用 Dataflow 从中读取数据,您可以运行最后一个命令了,该命令将在 8 小时内生成《蒙娜丽莎》的图片。
mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"
您可以使用包含现有图片的存储分区。您也可以使用此工具根据您自己的任何图片创建输入文件,然后将其上传到公开的 GCS 存储分区。
文件名根据 gs://keyviz-art/[painting]_[hours]h.txt
生成,示例:gs://keyviz-art/american_gothic_4h.txt
绘制选项:
- american_gothic
- mona_lisa
- pearl_earring
- persistence_of_memory
- starry_night
- sunday_afternoon
- the_scream
小时选项:1、4、8、12、24、48、72、96、120、144
向 allUsers
授予角色 Storage Object Viewer
,以公开您的 GCS 存储分区或文件。
选择图片后,只需在以下命令中更改 --file-path
参数即可:
mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT \ --filePath=gs://keyviz-art/american_gothic_4h.txt"
7. 稍后再查看
完整图像可能需要几个小时才能生效,但在 30 分钟后,您应该就会开始在 Key Visualizer 中看到活动。您可以使用以下参数:缩放、亮度和公制。您可以通过以下方法进行缩放:使用鼠标上的滚轮,或在 Key Visualizer 网格上拖动矩形。
亮度可以更改图片的缩放比例,如果您想深入观察非常热的区域,这会非常有用。
您还可以调整要显示的指标。有 OP、读取字节客户端、写入字节客户端等等。"读取字节客户端"似乎生成了平滑的图片,而“Ops”生成的图片中的线条越多,这在一些图片上看起来会非常棒。
8. 完成
清理相关资源以避免产生费用
为避免系统因此 Codelab 中使用的资源向您的 Google Cloud Platform 账号收取费用,您应删除您的实例。
gcloud bigtable instances delete $INSTANCE_ID
所学内容
- 使用 Dataflow 向 Bigtable 写入数据
- 使用 Dataflow 从 Bigtable 读取数据(在流水线的起点,流水线的中间)
- 使用 Dataflow 监控工具
- 使用 Bigtable 监控工具(包括 Key Visualizer)
后续步骤
- 详细了解 Key Visualizer 图片的创建方式。
- 如需详细了解 Cloud Bigtable,请参阅文档。
- 试用其他 Google Cloud Platform 功能。查阅我们的教程。