ClickHouse + Graphite:如何大幅減少磁碟空間消耗

ClickHouse + Graphite:如何大幅減少磁碟空間消耗

你好,哈布爾。

如果有人利用該系統 石墨網 並遇到儲存效能問題 耳語 (IO、磁碟空間消耗),那麼ClickHouse被替代的幾率應該趨於XNUMX。 此聲明意味著第三方實作已被用作接收指標的守護進程,例如 複寫機碳纖維.

ClickHouse很好地解決了所描述的問題。 例如,從 Whisper 傳輸 2TiB 資料後,它們可容納 300GiB。 我不會詳細討論這種比較;關於這個主題的文章有很多。 此外,直到最近,我們的 ClickHouse 儲存並不是一切都很完美。

空間消耗問題

乍一看,一切都應該運作良好。 下列的 文件,為指標儲存方案建立一個配置(進一步 retention),然後根據為graphite-web選擇的後端的建議建立一個表: 碳點擊屋+石墨點擊屋圖形庫,取決於使用哪個堆疊。 然後……定時炸彈爆炸了。

為了了解哪一個,您需要了解插入是如何運作的以及*系列引擎表中資料的進一步生命路徑合併樹 ClickHouse(圖表取自 介紹 阿列克謝‧札特萊平):

  • 已插入 блок 數據。 在我們的例子中,是到達的指標。
    ClickHouse + Graphite:如何大幅減少磁碟空間消耗
  • 每個這樣的區塊在寫入磁碟之前都會根據鍵進行排序。 ORDER BY建立表時指定。
  • 排序後, кусок (part)資料寫入磁碟。
    ClickHouse + Graphite:如何大幅減少磁碟空間消耗
  • 伺服器在後台監控,這樣這樣的碎片就不會很多,並啟動後台 слияния (merge,以下合併)。
    ClickHouse + Graphite:如何大幅減少磁碟空間消耗
    ClickHouse + Graphite:如何大幅減少磁碟空間消耗
  • 一旦資料停止主動流入伺服器,伺服器就會停止自行執行合併 партицию (partition),但您可以使用以下命令手動啟動該進程 OPTIMIZE.
  • 如果分割區中只剩下一塊,那麼您將無法使用通常的命令運行合併;您必須使用 OPTIMIZE ... FINAL

因此,第一個指標出現了。 它們佔據了一些空間。 隨後的事件可能會因多種因素而有所不同:

  • 分區鍵可以非常小(一天)或非常大(幾個月)。
  • 保留配置可能適合活動分區(其中記錄指標)內的幾個重要資料聚合閾值,也可能不適合。
  • 如果有大量數據,那麼最早的區塊(由於後台合併可能已經很大了(如果您選擇非最佳分區鍵))將不會與新的小塊合併。

而且結局總是一樣的。 ClickHouse 中指標佔用的空間僅在以下情況下增加:

  • 請勿應用 OPTIMIZE ... FINAL 手動或
  • 不要持續將資料插入所有分割區,這樣後台合併遲早會開始

第二種方法似乎是最容易實現的,因此它是不正確的,因此首先嘗試過。
我編寫了一個相當簡單的 python 腳本,該腳本在過去 4 年裡每天發送虛擬指標,並每小時運行一次 cron。
由於ClickHouse DBMS的整個操作是建立在這個系統遲早會完成所有後台工作的基礎上的,但不知道什麼時候,我無法等待舊的大塊開始合併的那一刻新的小。 很明顯,我們需要尋找一種自動執行強制最佳化的方法。

ClickHouse + Graphite:如何大幅減少磁碟空間消耗

ClickHouse系統表中的信息

我們來看表結構 系統零件。 這是有關 ClickHouse 伺服器上所有表格的每個部分的綜合資訊。 除此之外,包含以下列:

  • 資料庫名稱(database);
  • 表名(table);
  • 分區名稱和 ID (partition & partition_id);
  • 當這件作品被創作時(modification_time);
  • 片段中的最小和最大日期(按天進行分區)(min_date & max_date);

還有一張桌子 系統.graphite_retentions,具有以下有趣的領域:

  • 資料庫名稱(Tables.database);
  • 表名(Tables.table);
  • 應應用下一次聚合的指標年齡(age);

所以:

  1. 我們有一個區塊表和一個聚合規則表。
  2. 我們組合它們的交集並得到所有表 *GraphiteMergeTree。
  3. 我們正在尋找其中的所有分區:
    • 多於一件
    • 或者已經到了應用下一個聚合規則的時候了,而且 modification_time 比這一刻更老。

履行

這個請求

SELECT
    concat(p.database, '.', p.table) AS table,
    p.partition_id AS partition_id,
    p.partition AS partition,
    -- Самое "старое" правило, которое может быть применено для
    -- партиции, но не в будущем, см (*)
    max(g.age) AS age,
    -- Количество кусков в партиции
    countDistinct(p.name) AS parts,
    -- За самую старшую метрику в партиции принимается 00:00:00 следующего дня
    toDateTime(max(p.max_date + 1)) AS max_time,
    -- Когда партиция должна быть оптимизированна
    max_time + age AS rollup_time,
    -- Когда самый старый кусок в партиции был обновлён
    min(p.modification_time) AS modified_at
FROM system.parts AS p
INNER JOIN
(
    -- Все правила для всех таблиц *GraphiteMergeTree
    SELECT
        Tables.database AS database,
        Tables.table AS table,
        age
    FROM system.graphite_retentions
    ARRAY JOIN Tables
    GROUP BY
        database,
        table,
        age
) AS g ON
    (p.table = g.table)
    AND (p.database = g.database)
WHERE
    -- Только активные куски
    p.active
    -- (*) И только строки, где правила аггрегации уже должны быть применены
    AND ((toDateTime(p.max_date + 1) + g.age) < now())
GROUP BY
    table,
    partition
HAVING
    -- Только партиции, которые младше момента оптимизации
    (modified_at < rollup_time)
    -- Или с несколькими кусками
    OR (parts > 1)
ORDER BY
    table ASC,
    partition ASC,
    age ASC

傳回每個 *GraphiteMergeTree 表分割區,其合併應釋放磁碟空間。 剩下要做的唯一一件事就是透過一個請求來檢查所有這些 OPTIMIZE ... FINAL。 最終的實現也考慮到不需要接觸活動記錄的分區。

這正是該項目所做的 石墨通道優化器。 Yandex.Market 的前同事在生產中進行了嘗試,工作結果如下所示。

ClickHouse + Graphite:如何大幅減少磁碟空間消耗

如果您在具有 ClickHouse 的伺服器上執行該程序,它將簡單地開始以守護程序模式工作。 每小時執行一次請求,檢查是否出現了超過三天的可以優化的新分區。

我們近期的計劃是至少提供 deb 軟體包,如果可能的話還提供 rpm。

取而代之的是結論

在過去的 9 個多月裡,我一直在我的公司裡 創新遊戲 花了很多時間修補 ClickHouse 和石墨網路的交叉點。 這是一次很好的體驗,導致我們從 Whisper 快速過渡到 ClickHouse 作為指標儲存。 我希望這篇文章是關於我們對該堆疊的各個部分所做的改進以及將來將要做的事情的系列文章的開始。

開發該請求花費了幾公升啤酒和管理時間,以及 v0惡魔,為此我想向他表達我的謝意。 也為了評論這篇文章。

github 上的專案頁面

來源: www.habr.com

添加評論