Spanner 和 BigQuery:即時詐欺防禦盾

1. 簡介

歡迎來到《Petverse》後端,這是一款多人線上遊戲,玩家可以建立動物虛擬化身、探索世界,以及交易遊戲代幣。

最近,遊戲經濟面臨威脅。有錢的狗狗玩家帳戶中,大筆金額全數轉換成頂級鮪魚股票,我們懷疑有一群「羅賓漢貓」從富有的獵犬身上偷取食物,餵食大量貓咪。

在本程式碼研究室中,您將建構即時詐欺防禦盾牌,以揪出首腦和自動化機器人集團。您將體驗 Spanner 中的作業資料如何與 BigQuery 中的分析資料匯聚,進而透過圖形 (GQL) 和關聯式查詢偵測及調查複雜的詐欺模式。

學習內容

軟硬體需求

  • 已啟用計費功能的 Google Cloud 專案。
  • 具備 SQL、終端機指令和 Python 的基本知識。
  • 您可能需要 GitHub 帳戶 (程式碼代管於 GitHub)。

目標對象:中階開發人員、資料工程師和架構師。

預計總時長:45 到 60 分鐘。

費用預估:本程式碼研究室建立的資源費用應低於 $5 美元。

2. 事前準備 / 設定

建立或選取 Google Cloud 專案

您需要已啟用計費功能的 Google Cloud 專案,才能使用本實驗室所需的服務。

  1. Google Cloud 控制台的專案選取器頁面中,選取或建立 Google Cloud 專案。
  2. 確認 Cloud 專案已啟用計費功能。瞭解如何確認是否已啟用計費功能
  3. Cloud 控制台首頁中找出專案 ID

Cloud 控制台首頁

啟動 Cloud Shell

您將使用 Google Cloud Shell 做為執行環境。Cloud Shell 已預先安裝 gcloudgit 和其他必要工具。

  1. 前往 Google Cloud Shell
  2. 如果出現提示訊息,請點選「授權」
  3. 在 Cloud Shell 終端機中設定環境變數,確保您在專案中作業:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Cloud Shell:使用 gcloud config 設定專案

啟用必要的 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
  1. 建立 game_analytics BigQuery 資料集:
bq mk -d --location=US game_analytics
  1. 建立連線,連結至 Storage bucket 和 (選用) Spanner:
bq mk --connection --location=US --project_id=$PROJECT_ID \
    --connection_type=CLOUD_RESOURCE unicorn-connection
  1. 使用結構定義檔案,為 GameplayTelemetryAccountSignalsPlayersChatLogs 資料表建立結構定義:
bq query --use_legacy_sql=false < bq_schema.sql

設定 Spanner

Google Cloud Spanner 會處理營運即時交易。在本實驗室中,我們將使用經濟實惠的 100 個處理單元 (PU) 執行個體。

  1. 建立 Spanner 執行個體:
gcloud spanner instances create game-instance \
    --config=regional-us-central1 \
    --description="Game Instance" \
    --processing-units=100 \
    --edition=ENTERPRISE
  1. 建立 Spanner 資料庫 game-db
gcloud spanner databases create game-db --instance=game-instance
  1. 使用應用程式資料表 (PlayersTransactionsAccountSignals) 和屬性圖表 (PlayerNetwork) 更新 Spanner 結構定義:
gcloud spanner databases ddl update game-db --instance=game-instance --ddl-file=spanner_schema.sql
  1. 為多模態向量搜尋建立 AvatarSearchIndex
gcloud spanner databases ddl update game-db --instance=game-instance \
    --ddl="CREATE SEARCH INDEX AvatarSearchIndex ON Players(AvatarDescriptionTokens)"

將資料匯入 BigQuery

  1. 將範例資料匯入 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
  1. 前往 BigQuery 控制台,探索 game_analytics 資料集中的資料。

BigQuery 主控台

將資料匯入 Spanner

前往 Spanner 控制台,並探索 game-db 資料庫中的資料。

點選「Spanner Studio」,然後開啟「New Query (+)」

Spanner 控制台

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