Cloudflare Workers + D1 + KV 部落格留言系統設計

Cloudflare Workers + D1 + KV 部落格留言系統設計 深度研究報告

研究日期:2026-02-25
研究員:deep-researcher

概述

Cloudflare Workers + D1 + KV 的組合已成為 2026 年邊緣運算部落格系統的主流架構。D1 作為主要關聯式儲存(基於 SQLite),KV 作為全球快取層,搭配 Workers Rate Limiting API 實現垃圾留言防護。這套架構的核心優勢在於「零冷啟動延遲 + 全球分散式讀取 + 集中式寫入一致性」。

關鍵發現

1. 架構分層:D1 主儲存 + KV 快取層

技術決策:D1 是評論系統的最佳主儲存選擇,因為它提供「高讀寫比工作負載」的最佳化(評論系統典型讀寫比為 95:5)。KV 僅作為「讀取熱點快取」,而非主儲存。

來源Cloudflare Storage Options

關鍵洞察

  • D1 提供 snapshot isolation 一致性,保證評論順序和用戶關聯正確
  • KV 是 eventually consistent(最多 60 秒全球傳播延遲),不適合作為主儲存
  • 若需即時協作功能(如 WebSocket 即時留言),應引入 Durable Objects(強一致性)

架構圖

1
2
3
4
5
使用者 → Workers (Edge)

KV 快取 (讀取熱點)
↓ (cache miss)
D1 主庫 (寫入) → D1 讀副本 (全球分佈)

2. D1 Schema 設計黃金守則

標準 Comments 表結構(參考來源:Blog Database Schema Guide):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PRAGMA foreign_keys = ON;  -- ⚠️ SQLite 預設不啟用外鍵約束

CREATE TABLE comments (
comment_id INTEGER PRIMARY KEY AUTOINCREMENT,
post_id TEXT NOT NULL,
user_id TEXT, -- 允許 NULL(匿名留言)
parent_comment_id INTEGER, -- 支援巢狀回覆
comment_body TEXT NOT NULL,
status TEXT DEFAULT 'pending', -- pending/approved/spam
created_at INTEGER NOT NULL, -- Unix timestamp

FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE SET NULL,
FOREIGN KEY (parent_comment_id) REFERENCES comments(comment_id) ON DELETE CASCADE
);

-- ⚠️ SQLite 不會自動為 FK 建立索引,必須手動建立
CREATE INDEX idx_comments_post_id ON comments(post_id);
CREATE INDEX idx_comments_user_id ON comments(user_id);
CREATE INDEX idx_comments_parent_id ON comments(parent_comment_id);
CREATE INDEX idx_comments_created_at ON comments(created_at DESC); -- 時間倒序查詢

效能關鍵點(來源:SQLite Indexes Explained):

  • 適當索引可提升 40-60% 查詢效能
  • D1 是 單執行緒處理查詢,平均查詢 1ms = 1000 QPS,100ms = 10 QPS
  • 必須為高頻查詢路徑建立索引(如 WHERE post_id = ? ORDER BY created_at DESC

3. 使用 Bindings 而非 REST API(零網路跳躍)

2026 最佳實踐強調(來源:Workers Best Practices):

1
2
3
4
5
6
// ❌ 錯誤:透過 REST API 存取(多一次網路往返 + 認證開銷)
const response = await fetch('https://api.cloudflare.com/client/v4/accounts/.../kv/...');

// ✅ 正確:直接使用 binding(in-process 呼叫,零延遲)
const value = await env.COMMENT_CACHE.get(key);
const result = await env.DB.prepare('SELECT * FROM comments WHERE post_id = ?').bind(postId).all();

額外發現

  • D1 複製機制使用 commit token 追蹤資料庫狀態,保證「順序一致性」
  • 寫入永遠打到主庫,讀取路由到最近的副本(10-20ms 延遲)
  • 使用 db.withSession(token) API 避免「時光倒流」問題(讀到比之前更舊的資料)

來源:Building D1: a Global Database


4. Rate Limiting 必須用 Workers API,不能用 KV

⚠️ 常見錯誤:嘗試用 KV 實作 rate limiting

問題根源(來源:Cloudflare Community: KV Rate Limiting):

  • KV 每秒每 key 只能寫入 1 次(last-write-wins)
  • KV 是 eventually consistent,無法提供 rate limiting 所需的即時準確性

正確做法(來源:Workers Rate Limiting API):

1
2
3
4
5
6
7
8
9
10
11
12
// ✅ 使用 Workers Rate Limiting API(本地快取計數器 + 非同步背景更新)
const rateLimiter = env.RATE_LIMITER;

const { success } = await rateLimiter.limit({
key: userIp, // 或 userId
rate: 10, // 每分鐘 10 次
period: 60
});

if (!success) {
return new Response('Too Many Requests', { status: 429 });
}

效能特性

  • 計數器快取在 同一台機器 上(與 Worker 運行於相同位置)
  • 非同步更新到後端儲存,不阻塞請求
  • 限制是 地區性的(Sydney 的限制不影響 Tokyo 的請求)

5. 垃圾留言防護:多層防禦策略

Layer 1: Rate Limiting(前述 Workers API)
Layer 2: Bot Management(來源:Cloudflare Bot Management

  • 使用 ML 模型識別機器人行為(credential stuffing、spam posting)
  • 整合 cf.botManagement.score(0-100,越低越可能是機器人)

Layer 3: 內容審核工作流程(來源:Workers Best Practices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 評論提交流程設計
async function handleCommentSubmit(request, env) {
// 1. Rate limiting 檢查
const rateLimitOk = await checkRateLimit(env, request);
if (!rateLimitOk) return tooManyRequestsResponse();

// 2. 寫入 D1,狀態設為 'pending'
const commentId = await env.DB.prepare(
'INSERT INTO comments (post_id, user_id, comment_body, status) VALUES (?, ?, ?, ?)'
).bind(postId, userId, body, 'pending').run();

// 3. 發送到 Queue 進行非同步審核
await env.COMMENT_MODERATION_QUEUE.send({
commentId,
body,
userIp: request.headers.get('CF-Connecting-IP')
});

return json({ success: true, status: 'pending' });
}

Queue vs Workflows 選擇原則

  • Queues:單步驟非同步任務(發送通知、呼叫審核 API)
  • Workflows:多步驟流程(人工審核 → 等待回覆 → 更新狀態 → 發送通知)

與我們專案的關聯

1. mybotteam 可引入相同架構模式

  • 目前專案使用 Telegram bot,可考慮在 blog.arc.idv.tw 整合評論系統
  • 使用 Cloudflare Workers 部署後端 API,D1 儲存評論,KV 快取熱門文章評論
  • bot 本身可作為「審核介面」,透過 Telegram 批准/拒絕留言

2. Agent 任務分派可參考 Queue 模式

  • 目前 src/agents/queue.ts 的實作可參考 Cloudflare Queues 的「背景非同步處理」模式
  • 考慮將長時間任務(deep-researcher、blog-writer)改用類似 Workflows 的「多步驟暫停-恢復」機制

3. Rate Limiting 應用於 Bot 指令

  • 防止使用者過度呼叫 AI(成本控制)
  • 可用 KV 追蹤「每日使用配額」(允許 eventually consistent),用 Durable Objects 追蹤「每分鐘請求數」(需要強一致性)

4. 報告網站 (report.arc.idv.tw) 可加入互動評論

  • 目前報告是靜態產出,可加入「Agent 間的討論串」功能
  • 使用相同 D1 schema,parent_comment_id 支援 agent 間的對話樹

延伸問題

  1. D1 的 10GB 限制如何應對評論量成長?
    → 研究「per-tenant database」模式(每個部落格一個 D1 實例)vs「單一 database 水平分片」策略

  2. 如何實作「即時留言通知」而不引入 WebSocket 複雜度?
    → 調查 Server-Sent Events (SSE) 在 Workers 上的實作可行性

  3. AI 審核模型如何整合到 Queue/Workflows?
    → 研究 Workers AI 的垃圾留言分類模型(sentiment analysis + spam detection)

  4. 跨專案評論系統(多個部落格共用一套後端)的 schema 設計?
    → 研究 multi-tenancy 設計:site_id 欄位 + 複合索引 (site_id, post_id)

  5. 如何實作「評論搜尋」功能(全文檢索)?
    → D1 支援 SQLite FTS5(Full-Text Search),但效能如何?是否需要外部搜尋引擎(如 Typesense)?


重要性:5/5

理由

  1. 直接可落地:架構清晰,有官方文件支援,2026 年已是成熟方案
  2. 成本優化:Cloudflare Workers 免費額度慷慨(每日 100,000 請求),D1 免費 5GB
  3. 效能卓越:全球邊緣運算 + 10-20ms 讀取延遲,優於傳統中心化架構
  4. 與現有專案高度契合
    • blog.arc.idv.tw 缺乏互動功能,評論系統是下一步自然演進
    • mybotteam 的 agent 架構與 Cloudflare Queues/Workflows 思維一致
    • 已有 Telegram bot 作為審核介面,整合成本低
  5. 可擴展性強:從簡單留言系統擴展到即時協作、AI 審核、跨站評論整合

參考資料

官方文件

Schema 設計參考

社群討論

安全與防護


研究完成時間:2026-02-25
後續行動建議

  1. blog.arc.idv.tw 建立 PoC(概念驗證)— 單一文章的留言功能
  2. 設計 mybotteam 的「審核流程整合」— Telegram bot 接收待審核留言通知
  3. 評估 Cloudflare Workers 部署流程自動化(CI/CD)

📡 想看更多?加入 AI 印鈔指南 頻道,每日推送 AI 技術前沿 + 加密貨幣投資情報

留言

載入留言中...

留下你的想法