關於 TDengine 3.0 資料訂閱,你需要知道這些

TDengine發表於2023-09-25

小T導讀: 為了幫助應用實時獲取寫入時序資料庫 Time Series Database ) TDengine  的資料,或者以事件到達順序處理資料,TDengine 提供了類似訊息佇列產品的資料訂閱、消費介面。這樣在很多場景下,採用 TDengine 的時序資料處理系統就不需要再整合如 Kafka 一般的訊息佇列產品,從而簡化系統設計的複雜度,降低運維成本。TDengine 3.0 對資料訂閱功能又進行了最佳化升級,本文將詳細介紹其語法規則,方便開發者及企業使用。

與 Kafka 一樣,應用 TDengine 時你也需要定義 topic, 但 TDengine 的 topic 是基於一個已經存在的超級表、子表或普通表的查詢條件,即一個 SELECT 語句。你可以使用 SQL 對標籤、表名、列、表示式等條件進行過濾,以及對資料進行標量函式與 UDF 計算(不包括資料聚合)。與其他訊息佇列軟體相比,這是 TDengine 資料訂閱功能最大的優勢,它提供了更大的靈活性,資料的顆粒度可以由應用隨時調整,而資料的過濾與預處理是交給 TDengine 來完成,有效地減少傳輸的資料量與應用的複雜度。

消費者訂閱 topic 後(一個消費者可以訂閱多個 topic),可以實時獲得最新的資料。多個消費者可以組成一個消費者組 (consumer group),一個消費者組裡的多個消費者共享消費進度,便於多執行緒、分散式地消費資料,提高消費速度;但不同消費者組中的消費者即使消費同一個 topic,也並不共享消費進度。如果訂閱的是超級表,資料可能會分佈在多個不同的 vnode 上,也就是多個 shard 上,這樣一個消費組裡有多個消費者可以提高消費效率。TDengine 的訊息佇列提供了訊息的 ACK 機制,在當機、重啟等複雜環境下也能確保 at least once 消費。

為了實現上述功能,TDengine 會為 WAL (Write-Ahead-Log) 檔案自動建立索引以支援快速隨機訪問,並提供了靈活可配置的檔案切換與保留機制,使用者可以按需指定 WAL 檔案保留的時間以及大小:

  • WAL_RETENTION_PERIOD:為了資料訂閱消費,需要 WAL 日誌檔案額外保留的最大時長策略。WAL 日誌清理,不受訂閱客戶端消費狀態影響。單位為 s,預設為 3600,表示在 WAL 保留最近 3600 秒的資料,使用者可以根據資料訂閱的需要修改這個引數為適當值。
  • WAL_RETENTION_SIZE:為了資料訂閱消費,需要 WAL 日誌檔案額外保留的最大累計大小策略。單位為 KB,預設為 0,表示累計大小無上限。

透過以上方式,我們將 WAL 改造成了一個保留事件到達順序的、可持久化的儲存引擎(但由於   具有遠比 WAL 更高的壓縮率,因此不推薦保留太長時間,一般來說建議不超過幾天)。對於以 topic 形式建立的查詢,TDengine 將對接 WAL 而不是 TSDB 作為其儲存引擎。在消費時,TDengine 根據當前消費進度從 WAL 直接讀取資料,並使用統一的查詢引擎實現過濾、變換等操作,將資料推送給消費者。
為了方便大家上手實操,下文將對 TDengine 資料訂閱相關語法進行詳細解讀。

寫入資料

首先完成建庫、建一張超級表和多張子表操作,然後就可以寫入資料了,比如:

DROP DATABASE IF EXISTS tmqdb;
CREATE DATABASE tmqdb;
CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16) TAGS(t1 INT, t3 VARCHAR(16));
CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0");
CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1");       
INSERT INTO tmqdb.ctb0 VALUES(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00');
INSERT INTO tmqdb.ctb1 VALUES(now, 1, 1, 'a1')(now+1s, 11, 11, 'a11');

建立 topic

TDengine 使用 SQL 建立如下所示 topic(topic 建立個數有上限,透過引數 tmqMaxTopicNum 控制,預設 20 個):

CREATE TOPIC topic_name AS SELECT ts, c1, c2, c3 FROM tmqdb.stb WHEREc1 > 1;

TMQ 支援以下多種訂閱型別:

列訂閱

CREATE TOPIC topic_name as subquery

透過 SELECT 語句訂閱(包括 SELECT *,或 SELECT ts, c1 等指定列訂閱,可以帶條件過濾、標量函式計算,但不支援聚合函式、不支援時間視窗聚合)。但需要注意的是:

  • 該型別 TOPIC 一旦建立則訂閱資料的結構確定;
  • 被訂閱或用於計算的列或標籤不可被刪除(ALTER table DROP)、修改(ALTER table MODIFY);
  • 若發生表結構變更,新增的列不出現在結果中。

超級表訂閱

CREATE TOPIC topic_name AS STABLE stb_name

與 SELECT * from stbName 訂閱的區別是:

  • 不會限制使用者的表結構變更。
  • 返回的是非結構化的資料:返回資料的結構會隨超級表的表結構變化而變化。
  • with meta 引數可選,選擇時將返回建立超級表,子表等語句,主要用於 taosx 做超級表遷移。
  • where_condition 引數可選,選擇時將用來過濾符合條件的子表,訂閱這些子表。where 條件裡不能有普通列,只能是 tag 或 tbname,where 條件裡可以用函式,用來過濾 tag,但是不能是聚合函式,因為子表 tag 值無法做聚合。也可以是常量表示式,比如 2 > 1(訂閱全部子表),或者 false(訂閱 0 個子表)。
  • 返回資料不包含標籤。

資料庫訂閱

CREATE TOPIC topic_name [WITH META] AS DATABASE db_name;

透過該語句可建立一個包含資料庫所有表資料的訂閱,with meta 引數可選,同上。

建立消費者

訂閱 topics

一個 consumer 支援同時訂閱多個 topic。以 Java 為例:

List<String> topics = new ArrayList<>();
topics.add("tmq_topic");
consumer.subscribe(topics);

消費

在 Java 語言下如何對 TMQ 訊息進行消費,程式碼示意如下:

while(running){
  ConsumerRecords<Meters> meters = consumer.poll(Duration.ofMillis(100));
      for (Meters meter : meters) {
            processMsg(meter);
      }    
}

結束消費

消費結束後,應當取消訂閱。

/* 取消訂閱 */
tmq_unsubscribe(tmq);
/* 關閉消費者物件 */
tmq_consumer_close(tmq);

刪除 topic

如果不再需要訂閱資料,可以刪除 topic,需要注意:只有當前未在訂閱中的 topic 才能被刪除。

/* 刪除 topic */
DROP TOPIC topic_name;

狀態檢視

1、topics:查詢已經建立的 topic

SHOW TOPICS;

2、consumers:查詢 consumer 的狀態及其訂閱的 topic

SHOW CONSUMERS;

3、subscriptions:查詢 consumer 與 vgroup 之間的分配關係

SHOW SUBSCRIPTIONS;

寫在最後

受文章篇幅所限,本文只分享了部分語法的具體實現,需要了解相關設定及更多語言的程式碼示例,可以進入 TDengine 官網查詢資料訂閱的相關檔案。對於更為複雜的應用問題,也歡迎大家加入 TDengine 的開發者交流群(新增小T vx:tdengine),直接向社群技術支援人員尋求幫助。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70014783/viewspace-2985801/,如需轉載,請註明出處,否則將追究法律責任。

相關文章