Skip to main content

Command Palette

Search for a command to run...

Prometheus TSDB 第一次接觸

Updated
7 min read

1. 架構總覽

🏗️ 核心架構流程

🔑 核心概念:Prometheus 使用多層級的儲存架構,用來確保數據的持久性高效查詢儲存空間優化的保證。

2. WAL (Write-Ahead Log)

📝 功能定位

WAL是所有新數據的第一站,類似資料庫的 transaction log,確保數據不會因系統崩潰而遺失。

📁 檔案結構

/data/wal/
         ├── 00000000  # 128MB segment
         ├── 00000001  # 128MB segment
         ├── 00000002  # 活躍寫入
        └── checkpoint.00000001/

⚙️ 特性

特性說明
大小每個 segment 128MB
順序必須連續編號
保留2-3 小時數據
格式二進制

🔄 WAL 工作流程

✅ WAL 的作用

  1. 持久化保證:先寫入磁碟,確保數據安全

  2. 崩潰恢復:重啟時重建 Head Block

  3. 順序寫入:高效的磁碟 I/O


3. Head Block (記憶體區塊)

💾 功能定位

存放在記憶體中的活躍數據,提供最快的查詢速度。

🏗️ 結構組成

📊 關鍵特性

  • 數據範圍:通常 2-3 小時

  • 查詢速度:極快(直接從記憶體)

  • 壓縮算法:XOR + Delta-of-Delta

  • 更新頻率:即時


4. Checkpoint (檢查點)

✅ 功能定位

WAL 的快照,加速 Prometheus 重啟,減少需要重放的 WAL 數量。

📸 Checkpoint 機制

✨ 優點

  • ✅ 重啟更快(不需要重放所有 WAL)

  • ✅ 減少磁碟使用(可刪除舊 WAL)

  • ✅ 每 2 小時自動創建

🔧 工作原理

1.2 小時創建一次 checkpoint
2. Checkpoint 包含 00000000-00000002 的數據
3. 舊的 WAL segments 可以安全刪除
4. 重啟時:
   → 讀取最新 checkpoint
   → 重放之後的 WAL segments

5. Persistent Block (持久化區塊)

💿 功能定位

壓縮後的歷史數據,不可變(immutable),存儲在磁碟上。

📦 Block 結構

/data/01K9TJBMDM5BC097TAG3HETHDZ/  ← Block ULID
├── chunks/
│   └── 000001              # 壓縮的時間序列數據
├── index                   # 倒排索引(快速查詢)
├── meta.json               # 元數據(時間範圍、統計)
└── tombstones              # 刪除標記

🔄 Block 壓縮層級

📊 壓縮層級說明

層級時間範圍來源
Level 02 小時從 Head Block 轉換
Level 14-6 小時合併 2 個 Level 0
Level 212-24 小時合併多個 Level 1
Level 3+24+ 小時長期歷史數據

🎯 Block 特性

  • 不可變:一旦創建就不會修改

  • 時間範圍固定:每個 Block 覆蓋固定時間

  • 高壓縮率:~84% 空間節省

  • 快速查詢:通過 index 加速


6. Chunks (數據塊)

📦 功能定位

實際存儲時間序列樣本的地方,使用高效壓縮算法。

🗜️ 壓縮效率

類型大小說明
原始數據16 bytes/sampletimestamp (8) + value (8)
壓縮後1.3 bytes/sampleXOR + Delta-of-Delta
壓縮率84%節省空間

🔧 壓縮技術

📊 Chunk 組織

一個時間序列:metric{label="value"}

├── Chunk 1 (0-2小時)
│   ├── timestamp: 1763445600
│   ├── value: 42.5
│   ├── timestamp: 1763445615
│   └── value: 43.1
│   
├── Chunk 2 (2-4小時)
└── Chunk 3 (4-6小時)

7. 數據生命週期

🔄 完整流程

① 數據寫入階段

Scrape Target
    ↓
寫入 WAL (磁碟) ← 崩潰恢復保證
    ↓
寫入 Head Block (記憶體) ← 快速查詢
    ↓
定期創建 Checkpoint ← 加速重啟

② 數據壓縮階段(每 2 小時)

Head Block (記憶體)
    ↓
持久化為 Block (磁碟)
    ↓
Chunks 壓縮存儲
    ↓
創建 Index (快速查詢)
    ↓
舊 WAL 可刪除

③ 數據查詢階段

Query
    ↓
├── 查詢 Head Block (最近 2 小時) ← 記憶體,最快
└── 查詢 Persistent Blocks ← 磁碟,較慢
    ├── 讀取 Index (找到相關 Chunks)
    └── 讀取 Chunks (解壓縮數據)

📊 時間軸示意

時間: 0h    2h    4h    6h    8h    10h   12h
      ├─────┼─────┼─────┼─────┼─────┼─────┤
WAL:  [====活躍數據====]
      └────────┘
      轉換為 Block

Head: [====記憶體====]

Blocks:    [B1] [B2] [B3] [B4] [B5] ...
           └──┬──┘   └──┬──┘
              [B6]      [B7]  ← Level 1 壓縮
              └────┬────┘
                  [B8]       ← Level 2 壓縮

8. 問題診斷與解決

❌ 常見錯誤

opening storage failed: get segment range: segments are not sequential

🔍 錯誤原因

WAL segments 的編號不連續:

✗ 錯誤情況:
/data/wal/
├── 00000000
├── 00000001
- ├── 00000003  ← 缺少 00000002!
└── 00000004

✓ 正確情況:
/data/wal/
├── 00000000
├── 00000001
+ ├── 00000002  ← 連續!
└── 00000003

🎯 情況分析

/data/wal/
├── 00000              ⚠️ 不該存在!
├── checkpoint.00587/  ✓ 正常
├── 00588              ✓ 正常
└── 00589              ✓ 正常

診斷結果

  • ⚠️ 00000 是孤立的舊 segment

  • ✅ Checkpoint 機制正常運作

  • ✅ 新的 segments (00588, 00589) 正常

原因

  • Pod 異常重啟時創建了 00000

  • 但舊的 checkpoint 和 segments 還保留著

  • 導致 WAL 結構不一致


🛠️ 解決方案

方案對比

方案影響適用場景操作複雜度
方案 1:刪除異常 segment🟢 最小單一 segment 損壞簡單
方案 2:刪除整個 WAL🟡 中等多個 segment 損壞中等
方案 3:完全重置🔴 最大測試環境/嚴重損壞複雜

✅ 推薦方案:刪除異常 00000

步驟 1:驗證問題

kubectl exec -n kubecost kubecost-prometheus-server-7dd5f595d6-4k8h6 \
  -c prometheus-server -- ls -lh /data/wal/00000

步驟 2:備份(可選)

kubectl exec -n kubecost kubecost-prometheus-server-7dd5f595d6-4k8h6 \
  -c prometheus-server -- cp /data/wal/00000 /tmp/wal_00000_backup

步驟 3:刪除異常檔案

kubectl exec -n kubecost kubecost-prometheus-server-7dd5f595d6-4k8h6 \
  -c prometheus-server -- rm /data/wal/00000

步驟 4:重啟 Pod

kubectl delete pod -n kubecost kubecost-prometheus-server-7dd5f595d6-4k8h6

步驟 5:驗證恢復

# 監控新 Pod 啟動
kubectl get pods -n kubecost -w

# 查看日誌
kubectl logs -n kubecost <new-pod-name> -c prometheus-server -f

# 應該看到:
# ✅ "Server is ready to receive web requests"

步驟 6:檢查 WAL 結構

kubectl exec -n kubecost <new-pod-name> -c prometheus-server -- \
  ls -lh /data/wal/

# 預期結果:
# checkpoint.00587/
# 00588
# 00589
# 00590 (新創建)

🔄 備選方案 2:刪除整個 WAL

如果方案 1 失敗,使用此方案:

# 進入 Pod
kubectl exec -it -n kubecost <pod-name> -c prometheus-server -- sh

# 刪除 WAL 和 chunks_head
rm -rf /data/wal/*
rm -rf /data/chunks_head/*

# 退出並重啟
exit
kubectl delete pod -n kubecost <pod-name>

影響

  • ❌ 丟失最近 2-3 小時數據

  • ✅ 保留所有歷史 Blocks


🔄 備選方案 3:完全重置

僅用於測試環境或嚴重損壞!

# 1. 縮減副本
kubectl scale deployment kubecost-prometheus-server -n kubecost --replicas=0

# 2. 刪除 PVC(會刪除所有數據!)
kubectl delete pvc -n kubecost -l app=prometheus

# 3. 重新啟動
kubectl scale deployment kubecost-prometheus-server -n kubecost --replicas=1

影響

  • 丟失所有歷史數據

  • ✅ 全新乾淨的資料庫


📊 預防措施

1. 監控指標

# WAL segment 數量
prometheus_tsdb_wal_segment_current

# WAL 損壞次數
prometheus_tsdb_wal_corruptions_total

# Checkpoint 失敗次數
prometheus_tsdb_checkpoint_creations_failed_total

# TSDB Head 大小
prometheus_tsdb_head_series

2. 資源配置建議

# Prometheus 配置
resources:
  limits:
    memory: 4Gi        # 足夠的記憶體
    cpu: 2000m
  requests:
    memory: 2Gi
    cpu: 1000m

# 存儲配置
storage:
  tsdb:
    retention.time: 15d
    retention.size: 50GB
    wal-compression: true  # 啟用 WAL 壓縮

3. 定期檢查清單

  • [ ] 每週檢查 WAL 結構

  • [ ] 監控磁碟使用率(> 80% 告警)

  • [ ] 定期使用 promtool 驗證

  • [ ] 檢查 Prometheus 日誌中的錯誤

  • [ ] 監控 Pod 記憶體使用(避免 OOM)

4. 使用 Promtool 驗證

# 檢查 TSDB 健康度
kubectl exec -n kubecost <pod> -c prometheus-server -- \
  promtool tsdb analyze /data

# 檢查 WAL 完整性
kubectl exec -n kubecost <pod> -c prometheus-server -- \
  promtool tsdb check wal /data/wal

# 列出所有 Blocks
kubectl exec -n kubecost <pod> -c prometheus-server -- \
  promtool tsdb list /data

📚 總結

核心概念回顧

數據流向:
Scrape → WAL → Head Block → Checkpoint → Persistent Block → Chunks
         ↓      ↓            ↓            ↓                 ↓
      持久化  快速查詢    加速重啟     長期存儲         高壓縮

關鍵要點

  1. WAL:預寫日誌,確保數據持久性

  2. Head Block:記憶體中的活躍數據

  3. Checkpoint:WAL 快照,加速重啟

  4. Persistent Block:壓縮的歷史數據

  5. Chunks:實際數據存儲,高效壓縮

故障影響範圍

組件損壞影響恢復難度
WAL丟失 2-3 小時數據容易
Head Block丟失 2-3 小時數據容易
Checkpoint重啟較慢容易
Persistent Block丟失該 Block 時間範圍數據困難

🔗 參考資源

118 views

More from this blog

Claude Code 監控秘錄:OpenTelemetry(OTel/OTLP)實戰指南

稟告主公:此乃司馬懿進呈之兵書,詳解如何以 OpenTelemetry 陣法,令臥龍神算之一舉一動盡在掌握,知糧草消耗、察兵器效能、辨戰報異常,使主公運籌帷幄於大帳之中。 為何需要斥候情報? 司馬懿稟告主公: 臥龍神算(Claude Code)乃當世利器,然若無斥候回報,主公便如蒙眼行軍——兵器耗損幾何、糧草消費幾許、哪路斥候出了差錯,一概不知。臣以為,此乃兵家大忌。 無情報之弊,有四: 軍

Feb 19, 202610 min read178
Claude Code 監控秘錄:OpenTelemetry(OTel/OTLP)實戰指南

工程師的 Claude Code 實戰指南:從零開始到高效開發

工程師的 Claude Code 實戰指南:從零開始到高效開發 本文整合 Anthropic 官方 Best Practices 與社群實戰 Tips,帶你由淺入深掌握 Claude Code。 什麼是 Claude Code?為什麼值得學? 如果你還在用「複製程式碼貼到 ChatGPT,再複製答案貼回去」的工作流程,Claude Code 會讓你大開眼界。 Claude Code 是 Anthropic 推出的命令列工具,它直接活在你的 terminal 裡,能夠讀懂你的整個 codeb...

Feb 18, 20265 min read77
工程師的 Claude Code 實戰指南:從零開始到高效開發

System Design Interview Ch 12 Digital Wallet

確立問題與設計範疇 角色對話內容 面試者我們應該只關注兩個數位錢包之間的餘額轉帳操作嗎?我們是否需要擔心其他功能? 面試官讓我們只關注餘額轉帳操作。 面試者該系統需要支援多少 TPS(每秒交易次數)? 面試官讓我們假設是 1,000,000 TPS (每秒 100 萬次交易)。 面試者數位錢包對正確性有嚴格的要求。我們可以假設事務保證 就足夠了嗎? 面試官聽起來不錯。 面試者我們需要證明正確性嗎? 面試官這是一個很好的問題。正確性(Correctness)通常只有在交...

Feb 2, 202610 min read229
System Design Interview Ch 12 Digital Wallet

Claude Code 利用 Event-Driven Hooks 打造自動化開發大腦

在現代 AI 輔助開發中,我們不僅需要 AI 寫程式,更需要它懂規則、記性好,並且能自動處理那些繁瑣的雜事。透過 Claude Code Hooks 機制,我們可以介入 AI 的思考與執行迴圈,實現真正的「人機協作自動化」。 一、 動機與痛點:為什麼你需要介入 AI 的生命週期? 在預設狀態下,Claude Code 雖然強大,但它是「被動」且「無狀態」的,這導致了開發者常遇到以下痛點: 記憶重置 (Session Amnesia): 痛點:每次重啟終端機,AI 就像失憶一樣。 解法:你...

Jan 24, 20266 min read538
Claude Code 利用 Event-Driven Hooks 打造自動化開發大腦
M

MicroFIRE

71 posts