Apache IoTDB C# SDK 介紹

張善友 發表於 2023-01-22
IoT C#

    TsFile 是 IoTDB 的底層資料檔案,一種專門為時間序列資料設計的列式檔案格式。IoTDB TsFile資料讀寫主要是下面兩個結構:

    • IoTDB 提供了一個TSRecord工具,TSRecord記錄了一個裝置在一個時間戳下的若干測點資訊。在c# 客戶端裡被抽象成了Row Record
    • IoTDB 提供了一個Tablet工具,Tablet記錄了一個裝置的多個測點的資訊,按照一種表格的形式表示,這些測點具有相同的時間戳序列,因此可以應用在測點具有相同時間戳序列(每個時間戳下各個測點都具有值)的裝置中。

    IoTDB C# SDK  叫做 Apache-IoTDB-Client-CSharp,Github:https://github.com/eedalong/Apache-IoTDB-Client-CSharp ,Nuget 包有兩個:

    Apache.IoTDB和 Apache.IoTDB.Data。 其中 Apache.IoTDB.Data 是對ADO .NET支援,以.NET 讀取資料庫的方式方便不同使用習慣的使用者, C#客戶端也及時更新支援最新的Apache IoTDB的特性,如對齊序列插入、SchemaTemplate操縱介面的 支援、支援插入空值的Tablet結構等。

    最近剛剛釋出了對IoTDB 1.0版本的支援的1.0.0.1預覽版已經發布,歡迎各位試用並提issue~: https://www.nuget.org/packages/Apache.IoTDB/1.0.0.1-alpha


    使用示例


    // 引數定義
    string host = "localhost";
    int port = 6667;
    int pool_size = 2;

    // 初始化session
    var session_pool = new SessionPool(host, port, pool_size);

    // 開啟session
    await session_pool.Open(false);

    // 建立時間序列
    await session_pool.CreateTimeSeries("root.test_group.test_device.ts1", TSDataType.TEXT, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
    await session_pool.CreateTimeSeries("root.test_group.test_device.ts2", TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
    await session_pool.CreateTimeSeries("root.test_group.test_device.ts3", TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);

    // 插入record
    var measures = new List<string>{"ts1", "ts2", "ts3"};
    var values = new List<object> { "test_text", true, (int)123 };
    var timestamp = 1;
    var rowRecord = new RowRecord(timestamp, values, measures);
    await session_pool.InsertRecordAsync("root.test_group.test_device", rowRecord);

    // 插入Tablet
    var timestamp_lst = new List<long>{ timestamp + 1 };
    var value_lst = new List<object> {new() {"iotdb", true, (int) 12}};
    var tablet = new Tablet("root.test_group.test_device", measures, value_lst, timestamp_ls);
    await session_pool.InsertTabletAsync(tablet);

    // 關閉Session
    await session_pool.Close();


    詳細介面資訊可以參考介面文件

    連線池

    C#客戶端暴露的所有介面均為非同步介面。使用C#客戶端從首先建立一個SessionPool開始,建立SessionPool時需要指定伺服器的IP 、Port 以及 SessionPool的大小,SessionPool的大小代表本地與伺服器建立的連線的數目。為了實現併發客戶端請求,客戶端提供了針對原生介面的連線池(SessionPool),由於SessionPool本身為Session的超集,當SessionPoolpool_size引數設定為1時,退化為原來的Session

    客戶端 使用ConcurrentQueue資料結構封裝了一個客戶端佇列,以維護與服務端的多個連線,當呼叫Open()介面時,會在該佇列中建立指定個數的客戶端,同時透過System.Threading.Monitor類實現對佇列的同步訪問。

    當請求發生時,會嘗試從連線池中尋找一個空閒的客戶端連線,如果沒有空閒連線,那麼程式將需要等待直到有空閒連線

    當一個連線被用完後,他會自動返回池中等待下次被使用

    在使用連線池後,客戶端的併發效能提升明顯,這篇文件展示了使用執行緒池比起單執行緒所帶來的效能提升

    ByteBuffer

    在傳入RPC介面引數時,需要對Record和Tablet兩種資料結構進行序列化,我們主要透過封裝的ByteBuffer類實現

    在封裝位元組序列的基礎上,我們進行了記憶體預申請與記憶體倍增的最佳化,減少了序列化過程中記憶體的申請和釋放,在一個擁有20000行的Tablet上進行序列化測試時,速度比起原生的陣列動態增長具有35倍的效能加速,詳見以下兩篇文件:

    在庫裡 有一個 IoTDB C#客⼾端效能分析報告:https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/time_profile_zh.pdf ,建議大家看一看,這裡只說結論:

    • 在插⼊與該⽤⼾類似的結構化較強、沒有空值、規整、每⾏的column固定的的資料時,建議使⽤insert_tablet接⼝,經過改善後的insert_tablet接⼝具備較好的效能,能滿⾜該⽤⼾的需求
    • 資料量較⼤,但資料整體不規整或者有空值,每⾏資料的column數不定時建議使⽤insert_records接⼝,該接⼝對record資料的插⼊速度較為可觀
    • 資料量⼩,需要對原有資料做出⼀定的修正 時,使⽤insert_record接⼝

     

    參考文章: