「過期不候」,有生命週期的 TiDB 數據表

近日,由 TiDB 社區主辦,專屬於全球開發者與技術愛好者的頂級挑戰賽事——TiDB Hackathon 2020 比賽圓滿落幕。今年是 TiDB Hackathon 第四次舉辦,參賽隊伍規模創歷屆之最,共有 45 支來自全球各地的隊伍報名,首次實現全球聯動。經過 2 天時間的極限挑戰, 大賽湧現出不少令人激動的項目。

本篇文章的作者爲 T4 隊的孫曉光,他們團隊在本次 Hackathon 比賽中爲 TiDB 的數據表增加了 TTL 能力,讓數據以指定的 TTL 策略自動過期並回收對應的資源,實現了數據價值的實時蒸餾,萃取高價值的新鮮數據。

伴隨着萬物互聯的趨勢,當今各種應用場景的數據體量都在迅速膨脹。不但傳統意義上的大數據分析場景在迅速擴展範圍,在線業務交易系統所承載的數據規模也在迅速向 BigData scale 邁進。用更合理的成本支撐更大規模的業務數據流量是 TiDB 一直在努力解決的問題,更好的匹配 TiDB 成本和所承載數據的價值是擴大 TiDB 應用場景的關鍵因素。數據總價值超越 TiDB 成本越高,TiDB 爲業務創造的價值越大。

數據價值和 TiDB 成本的匹配在從前就有過許多的討論,並且 TiDB 已經在分級存儲方向做了諸多的探索,充分利用更低成本的介質放置性能要求相對寬鬆的冷數據。除了從降低單位數據成本角度出發降低成本之外,我們也可以通過提升數據價值密度的方式獲得數據價值和存儲的優化匹配,將 TiDB 的能力用於存儲最有價值的數據上。

在許多應用場景中數據價值同時間有着非常強的相關性,數據的價值隨着時間的推移會迅速貶值導致存儲收益越來越低。考慮到這種應用場景的普遍性,我們在 TiDB Hackathon 2020 中嘗試爲 TiDB 引入 TTL 表,讓 TiDB 能夠利用時間維度對數據進行自動化的生命週期管理。利用數據自動蒸餾的機制讓 TiDB 的每一份資源投入都應用在高度萃取的高價值新鮮數據上。

技術背景

Time To Live 是大家非常熟悉的能力,廣泛存在於各類緩存和存儲類系統中,如 Redis、RocksDB 和 MyRocks 等等。同這些系統類似,TiDB 中的 TTL 表能夠在無用戶干預的情況下自動管理寫入數據的生命週期,在數據寫入時間超過設定的過期閾值後自動過期並回收佔用的資源。這種自動化的機制不但能夠將用戶從乏味的數據生命週期管理中解放出來,還能夠充分利用系統內部的工作機制優化數據刪除路徑,消耗更少的資源,更快的回收更多的數據。在綜合考慮 TiDB 的運作機制和用戶使用複雜度後,我們爲數據表增加了過期時間和過期顆粒度兩個設置。用戶可以從「行」和「分區」過期兩種顆粒度中進行選擇,如果對數據過期時間精確度要求不高可以選擇按「分區」方式過期,獲得更高的資源回收效率。

TTL 表定義

這兩種 TTL 表的定義非常簡單,只需參考下面的樣例在建表時提供相應的過期時間設置並選擇期望的數據過期顆粒度即可。由於兩種顆粒度背後實現的機制不同,使用 ALTER TABLE 我們只能將一個現有的 TiDB 錶轉化爲「行」顆粒度的 TTL 表,具體原因在後面的實現機制部分再進行介紹。

「行」顆粒度 TTL 表 DDL

CREATE TABLE ttl_table {
    id BIGINT PRIMARY KEY AUTO_RANDOM,
    author VARCHAR(255),
    post VARCHAR(255)
} TTL=’1h’, TTL_GRANULARITY=’ROW’;

「分區」顆粒度 TTL 表 DDL

CREATE TABLE ttl_table {
    id BIGINT PRIMARY KEY AUTO_RANDOM,
    author VARCHAR(255),
    post VARCHAR(255)
} TTL=’1d’, TTL_GRANULARITY=’PARTITION’;

實現方式

「行」顆粒度 TTL 表

當 TTL 表工作與「行」顆粒度模式時,我們可以利用 TiDB 週期驅動 TiKV 進行 MVCC GC 的時機對過期的數據以「行」爲單位進行回收。爲了將過期策略下發到 TiKV 上,我們將所有 TTL 表對應的數據範圍(key range)連同他們的 TTL 設定一起隨 GC 任務下發到 TiKV 中。在 GC 過程中對於存在於 TTL key range 中的數據,能夠根據 MVCC 信息計算得到數據的存活時長,對於那些 MVCC GC 有效但存活時間超過 TTL 閾值的數據可以在 GC 過程中進行刪除回收空間。需要注意的是目前絕大多數 TiDB 表的存儲佈局都是非聚簇的(non-clustered),如果主鍵索引或其它的二級索引同主數據之間刪除進度不一致,則會導致在主數據刪除的情況下索引數據仍然可見導致的回表失敗。爲了解決這個問題我們將 TTL 表拆分成數據和索引兩個範圍(key range),將數據的 TTL 設定爲索引 TTL 加最近兩輪 GC 的時間間隔。通過這種機制我們能夠確保所有的數據比索引多存活至少一個 GC 週期,從而避免數據不一致導致的回表問題。除了利用 GC 時機對過期數據進行刪除之外,Compaction 階段也很適合對已過期的數據進行回收。由於 Hackathon 時間緊張我們僅實現了 GC 回收機制,未來在 TiDB 上處於產品級狀態的 TTL 表一定會採用更加優化的實現。

「分區」顆粒度 TTL 表

對於數據庫來說刪除大量數據是一個從資源消耗角度看非常昂貴的操作,採用週期 GC 或 Compaction 的機制對數據刪除能夠極大的降低資源上的消耗。但大家可能想到爲什麼不能夠利用 TRUNCATE 的機制實現更高效率的數據過期呢?

通過將 TTL 表實現爲一個用戶不可感知的特殊分區表,利用通過滑動窗口切換分區的方式我們能夠將數據以較粗的顆粒度按時間順序放置在多個物理分區中。通過週期輪轉的方式創建新分區並對最老的一個分區進行 TRUNCATE 和刪除操作,處於最老分區的所有過期數據能夠以非常低的代價迅速刪除。對於這種特殊的刪除操作,RocksDB 能夠直接將對應範圍的數據邏輯刪除轉化爲物理文件刪除操作,達成低成本快速回收空間的目標。

在理解了「分區」顆粒度 TTL 表的工作原理之後,大家應該不難理解由於目前 TiDB 並不允許「普通表」同「分區表」以及不同類型的「分區表」之間進行自由的轉換,所以任何現有的 TiDB 表都不能被轉化爲「分區」顆粒度的 TTL 表。

應用場景

爲了讓大家更好的理解 TTL 表的適用範圍,我們結合曾經遇到的一些實際問題對一些開源項目進行了改造讓它們支持以 TiDB 作爲存儲介質,並利用 TTL 表作爲存儲讓存儲在這些系統中的數據在系統無感知的情況下自動維持數據的生命週期。

Apache Kylin

維度報表在大數據場景中被廣泛的應用於各種決策的支撐,具有數據價值高、時效性強的特點。Kylin 以 MOLAP 的方式對原始數據進行預處理,提供快速的數據切片(slicing)、切塊(dicing)、上卷(rollup)和下鑽(drill down)等分析能力。在這樣的應用場景下,維度報表的數據規模同維度數量和基數正相關,在許多場景下數據規模遠超單機數據庫所能支撐的數據上限。隨着時間的推移對歷史報表數據進行靈活決策分析的需求會迅速減少,因此相應數據也會隨着分析需求的減少而迅速貶值。維度報表的數據往往一週甚至更短的時間就不再具備即席(Adhoc)分析價值,需要對大量無價值歷史數據進行簡易高效的清理。利用 TTL 表存儲數據不但能夠自動維護維度報表數據的生命週期,還能夠充分利用 TiDB 索引查詢能力簡化 Kylin 的實現並且能夠通過統一管理報表數據和元數據進一步簡化 Kylin 的管理成本。

Jaeger Tracing

Jaeger Tracing 實現了 OpenTracing 開放標準並且提供了它的下一代標準 OpenTelemetry 的實驗性支持。目前 Jaeger 官方支持的存儲系統包括 Cassandra 和 ElasticSearch,除此之外還提供了 gRPC 插件方便用戶接入自己的存儲系統。我們利用插件機制爲 Jaeger 帶來了 TiDB 存儲後端的支持,在 TTL 表的幫助下不但能夠充分利用底層存儲 TiKV 提供的高吞吐和擴展性,還能夠自動化的管理歷史追蹤數據的生命週期降低系統管理成本

Kubernetes Events 長期存儲

K8s 的 event 對象記錄了集羣中所發生的各種事件,這些事件在分析排查異常現象或者操作審計方面都非常有價值。在 K8s 集羣規模較大且變更頻繁時我們通常會選擇將集羣事件存儲在獨立的 etcd 集羣,但受限於 etcd 存儲空間仍然無法在頻繁部署更新的場景下記錄較長時間內的 K8s 集羣事件。選擇將事件存儲在 TiDB 中不但可以帶來更大的存儲空間存儲更長時間的記錄,還能夠利用 TiDB 的二級索引能力爲存儲的集羣事件帶來靈活且高性能的查詢能力。在 TTL 表的幫助下,存儲在 TiDB 集羣中的歷史事件能夠自動過期回收空間。

MQTT QoS 1 & 2 消息持久化

MQTT 被廣泛應用於移動互聯網和 IoT 場景中各種實時消息的上行和下發場景。考慮到移動設備和 IoT 設備網絡接入質量的波動性,需要將確保投遞的 QoS 1 & 2 的消息持久化存儲來應對客戶端長時間不在線的情況。當持久化存儲系統內置數據過期支持時,能夠很好的適配同時具有可靠投遞和投遞時效性要求的應用場景,例如新聞熱點、AMBER Alert、天氣預報等等。在 Hackathon 中我們嘗試將一個流行的 MQTT Broker 進行改造,爲其引入了 MySQL 存儲後端支持。在 TTL 表的幫助下業務無需對數據的生命週期進行任何管理,數據能夠按照用戶設置的 Retention 週期自動過期刪除。在高手雲集創意無限的 TiDB Hackathon 中,許多項目的創新性和實用性都遠超 TTL 表。雖然 TTL 表沒能獲得獎項,但我們相信它背後試圖解決的問題具有現實的意義和普適性。希望後續繼續投入精力完善 TTL 表的設計和實現,同時也歡迎大家來一起參與 TTL 表的需求和設計RFC(https://github.com/pingcap/tidb/pull/22763) 討論,推動社區對 TTL 功能的認可並最終將它帶到 TiDB 中更好的服務大家。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章