prometheus-PromQL-3

本章重點: 偏移量修改器,offset,@ time時間戳 理論與示例, 看一萬遍不如練一遍

promQL篇章: 表達式,豆包ai,偏移量修改器,指標類型,指標類型,聚合計算函數,持久化查詢

默認情況下,PromQL 的查詢基準為 “當前時間”,但實際運維場景中,我們常需回溯歷史數據 —— 比如排查 1 小時前的磁盤 IO 異常、核對昨天此時的內存使用率,這就需要藉助偏移量修改器(offset modifier) 調整查詢的時間基準。

一、偏移量修改器

偏移量修改器是 PromQL 中用於調整查詢時間基準的語法組件,偏移量修改器通過offset關鍵字指定偏移時長,語法為在“向量選擇器”後追加“offset <時間>”,核心作用是“將查詢的時間基準向前推移指定時長”,支持即時向量和範圍向量兩類場景。

  • 定義與核心作用

    其核心價值在於解決 “歷史數據回溯” 需求:

    • 排查過去某一時刻的異常狀態(如 “1 小時前是否觸發磁盤滿告警”);
    • 對比不同時間點的指標差異(如 “今天此時與昨天此時的 CPU 負載對比”);
    • 分析歷史時間段的趨勢特徵(如 “3 小時前持續 10 分鐘的網絡波動”)。

1.1、語法結構與使用規則

偏移量的語法格式固定,需緊跟 “向量選擇器” 之後,不可插入函數內部或計算表達式中間:

# 通用語法(即時向量)
<即時向量選擇器> offset <時間時長>

# 通用語法(範圍向量)
<範圍向量選擇器> offset <時間時長>
  • 關鍵規則説明

    • 時間時長支持單位s(秒)、m(分)、h(時)、d(天),例如5m(5 分鐘)、2h(2 小時)、1d(1 天);

    • 語法位置固定:必須緊跟向量選擇器(指標 + 標籤匹配器),不可拆分函數與向量選擇器

      # 例如 1 小時前的 CPU 平均使用率(速率)
      rate(node_cpu_seconds_total[5m] offset 1h)  	<-- 語法正常
      rate(node_cpu_seconds_total offset 1h [5m]) 	<-- 語法異常
      
      表達式組件 具體説明
      node_cpu_seconds_total 指標含義:CPU 在不同模式(如 user 用户態、system 系統態、idle 空閒態等)下的累計運行時間(單位:秒)類型:Counter(計數器,單調遞增,重啓時重置)
      [10m] 範圍向量標識,取該指標最近 10 分鐘內的所有原始樣本數據(默認每 15 秒 1 個點,共 40 個數據點)作用:為rate()函數提供計算速率的時間窗口,窗口越大結果越平滑、抗波動能力越強
      offset 1h 偏移量修改器,將整個查詢的時間基準向前推移 1 小時結合[10m]後,實際查詢時段為 “now-1h-10m 到 now-1h”(1 小時前的 10 分鐘),而非當前時間的最近 10 分鐘
      rate()函數 作用:計算 Counter 指標在指定時間窗口內的平均增長率(單位:次 / 秒)此處用途:將 “CPU 累計秒數” 轉換為 “每秒 CPU 使用時間佔比”(即 CPU 使用率),結果為 0~1 的小數(如 0.7 表示 70%)
    • @時間戳的區別offset是 “相對偏移”(基於當前時間向前推移)

      • PromQL 中 time() = 當前時間戳,沒有 now() 函數。

      • @ 後面必須跟純數值時間戳,不能直接寫表達式(需手動計算後填入)。

      • 相對時間偏移(如 1 小時前)優先用 offset,絕對時間點(如昨天 15:00)才需要 @ + 數值時間戳。

        # 示例
        先用  time() - 3600  # time()返回當前時間戳(秒),減3600秒即1小時前 = 1762840407
        # 這樣我們就獲取到 了 1 小時前的 5 分鐘內 CPU 平均使用率
        rate(node_cpu_seconds_total[5m] @ 1762840407)
        
        # 這樣還得計算 不如用
        rate(node_cpu_seconds_total[5m] offset 1h)
        
        # 查10.4.50.130節點、排除空閒態的CPU使用率(1小時前的10分鐘)
        rate(node_cpu_seconds_total{instance="10.4.50.130:9100", mode!="idle"}[10m] @ 1762840407)
        
    • 數據保留期限制:偏移時長不可超過 Prometheus 的配置數據保留期(如數據僅保留 15 天,偏移 16 天將返回空結果)。

    • @ 時間戳與 offset 的場景對比表

      對比維度 @ 時間戳(絕對時間指定) offset <時長>(相對偏移)
      核心邏輯 直接指定 “絕對時間點”(如 @ 1762840961),查詢以該時間點為基準的範圍數據 基於 “當前時間” 向前推移指定時長(如 offset 1h),查詢相對當前的歷史範圍數據
      語法格式 指標{標籤}[範圍] @ 數值時間戳(時間戳必須是純數字,如 @ 1762840961 指標{標籤}[範圍] offset 時長(時長支持 s/m/h/d,如 offset 30m
      時間基準 固定時間點(與當前時間無關,如 “昨天 15:00”) 動態相對時間(隨當前時間變化,如 “當前時間減 1 小時”)
      適用場景 1. 精準查詢 “固定歷史時間點” 的數據(如排查昨天 10:00 的異常)2. 跨天 / 跨時段的固定時間對比(如每天 18:00 的負載對比)3. 已知具體異常發生時間的回溯(如日誌記錄的 17:30 故障) 1. 查詢 “相對於當前時間的歷史時段”(如 1 小時前、30 分鐘前)2. 近期數據回溯(如排查剛才的短暫波動)3. 動態時間對比(如當前與 1 小時前的負載差異)
      優勢 時間點精準,不受當前時間變化影響,適合固定時段分析 語法簡潔,無需計算時間戳,適合相對時間查詢
      劣勢 需要手動計算或獲取數值時間戳,語法較繁瑣 時間基準隨當前時間動態變化,無法固定某一絕對時間點
      示例(CPU 監控) 查詢 “2025-11-11 15:00”(時間戳 1717234800)的 10 分鐘 CPU 使用率:rate(node_cpu_seconds_total[10m] @ 1762840961) 查詢 “1 小時前的 10 分鐘” CPU 使用率:rate(node_cpu_seconds_total[10m] offset 1h)
      兼容性 所有 Prometheus 版本支持,但需注意時間戳格式(必須為數值) 所有 Prometheus 版本支持,語法無特殊限制
      • 總結建議

        • offset:若需求是 “相對於現在的歷史數據”(如 1 小時前、30 分鐘前),優先用 offset,簡單直接。
        • @ 時間戳:若需求是 “固定時間點的歷史數據”(如昨天 10 點、上週三的某個時段),則用 @ + 數值時間戳,精準鎖定。

        日常運維中,offset 因語法簡潔、無需處理時間戳,是更常用的選擇;@ 時間戳多用於需要精確定位歷史事件的場景(如結合日誌時間排查問題)。

1.2、適用對象:即時向量與範圍向量

偏移量修改器支持兩類向量選擇器,核心差異在於 “時間維度的覆蓋範圍”:

  • 即時向量(Instant Vector):僅包含 “單個時間點” 的樣本數據,偏移後查詢 “歷史某一時刻” 的狀態;

  • 範圍向量(Range Vector):包含 “連續時間段” 的所有樣本數據,偏移後查詢 “歷史某一時間段” 的趨勢。

二、示例

  • 即時向量 + 偏移量:查詢歷史單個時間點數據 , 核對歷史某一時刻的指標狀態,快速驗證 “過去是否出現異常”。

    # 1. 內存監控:查詢30分鐘前10.4.50.130節點的空閒內存大小
    node_memory_MemFree_bytes{instance="10.4.50.130:9100"} offset 30m
    
    # 2. CPU監控:查詢2小時前的CPU用户態使用率(通過rate()計算即時速率)
    rate(node_cpu_seconds_total{mode="user", instance="10.4.50.130:9100"}[5m] offset 2h)
    
    # 3. 磁盤監控:查詢6小時前/掛載點的磁盤使用率(已用空間/總空間)
    (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} offset 6h
    
    # 4. 網絡監控:查詢1天前eth0網卡的出站速率(即時值)
    rate(node_network_transmit_bytes_total{device="eth0"}[5m] offset 1d) 
    
    # 5. 計算 3 小時前的 30 分鐘內內存使用率最大值
    max_over_time((node_memory_MemUsed_bytes / node_memory_MemTotal_bytes)[30m] offset 3h)
    
  • 範圍向量 + 偏移量:查詢歷史某個時間段數據 ,核心用途:回溯歷史時段的指標趨勢,分析異常波動的持續特徵(如峯值、平均值)。

    # 1. 磁盤監控:查詢1小時前開始的10分鐘內,sda磁盤的平均IO操作數
    avg_over_time(node_disk_io_now{device="sda"}[10m] offset 1h)
    
    # 2. 子查詢步長 1 分鐘,取 2 小時前 1 小時的平均值
    avg_over_time(rate(node_cpu_seconds_total{mode="user"}[5m])[1h:1m] offset 2h)	
    
    # 3. 內存監控:查詢3小時前開始的30分鐘內,10.4.50.130節點的最大內存使用率
    max_over_time(
      (
        (node_memory_MemTotal_bytes{instance="10.4.50.130:9100"} 
         - node_memory_MemFree_bytes{instance="10.4.50.130:9100"} 
         - node_memory_Buffers_bytes{instance="10.4.50.130:9100"} 
         - node_memory_Cached_bytes{instance="10.4.50.130:9100"}) 
        / node_memory_MemTotal_bytes{instance="10.4.50.130:9100"}
      )[30m:1m]  # 子查詢:取30分鐘數據,步長1m(轉為範圍向量)
      offset 3h  # 偏移到3小時前
    )
    
    # 4. CPU監控:查詢6小時前開始的1小時內,每5分鐘的CPU系統態平均速率
    avg_over_time(rate(node_cpu_seconds_total{mode="system"}[5m])[1h:5m] offset 6h)
    
    # 5. 網絡監控:查詢1天前開始的20分鐘內,eth0網卡的最大入站速率
    max_over_time(rate(node_network_receive_bytes_total{device="eth0"}[5m])[20m] offset 1d)
    
    • avg_over_time(rate(node_cpu_seconds_total{mode="system"}[5m])[1h:5m] offset 6h) 語法的詳細説明

      • 原始指標:獲取 CPU 系統態的累計時間(counter)。

      • 算速率:用 rate([5m]) 將累計值轉為 5 分鐘內的平均每秒增長(消除 counter 單調遞增特性)。

      • 取範圍:用子查詢 [1h:5m] 截取 1 小時內的速率數據(每 5 分鐘一個點),形成範圍向量。

      • 移時間offset 6h 將這 1 小時的數據窗口挪到 6 小時前。

      • 求平均avg_over_time 計算該窗口內的平均速率,得到最終結果。

      • 如圖: 前6小時的每5分鐘一格

        image-20251111170237152.png

  • 進階組合:偏移量 + 多指標運算 ,適用於複雜場景分析,如對比不同時間點的指標差異、計算曆史時段的波動範圍。

    # 1. 對比“現在”和“1小時前”/掛載點的磁盤使用率差異(排查速率變化)
    (
      (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"}
    ) - (
      (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} offset 1h
    )
    
    # 2. 查詢1小時前開始的30分鐘內,內存使用率的波動範圍(最大值-最小值)
    max_over_time(((node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes)[30m:1m] offset 1h) - min_over_time(((node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes)[30m:1m] offset 1h)
    
    子查詢(範圍化)	
    	[...] [30m:1m]	將上述使用率結果轉為 “範圍向量”:
    		  - 30m:取 30 分鐘內的所有數據
    		  - 1m:步長(每 1 分鐘取一個數據點,控制樣本密度)
    時間偏移	
    	offset 1h	將整個 30 分鐘的時間窗口向前偏移 1 小時 → 即查詢 “1 小時前的 30 分鐘” 數據(而非當前時間附近)
    
    # 3. 排查昨天同一時段(1小時窗口)的磁盤讀寫速率峯值(合併讀寫指標)
    max_over_time(rate(node_disk_read_bytes_total{device='sda'}[5m])[10m:1m] offset 1d) or max_over_time(rate(node_disk_written_bytes_total{device='sda'}[5m])[10m:1m] offset 1d)
    
    # 4. 瞬時值對比, 對比 1 小時前與 2 小時前的空閒內存差
    # 指標A offset 偏移量 - 指標B offset 偏移量例:
    node_memory_MemFree_bytes offset 1h - node_memory_MemFree_bytes offset 2h
    

三、總結

  1. 常見錯誤與解決方案

    • 錯誤 1:偏移量位置錯誤(插入函數內部)非法寫法:rate(node_cpu_seconds_total offset 1h [5m])正確寫法:rate(node_cpu_seconds_total[5m] offset 1h)原因:偏移量必須緊跟向量選擇器,不可拆分函數與時間範圍。
    • 錯誤 2:範圍向量運算類型不匹配(舊版本兼容問題)問題:Prometheus 3.5 及以下版本不支持A[10m] - B[10m]直接運算解決方案:使用子查詢(A - B)[10m:1m],先計算單時間點值再組合成範圍向量。
    • 錯誤 3:偏移時長超過數據保留期現象:查詢返回空結果解決方案:通過prometheus_config核對storage.tsdb.retention配置,確保偏移時長≤數據保留期。
  2. 最佳實踐建議

    • 採樣間隔適配:範圍向量 + 偏移量查詢時,子查詢間隔(如[10m:1m]中的1m)建議與指標採集間隔一致,避免數據失真;
    • 標籤嚴格對齊:多指標運算 + 偏移量時,確保所有指標的標籤(如instancemountpoint)一致,避免 PromQL 忽略不匹配樣本;
    • 性能優化:大範圍偏移(如7d)+ 長時間段查詢(如[1h])會增加 Prometheus 計算壓力,建議縮小時間範圍或按需採樣。
  3. 總結

    偏移量修改器是 PromQL 實現 “歷史數據回溯” 的核心工具,其本質是通過調整時間基準,讓查詢突破 “當前時間” 的限制。無論是單個歷史時間點的狀態核對,還是歷史時間段的趨勢分析,偏移量都能與即時向量、範圍向量靈活組合,適配運維排查、趨勢對比、異常覆盤等多樣化需求。

    掌握偏移量的關鍵在於:牢記 “語法位置固定”“向量類型匹配”“數據保留期限制” 三大原則,結合實際監控場景選擇合適的偏移時長與向量類型。