1. 简介
欢迎来到 Petverse 的后端,这是一款多人在线游戏,玩家可以在其中创建动物头像、探索世界并交易游戏代币。
最近,游戏经济面临威胁。大量资金正从富有的狗狗玩家的账户中流失,全部转换为优质金枪鱼库存。我们怀疑有一群“罗宾汉猫”,它们从富有的猎犬那里偷东西来喂养猫群。
在此 Codelab 中,您将构建一个实时欺诈防御盾,以捕获主谋及其自动化机器人团伙。您将体验 Spanner 中的运营数据如何与 BigQuery 中的分析数据融合,从而通过图表 (GQL) 和关系型查询检测和调查复杂的欺诈模式。
您将执行的操作
- 使用 BigQuery 持续查询检测实时数据流中的异常,并将其推送到 Spanner。
- 使用 Spanner Graph 追踪财务关系,调查欺诈团伙。
- 使用 Spanner 向量搜索查找相似的个人资料描述,从而识别机器人账号。
- 使用 BigQuery 图分析海量通信日志,揭示协调阴谋。
所需条件
- 启用了结算功能的 Google Cloud 项目。
- 具备 SQL、终端命令和 Python 的基础知识。
- 您可能需要 GitHub 账号(代码托管在 GitHub 上)。
受众群体:中级开发者、数据工程师和架构师。
预计总时长:45 至 60 分钟。
费用估算:本 Codelab 中创建的资源产生的费用应低于 5 美元。
2. 准备工作 / 设置
创建或选择 Google Cloud 项目
您需要一个启用了结算功能的 Google Cloud 项目,才能使用本实验所需的服务。
- 在 Google Cloud 控制台的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何验证是否已启用结算功能。
- 在 Cloud 控制台首页中找到您的项目 ID

启动 Cloud Shell
您将使用 Google Cloud Shell 作为执行环境。Cloud Shell 预安装了 gcloud、git 和其他所需工具。
- 前往 Google Cloud Shell。
- 如果出现提示,请点击授权。
- 在 Cloud Shell 终端中设置环境变量,确保您正在自己的项目中操作:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

启用必要的 API
运行以下命令,为 Spanner、BigQuery 和 Vertex AI 启用 API:
gcloud services enable spanner.googleapis.com \
bigquery.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
bigqueryreservation.googleapis.com
创建 BigQuery 预留和分配
如需运行 GQL 查询,您必须拥有使用企业版或企业 Plus 版的预留,并在 Cloud Shell 中创建具有自动扩缩功能的企业版预留:
# 1. Create a BigQuery Enterprise reservation with 0 baseline slots and 100 max autoscaling slots
bq mk --reservation \
--project_id=${GCP_PROJECT} \
--location=US \
--edition=ENTERPRISE \
--slots=0 \
--autoscale_max_slots=100 \
--ignore_idle_slots=true \
spanner-bigquery-reservation
# 2. Assign your Cloud project to the newly created reservation for query execution
bq mk --reservation_assignment \
--project_id=${GCP_PROJECT} \
--location=US \
--reservation_id=spanner-bigquery-reservation \
--job_type=QUERY \
--assignee_type=PROJECT \
--assignee_id=${GCP_PROJECT}
克隆代码库
克隆包含应用代码和示例架构的代码库:
git clone https://github.com/GoogleCloudPlatform/cloud-spanner-samples.git
cd cloud-spanner-samples/spanner-bq-fraud-defense
3. 预配基础设施
您现在将在 BigQuery 中设置数据仓库,并在 Spanner 中设置运营数据库。
设置 BigQuery 数据集和连接
BigQuery 将分析游戏中的遥测数据流。
在 Google Cloud Shell 的控制台中,继续运行以下命令,确保项目 ID 仍处于设置状态:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
- 创建
game_analyticsBigQuery 数据集:
bq mk -d --location=US game_analytics
- 创建连接以连接到存储分区和(可选)Spanner:
bq mk --connection --location=US --project_id=$PROJECT_ID \
--connection_type=CLOUD_RESOURCE unicorn-connection
- 使用架构文件为
GameplayTelemetry、AccountSignals、Players和ChatLogs表创建架构:
bq query --use_legacy_sql=false < bq_schema.sql
设置 Spanner
Google Cloud Spanner 将处理运营实时交易。在本实验中,我们将使用经济实惠的 100 个处理单元 (PU) 实例。
- 创建 Spanner 实例:
gcloud spanner instances create game-instance \
--config=regional-us-central1 \
--description="Game Instance" \
--processing-units=100 \
--edition=ENTERPRISE
- 创建 Spanner 数据库
game-db:
gcloud spanner databases create game-db --instance=game-instance
- 使用应用表(
Players、Transactions、AccountSignals)和属性图(PlayerNetwork)更新 Spanner 架构:
gcloud spanner databases ddl update game-db --instance=game-instance --ddl-file=spanner_schema.sql
- 为多模态向量搜索创建
AvatarSearchIndex:
gcloud spanner databases ddl update game-db --instance=game-instance \
--ddl="CREATE SEARCH INDEX AvatarSearchIndex ON Players(AvatarDescriptionTokens)"
将数据导入 BigQuery
- 将演示数据导入 BigQuery:
bq load --source_format=AVRO game_analytics.GameplayTelemetry gs://sample-data-and-media/spanner-bq-fraud-heist/GameplayTelemetry
bq load --source_format=AVRO game_analytics.AccountSignals gs://sample-data-and-media/spanner-bq-fraud-heist/AccountSignals
bq load --source_format=AVRO game_analytics.Players gs://sample-data-and-media/spanner-bq-fraud-heist/Players
bq load --source_format=AVRO game_analytics.ChatLogs gs://sample-data-and-media/spanner-bq-fraud-heist/ChatLogs
- 前往 BigQuery 控制台,然后探索
game_analytics数据集中的数据。

将数据导入 Spanner
前往 Spanner 控制台,然后探索 game-db 数据库中的数据。
点击 Spanner Studio,然后打开新查询 (+)。

将以下 INSERT 语句粘贴到查询编辑器中,然后点击运行:
-- Table: Players
INSERT INTO Players (
PlayerId,
Name,
Species,
Clan,
AvatarDescription,
ProfilePictureUrl,
CreatedAt
) VALUES
('dc8cf07a-ac0f-48da-9f64-4f379492b1e7', 'Pixel', 'Cat', 'CatClan', 'A heroic cat wearing a green tunic and a feathered cap', 'gs://sample-data-and-media/pixel_profile_booth.png', '2026-03-02T05:11:28.077335+00:00'),
('e82df4fb-0b6d-44dc-8609-70b41430af38', 'Rocky_1', 'Dog', 'DogClan', 'A robot dog with metal plating', 'gs://sample-data-and-media/wheaten_terrier_102.jpg', '2026-03-02T05:11:28.077374+00:00'),
('ea3afac7-54f0-4f68-8ed5-a5b6bd386c59', 'Whiskers_2', 'Cat', 'CatClan', 'A sneaky black cat hiding in the shadows', 'gs://sample-data-and-media/Bengal_100.jpg', '2026-03-02T05:11:28.077389+00:00'),
('f37d558b-fd0a-404c-a193-bc3a8a2edfba', 'Felix_3', 'Cat', 'CatClan', 'A cyber-punk cat with neon glasses', 'gs://sample-data-and-media/Abyssinian_1.jpg', '2026-03-02T05:11:28.077407+00:00'),
('f3687206-405e-43b6-afb0-8ca73eee5dd1', 'Luna_4', 'Cat', 'CatClan', 'A tabby cat with a red bandana', 'gs://sample-data-and-media/Bengal_100.jpg', '2026-03-02T05:11:28.077419+00:00'),
('82383e2d-d3a2-481d-b0cf-bfe165ed9bfd', 'Luna_5', 'Cat', 'CatClan', 'A fluffy persian cat with a golden collar', 'gs://sample-data-and-media/Abyssinian_114.jpg', '2026-03-02T05:11:28.077429+00:00'),
('755c7aff-e538-4681-9b90-4b870a42ac72', 'Buddy_6', 'Dog', 'DogClan', 'A tough bulldog with a spiked collar', 'gs://sample-data-and-media/yorkshire_terrier_101.jpg', '2026-03-02T05:11:28.077439+00:00'),
('8a034e84-26b3-4198-8ec9-3749b1f60537', 'Charlie_7', 'Dog', 'DogClan', 'A police german shepherd with a badge', 'gs://sample-data-and-media/wheaten_terrier_102.jpg', '2026-03-02T05:11:28.077462+00:00'),
('ca288a07-2bf8-46fa-a121-9bd0d0f44c64', 'Rocky_8', 'Dog', 'DogClan', 'A robot dog with metal plating', 'gs://sample-data-and-media/yorkshire_terrier_101.jpg', '2026-03-02T05:11:28.077474+00:00'),
('7b2881f0-289b-4ea4-9c0e-c1748249b70a', 'Bella_9', 'Dog', 'DogClan', 'A robot dog with metal plating', 'gs://sample-data-and-media/yorkshire_terrier_101.jpg', '2026-03-02T05:11:28.077484+00:00'),
('153f4022-a4ce-404a-8544-25d004fd34ad', 'Simba_10', 'Cat', 'CatClan', 'A tabby cat with a red bandana', 'gs://sample-data-and-media/Bengal_100.jpg', '2026-03-02T05:11:28.077494+00:00'),
('3fb82b8e-75a1-49fd-8691-a9dabb42bc4b', 'Charlie_11', 'Dog', 'DogClan', 'A police german shepherd with a badge', 'gs://sample-data-and-media/staffordshire_bull_terrier_116.jpg', '2026-03-02T05:11:28.077507+00:00'),
('e37b6dcf-7ccb-47d0-8b9d-0da2fa30ad09', 'Felix_12', 'Cat', 'CatClan', 'A cyber-punk cat with neon glasses', 'gs://sample-data-and-media/Bengal_105.jpg', '2026-03-02T05:11:28.077516+00:00'),
('0b395a7b-0673-4348-afd0-7cea9252629f', 'Bella_13', 'Dog', 'DogClan', 'A police german shepherd with a badge', 'gs://sample-data-and-media/yorkshire_terrier_101.jpg', '2026-03-02T05:11:28.077527+00:00'),
('64921a63-bea6-4a5c-9e49-7a817678c94f', 'Charlie_14', 'Dog', 'DogClan', 'A tough bulldog with a spiked collar', 'gs://sample-data-and-media/yorkshire_terrier_101.jpg', '2026-03-02T05:11:28.077537+00:00'),
('0d9040df-34a3-4e54-b660-a85e3c60a6fe', 'Felix_15', 'Cat', 'CatClan', 'A fluffy persian cat with a golden collar', 'gs://sample-data-and-media/Abyssinian_114.jpg', '2026-03-02T05:11:28.077546+00:00'),
('188c23a6-4c3b-4c25-9b40-9ec8ad7712a3', 'Max_16', 'Dog', 'DogClan', 'A fast greyhound wearing a racing vest', 'gs://sample-data-and-media/wheaten_terrier_102.jpg', '2026-03-02T05:11:28.077556+00:00'),
('a2eaefc9-dbff-4704-b908-74518d687e17', 'Rocky_17', 'Dog', 'DogClan', 'A tough bulldog with a spiked collar', 'gs://sample-data-and-media/shiba_inu_105.jpg', '2026-03-02T05:11:28.077565+00:00'),
('b59d9b9a-a169-43c1-832d-7e7d4acfa19c', 'Felix_18', 'Cat', 'CatClan', 'A sneaky black cat hiding in the shadows', 'gs://sample-data-and-media/Abyssinian_1.jpg', '2026-03-02T05:11:28.077581+00:00'),
('7019b91a-d908-4c93-8ed2-d1c60e518630', 'Nala_19', 'Cat', 'CatClan', 'A royal siamese cat wearing a crown', 'gs://sample-data-and-media/Abyssinian_1.jpg', '2026-03-02T05:11:28.077595+00:00'),
('1a972a71-a530-407a-b3f7-1dd9b2532cec', 'Luna_20', 'Cat', 'CatClan', 'A sneaky black cat hiding in the shadows', 'gs://sample-data-and-media/Bengal_105.jpg', '2026-03-02T05:11:28.077604+00:00'),
('3bd0489d-3f43-428d-be2d-0434f0e04ed8', 'Luna_21', 'Cat', 'CatClan', 'A cyber-punk cat with neon glasses', 'gs://sample-data-and-media/Bombay_104.jpg', '2026-03-02T05:11:28.077613+00:00'),
('28d7ab21-7ca7-435b-bdc4-5266a381ef89', 'Whiskers_22', 'Cat', 'CatClan', 'A fluffy persian cat with a golden collar', 'gs://sample-data-and-media/Bombay_104.jpg', '2026-03-02T05:11:28.077623+00:00'),
('87d880d4-c949-40e3-8d76-9307b45d57fe', 'Rocky_23', 'Dog', 'DogClan', 'A robot dog with metal plating', 'gs://sample-data-and-media/wheaten_terrier_102.jpg', '2026-03-02T05:11:28.077632+00:00'),
('b49a4523-83ff-4f59-8fca-54356928a18b', 'Nala_24', 'Cat', 'CatClan', 'A tabby cat with a red bandana', 'gs://sample-data-and-media/Bengal_105.jpg', '2026-03-02T05:11:28.077641+00:00'),
('1e049026-1231-4763-bc50-82cb51950fa2', 'Nala_25', 'Cat', 'CatClan', 'A fluffy persian cat with a golden collar', 'gs://sample-data-and-media/Abyssinian_1.jpg', '2026-03-02T05:11:28.077650+00:00'),
('e83caccd-e81e-454a-bf92-9d9a5a509e25', 'Simba_26',