1. 簡介
歡迎來到《Petverse》後端,這是一款多人線上遊戲,玩家可以建立動物虛擬化身、探索世界,以及交易遊戲代幣。
最近,遊戲經濟面臨威脅。有錢的狗狗玩家帳戶中,大筆金額全數轉換成頂級鮪魚股票,我們懷疑有一群「羅賓漢貓」從富有的獵犬身上偷取食物,餵食大量貓咪。
在本程式碼研究室中,您將建構即時詐欺防禦盾牌,以揪出首腦和自動化機器人集團。您將體驗 Spanner 中的作業資料如何與 BigQuery 中的分析資料匯聚,進而透過圖形 (GQL) 和關聯式查詢偵測及調查複雜的詐欺模式。
學習內容
- 使用 BigQuery 持續查詢,在即時串流中偵測異常狀況,並將結果推送至 Spanner。
- 使用 Spanner Graph 追蹤財務關係,調查詐欺集團。
- 使用 Spanner 向量搜尋找出相似的個人資料說明,找出機器人帳戶。
- 使用 BigQuery Graph 分析大量通訊記錄,找出協調圖。
軟硬體需求
- 已啟用計費功能的 Google Cloud 專案。
- 具備 SQL、終端機指令和 Python 的基本知識。
- 您可能需要 GitHub 帳戶 (程式碼代管於 GitHub)。
目標對象:中階開發人員、資料工程師和架構師。
預計總時長:45 到 60 分鐘。
費用預估:本程式碼研究室建立的資源費用應低於 $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 查詢,您必須擁有使用 Enterprise 或 Enterprise Plus 版本的預留空間,並在 Cloud Shell 中建立具有自動調度的 Enterprise Edition 預留空間:
# 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
- 建立連線,連結至 Storage bucket 和 (選用) 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」,然後開啟「New Query (+)」。

將下列 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',