Firestore 與 Bigtable 簡介
對於需要彈性 Schema 或海量吞吐量的應用程式,Google Cloud 提供兩種互補的 NoSQL 選項,PCD 考試常將它們放在一起比較:Firestore 是針對行動裝置、Web 與 IoT 客戶端調校的無伺服器文件資料庫,提供即時同步與離線支援;Cloud Bigtable 則是針對 PB 級營運與分析負載調校的寬欄、稀疏矩陣式服務,能提供低於 10 ms 的延遲。兩者都是 NoSQL,但目標的存取模式天差地遠。Firestore 為小型半結構化文件而生,以 ID 或索引查詢取出,支援強一致性查詢與 ACID 交易。Bigtable 為大量、寫入密集的時序或遙測資料而生,整個效能模型只取決於一把主鍵(Row Key),既沒有次要索引,也沒有 Join 或跨列交易。PCD 考試會根據資料形狀、查詢模式、延遲目標、耐久性與複寫需求要你從中擇一,同時要熟悉建立時就鎖死的設計(模式、Row Key 反模式、Key Visualizer、Autoscaling)等常見干擾項。
Firestore 是無伺服器文件資料庫,使用 Collection 包 Document,提供強一致性查詢、ACID 交易、即時 Listener、離線快取,以及在 Google 邊緣執行的 Security Rules。Cloud Bigtable 則是受管的寬欄稀疏式 NoSQL 服務,使用單一 Row Key、Column Family,並在 PB 級資料上提供毫秒級掃描效能,專為時序、IoT、金融帳本與個人化推薦設計。
Firestore Native 與 Datastore 模式
Firestore 是同一個產品下的兩個 模式:Firestore Native 與 Datastore 模式,模式在資料庫建立時決定,且建立後無法變更。這個不可逆性是最常見的考題陷阱。模式選錯就只能另開一個資料庫並透過 Dataflow 或排程匯出匯入做資料遷移。
Firestore Native 模式
Native 模式是預設且推薦的選擇,幾乎所有新工作負載都適用。它提供即時 Listener(onSnapshot)、Web/iOS/Android SDK 的離線持久化、行動/Web 端 Security Rules、所有查詢都強一致、以及最多橫跨 500 份文件的 ACID 交易。讀寫扇出針對「行動端直連資料庫、不經後端」的場景做了優化。整體吞吐量近乎無上限,但單一文件層級有節流——約每秒 1 次持續寫入——以提供可預測的強一致性。
Datastore 模式
Datastore 模式是原本 App Engine Datastore 的後繼者,沿用舊的 Datastore API,支援 entity group 內極高的寫入吞吐量,適合伺服器端工作負載:不需要行動 SDK、不需要即時 Listener、不需要 Security Rules。從 App Engine 遷移或執行需要高 QPS 與最終一致全域查詢的批次後端時最合適。
兩種模式如何選
只要有行動端、即時 UI、或客戶端 Security Rules 需求,就一定要選 Native 模式。若是 App Engine、Cloud Run、GKE 等以 Service Account 跑的無狀態後端,且從不直接暴露資料庫給終端裝置,Datastore 模式也可以接受。不論選哪個,該資料庫此後就鎖定。
Firestore 模式(Native 或 Datastore)在資料庫建立時決定且不可變。常見 PCD 陷阱是替行動 App 選了 Datastore 模式——失去即時 Listener、離線持久化與客戶端 Security Rules,唯一補救方式是另開新資料庫並做資料遷移。
Firestore 多區域:nam5 與 eur3
建立 Firestore 資料庫時除了模式,還要選 Location,這同樣終身鎖定。Location 有三種:Regional(單一區域如 us-central1)、Multi-region、以及Eventual multi-region。PCD 必須認得的兩個 Multi-region 是 nam5 與 eur3。
nam5(北美)
nam5 是橫跨多個美國區域的北美多區域 Location,資料以 Paxos 同步複寫,提供 99.999% 可用性 SLA,並能在單一區域整個失效時繼續運作、零資料遺失。代價是寫入延遲比 Regional 多幾十毫秒。
eur3(歐洲)
eur3 是 nam5 在歐洲的對應版本,跨多個歐洲區域複寫。題目提到 GDPR、歐盟資料當地化、或服務歐洲使用者且要多區域耐久性時,答案就是 eur3,同樣享有 99.999% SLA。
Regional 與 Multi-region 取捨
Regional Firestore 提供 99.99% SLA、較低寫入延遲、較低成本。Multi-region(nam5、eur3)成本較高,但多了一個 9,並能撐過整個區域失效。Location 與模式一樣建立後不能改,所以「跨區域最高耐久性」這題的 PCD 答案,就是一開始就選 nam5 或 eur3。
Firestore Location(Regional 如 us-central1,或 Multi-region nam5 / eur3)在建立時決定。Multi-region Location 透過跨多個北美(nam5)或歐洲(eur3)區域的同步複寫,提供 99.999% SLA,而 Regional 為 99.99%。
Firestore Security Rules
Firestore Security Rules 是一種 DSL,運行在 Google 邊緣節點上,在每個客戶端讀寫真正打到資料庫之前就先做授權檢查。它讓行動端與 Web 端可以直連 Firestore,不必架 Cloud Run/App Engine 中介層。
撰寫規則
規則用 firebase deploy --only firestore:rules 部署,存放在 firestore.rules 檔。基本結構為 match /collection/{docId} { allow read, write: if <condition>; }。條件可引用 request.auth.uid(Firebase Auth 已驗證的使用者)、request.resource.data(即將寫入的文件狀態)、resource.data(既存狀態),甚至可以用 get() / exists() 去查詢其他文件。
常見模式
最經典的模式是「每個使用者只能存取自己的資料」:allow read, write: if request.auth != null && request.auth.uid == userId;。角色控制可用 get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin'。規則也能驗證欄位型別、用 request.resource.data.keys().hasAll(['title','body']) 強制 Schema、阻擋未授權的欄位變更。
Security Rules 與 IAM 的差別
PCD 常見陷阱是把 Security Rules 與 IAM 搞混。IAM 控制 Service Account 與開發者對 Firestore API 本身的存取;Security Rules 則控制終端裝置透過 SDK 能讀寫什麼。兩者都會被評估,但對行動/Web 存取真正有意義的是 Security Rules。
不要只靠客戶端驗證,也不要保留「30 天內所有讀寫都通過」的測試模式預設。Production 規則必須預設拒絕,並在每條 match 路徑明確檢查 request.auth;PCD 情境常會扣分於正式上線後仍掛著 allow read, write: if true;。
Firestore 與 Realtime Database
Firebase Realtime Database(RTDB)是 Firestore Native 的前身產品,PCD 仍會要你從中選一個。RTDB 把資料存成一棵巨大的 JSON 樹,透過 WebSocket 推送更新,查詢能力較淺,且只能落在單一區域。單一資料庫實例約撐 10 萬個同時連線,對小型、低延遲的 Presence/Chat 工作負載成本很低。
何時選 Firestore
當你需要結構化的 Collection 與 Document(而非單一 JSON 樹)、能對多欄位排序/過濾/分頁的豐富查詢、跨多份文件的 ACID 交易、nam5/eur3 多區域提供的 99.999% SLA,或單實例連線上限以外的成長空間時,選 Firestore。它也是 Google 持續投資的策略性平台。
RTDB 仍勝出的場景
對極低延遲的 Presence 系統——例如多人遊戲狀態、排行榜、輸入中提示——需要在許多連線裝置之間以 sub-100 ms 扇出單一小封包,而且可以接受扁平資料模型時,RTDB 仍然更合適。
Firestore 在行動裝置上的離線能力
離線支援是 Firestore Native 的招牌功能,也是 PCD 常出題的情境。Firestore 的 iOS、Android、Web SDK 會把 App 讀過或訂閱過的文件維護在 本地快取 中。裝置斷網時,讀取會直接從快取回傳,寫入則進入 mutation queue 等待重送。
樂觀本地寫入
App 離線呼叫 db.collection('orders').add({...}) 時,SDK 立刻產生本地 ID、寫入快取、觸發本地 Listener 讓 UI 立即更新,並把這個 mutation 排入佇列。連線恢復後,SDK 按順序重播佇列,並用 last-write-wins 解決衝突。
onSnapshot 即時 Listener
Listener 會觸發兩次——一次來自快取、一次來自伺服器——讓 UI 可以立刻顯示舊資料,待伺服器確認後再刷新。metadata.fromCache 旗標告訴 App 這個 snapshot 是本地的還是權威的。
快取大小與多分頁
預設快取大小在行動裝置為 100 MB、Web 為 40 MB。行動裝置可調到無限(CACHE_SIZE_UNLIMITED)。Web 多分頁持久化要呼叫 enableMultiTabIndexedDbPersistence。
PCD 出現「外勤行動 App、連線時有時無」這類場景時,正解就是 Firestore Native + nam5/eur3 Multi-region + 啟用離線持久化——不會是 Cloud SQL 或 Bigtable。Bigtable 沒有行動 SDK、沒有離線快取。
Bigtable Row Key 設計
Row Key 設計是 Bigtable 最關鍵的單一決策,PCD 會直接考。Bigtable 把資料依 Row Key 以字典序排序,再把連續的 Key 範圍切成 Tablet 分散到各節點上。若 Row Key 在時間或數值上群聚,所有寫入會落在同一個節點,形成 Hotspot。
反模式:單調遞增 Key
時間戳(1715616000000)、自增 ID、或序號做為 Row Key 的開頭就是教科書級反模式。所有新寫入都落在最後一個 Tablet、由單一節點服務,30 個節點的叢集只會跑出單節點的吞吐量。
正確模式
- Field promotion:以高基數識別碼(例如
deviceId)開頭,後面接反轉時間戳:device12345#20260513。 - Salting:在前面加一個 hash 前綴(
hash(deviceId) % 100)讓寫入均勻分散,代價是無法純按時間掃描。 - Reverse timestamp:存
Long.MAX_VALUE - timestamp,這樣最新資料會排在最前面,仍可做時間掃描。 - Composite key:結合租戶 ID 與業務識別——
tenant42#user88#20260513——讓多租戶掃描仍高效。
Row Key 越短越好
Row Key 會出現在每個 Cell 上,50-byte 的 Key 乘上十億列就是 50 GB 額外開銷。盡量用緊湊、定長的編碼。
Bigtable Hotspot 幾乎都是單調遞增 Row Key(時間戳、自增 ID、連續使用者 ID)造成的。修法是 Field promotion(高基數 ID 在前)、Salting(hash 前綴)或反轉時間戳——可在 Key Visualizer 的亮度圖上肉眼確認。
Bigtable Column Family
Bigtable 一列被切成多個 Column Family,這些 Family 在建表時就要宣告。同一個 Family 內可放任意多個 Column Qualifier,完全 Schema-less。Family 的存在有兩個運維理由。
儲存與壓縮局部性
每個 Column Family 在磁碟上分開存放,並共用一份壓縮字典。把會一起讀的欄位放在同一個 Family(例如所有遙測樣本放 t:、所有 Metadata 放 m:),可讓掃描有效率。
各別 Family 的垃圾回收政策
GC 策略——版本數上限(maxversions=5)、最大年齡(maxage=30d),或交集/聯集規則——是 以 Column Family 為單位 設定的。常見做法是同一列上開兩個 Family:raw: 留 7 天高解析資料、agg: 留 1 年聚合。
限制
一張表最多可開 100 個 Column Family,但實務最佳實踐是控制在 10 個以內。Family 名稱要短(會跟著每個 Cell 一起儲存),Family 內的 Column Qualifier 開上千個都還沒問題。
Bigtable Tall 與 Wide Table
Bigtable Schema 有兩種形狀,PCD 情境會給線索指向其中一種。
Tall(時序)表
Tall 表每個事件是新一列,Row Key 編碼「實體 + 時間戳」:deviceId#20260513T120000。讀取是掃描一段 Key 範圍,寫入是純 append,每列 Cell 數少。這是 IoT 遙測、金融行情、廣告曝光紀錄等寫入密集場景的正解,也方便用 max-age GC 自動清掉舊資料。
Wide(實體)表
Wide 表每個實體一列,歷史資料以 Column 或 Cell 版本攤在這一列上。Row Key 是 deviceId,Column 存最近 N 筆樣本或各屬性的歷史。Wide 列受限於 Bigtable 強制的 每列 256 MB 硬上限,所以只在每個實體歷史不大的情境適用。User profile 這類「通常一次抓一個實體、想一次拿到所有屬性」的資料才該用 Wide。
取捨
Tall 表時間範圍掃描效率高;Wide 表抓單一實體更快,但一旦超過 256 MB 就會壞掉。PCD 描述「每個裝置每秒上百萬筆事件、保留 90 天」的場景,答案幾乎一定是 Tall。
Bigtable Key Visualizer
Key Visualizer 是 Bigtable 診斷 Hotspot 的工具,會渲染一張熱圖,Y 軸是 Row Key 範圍、X 軸是時間,亮度代表每秒運算次數(或 CPU per range 等指標)。
解讀熱圖
水平方向的亮線代表某一段 Row Key 範圍承擔了不成比例的流量——典型的單調遞增 Key Hotspot 樣態。垂直方向的亮條代表整個叢集瞬間負載大,通常沒事。斜對角圖樣可能代表掃描在 Keyspace 上慢慢爬。
所需規模
Key Visualizer 至少要 30 GB 資料且要有足夠近期流量才會產生掃描圖。它免費、會在正式規模的表上自動執行;PCD 考題問「如何找 Bigtable Hotspot」時,要答的就是它。
Bigtable 診斷工具名稱:Key Visualizer。需要 30 GB 以上資料、渲染 Row Key × 時間熱圖,水平亮帶就代表 Row Key Hotspot。修法是重新設計 Row Key,典型手法是 Field promotion、Salting 或反轉時間戳。
Bigtable 複寫(Replication)
Bigtable 複寫的做法是在一個 Instance 下加入一或多個 Cluster。每個 Cluster 位於單一 Zone,持有完整資料副本,各自服務流量。複寫為非同步、跨 Cluster 最終一致。
高可用
單 Cluster Instance SLA 為 99.9%。在同一個 region 加第二個 Cluster(多 Cluster 路由,MULTI_CLUSTER_ROUTING_USE_ANY)會把 SLA 提升到 99.99%。在兩個 region 各放 Cluster 可進一步提升可用性並撐過單一 region 失效。複寫也能讓資料貼近讀者——美國 + 歐洲各一個 Cluster,歐洲使用者就能低延遲讀取。
App Profile 與路由
App Profile 決定 Client 怎麼連:Single-cluster routing 把工作負載釘在某一個 Cluster(適合 read-after-write 或 OLTP/批次工作負載隔離),Multi-cluster routing 自動送請求到最近健康 Cluster 並自動故障切換。
一致性注意事項
因為複寫是最終一致,寫到 Cluster A 的資料可能要幾秒(通常 sub-second,負載大時更久)才會出現在 Cluster B。需要跨區域強一致 read-after-write 的場景 Bigtable 不適合——選 Cloud Spanner。
Bigtable Autoscaling
Bigtable 的運算單位是 Node,過去得手動指定數量。Autoscaling(2022 GA)能依 CPU 使用率與儲存使用率自動上下調整節點數。
設定
可調整的參數有:--autoscaling-min-nodes、--autoscaling-max-nodes、--autoscaling-cpu-target(預設 50%,範圍 10–80%)、--autoscaling-storage-target(SSD 通常 2560 GB/節點、HDD 8192 GB/節點)。Autoscaling 約以一分鐘為週期評估,但縮減速度受限——每 10 分鐘最多縮一個節點,避免 Tablet 重新分配抖動。
gcloud bigtable clusters update my-cluster \
--instance=my-instance \
--autoscaling-min-nodes=3 \
--autoscaling-max-nodes=30 \
--autoscaling-cpu-target=60
何時手動勝過 Autoscaling
有明顯且可預測尖峰的工作負載(黑色星期五、開盤)有時更適合用 Cloud Scheduler + Cloud Functions 排程預先擴容,因為 Autoscaling 會比尖峰晚一分鐘才反應。對穩定或自然成長的負載,Autoscaling 配 50–70% CPU 目標就是預設正解。
白話文解釋
類比 1:檔案櫃 vs. 巨型試算表
Firestore 像一個智慧檔案櫃。每個抽屜(Collection)裝著資料夾(Document),每個資料夾可以放不同種類的紙張(Field),門口的圖書館員(Security Rules)會在訪客碰任何資料夾前先檢查識別證。Bigtable 則像一座倉庫,裡面擺著無限長的試算表,每一列形狀都一樣:左邊一個巨大的 Key、右邊任意多個稀疏 Cell。堆高機司機(Tablet Server)一次只能搬一架貨架,所以當大家都要最新一列時,會有一台司機被塞爆而其他人閒置——這就是 Row Key 設計要避免的 Hotspot。
類比 2:瑞士刀 vs. 工業電鑽
Firestore 是瑞士刀:即時同步、離線、交易、查詢、Security Rules——很多事都能做、有幾件做得特別好,最適合行動 App。Bigtable 是 30 馬力的工業電鑽:只做一件事(個位數毫秒延遲下的大量循序讀寫),但這件事的規模 GCP 上沒有其他服務跟得上。修錶不會用電鑽,鑽水泥也不會用瑞士刀。
類比 3:商場樓層指示 vs. 高速公路感測器網路
Firestore 像入口的商場樓層指示:地圖不大、組織清楚、任何人走過去都能查得到、還能在手機離線使用。Bigtable 像高速公路感測器網路:每一輛車觸發一列遙測,一天數十億筆,沒人會單獨讀某一列——只會掃時間範圍計算車流。把感測器資料塞進樓層指示,它會垮;把樓層指示放進感測器網路,你買它的所有好功能會全部消失。
常見問題(FAQs)
Q1:可以把 Firestore 資料庫從 Datastore 模式改成 Native 模式嗎?
A1:不行。模式在建立時鎖定。要切換只能新開一個目標模式的 Firestore 資料庫,用 gcloud firestore export 把來源資料庫匯出到 Cloud Storage Bucket,再用 gcloud firestore import 匯入新資料庫,並把應用程式裡的資料庫 ID 改過去。
Q2:Firestore 的 nam5 與 us-central1 差在哪?
A2:us-central1 是 Regional Location——單一 region、99.99% SLA、寫入延遲較低、成本較低。nam5 是 Multi-region Location,橫跨多個美國 region 做同步複寫、99.999% SLA、能撐過整個 region 失效,代價是寫入延遲較高與成本較高。Location 和模式一樣,建立後不能改。
Q3:怎麼診斷 Bigtable Hotspot?
A3:到 Bigtable Console 打開 Key Visualizer。Row Key 軸上的水平亮帶代表某段 Key 範圍承擔了不成比例的負載——通常就是單調遞增 Row Key。用 Field promotion(高基數 ID 在前)、Salting 或反轉時間戳重新設計 Row Key。Key Visualizer 大約需要 30 GB 資料才會產生掃描。
Q4:Firestore 支援離線讀寫嗎?
A4:支援。iOS、Android、Web SDK 都會維護本地快取(行動端預設 100 MB、Web 預設 40 MB,可調至無限)。離線時讀取直接由快取回應;寫入進入 mutation queue,連線恢復後重播。即時 Listener 會先從快取觸發一次,伺服器連得到時再觸發第二次。
Q5:Bigtable 複寫和 Bigtable Autoscaling 有什麼關係?
A5:兩者各自獨立。複寫是在 Instance 下加入 Cluster(每個 Cluster 在單一 Zone),透過 App Profile 提供更高可用性(多 Cluster 路由 99.99% SLA)與更貼近區域的低延遲讀取。Autoscaling 是針對單一 Cluster 內的 Node 數,依 CPU 目標(預設 50%)與儲存目標自動上下調。實務上會兩者並用——複寫過的 Instance 內,每個 Cluster 都各自掛一個 Autoscaler。
Q6:Bigtable 能像 Firestore 那樣做跨列交易嗎?
A6:不行。Bigtable 僅支援單列原子操作(含 check-and-mutate 與 read-modify-write 計數器),沒有跨列或跨表的交易。GCP 上要做跨列 ACID:關聯式選 Cloud Spanner、文件式選 Firestore Native(單筆交易最多 500 份文件)。
Q7:什麼時候該用 Bigtable 而不是 BigQuery 做分析?
A7:當延遲必須穩定低於 10 ms、寫入每秒數十萬筆、且存取方式是依 Row Key 或 Key 範圍取資料時就用 Bigtable——典型場景是營運儀表板、即時個人化推薦、時序資料服務層。需要 SQL、跨整個資料集做聚合、或臨時分析時則用 BigQuery;BigQuery 依掃描位元組計費,不適合單筆 Point Lookup。實務上常把兩者搭配:Bigtable 服務即時熱資料層,Dataflow 每日把快照匯出到 BigQuery 做長期分析。