圖數據庫 Nebula Graph TTL 特性

身處在如今這個大數據時代,咱們處理的數據量需以 TB、PB, 甚至 EB 來計算,怎麼處理龐大的數據集是從事數據庫領域人員的共同問題。解決這個問題的核心在於,數據庫中存儲的數據是否都是有效的、有用的數據,所以如何提升數據中有效數據的利用率、將無效的過時數據清洗掉,便成了數據庫領域的一個熱點話題。在本文中咱們將着重講述如何在數據庫中處理過時數據這一問題。mysql

在數據庫中清洗過時數據的方式多種多樣,好比存儲過程、事件等等。在這裏筆者舉個例子來簡要說明 DBA 常用的存儲過程 + 事件來清理過時數據的過程。sql

存儲過程 + 事件清洗數據

存儲過程(procedure)

存儲過程是由一條或多條 SQL 語句組成的集合,當對數據庫進行一系列的讀寫操做時,存儲過程可將這些複雜的操做封裝成一個代碼塊以便重複使用,大大減小了數據庫開發人員的工做量。一般存儲過程編譯一次,能夠執行屢次,所以也大大的提升了效率。數據庫

存儲過程有如下優勢:安全

  • 簡化操做,將重複性很高的一些操做,封裝到一個存儲過程當中,簡化了對這些 SQL 的調用數據結構

  • 批量處理,SQL + 循環,減小流量,也就是「跑批」app

  • 統一接口,確保數據的安全ide

  • 一次編譯屢次執行,提升了效率。函數

以 MySQL 爲例,假如要刪除數據的表結構以下:性能

mysql> SHOW CREATE TABLE person;
+--------+---------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                    |
+--------+---------------------------------------------------------------------------------------------------------------------------------+
| person | CREATE TABLE `person` (
  `age` int(11) DEFAULT NULL,
  `inserttime` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

建立一個名爲 person 的表,其中 inserttime 字段爲 datetime 類型,咱們用 inserttime 字段存儲數據的生成時間。大數據

建立一個刪除指定表數據的存儲過程,以下:

mysql> delimiter //

mysql> CREATE PROCEDURE del_data(IN `date_inter` int)
    -> BEGIN
    ->   DELETE FROM person WHERE inserttime < date_sub(curdate(), interval date_inter day);
    -> END //

mysql> delimiter ;

建立一個名爲 del_data 的存儲過程,參數 date_inter 指定要刪除的數據距離當前時間的天數。當表 person 的 inserttime 字段值(datetime 類型)加上參數 date_inter 天小於當前時間,則認爲數據過時,將過時的數據刪除。

事件(event)

事件是在相應的時刻調用的過程式數據庫對象。一個事件可調用一次,也可週期性的啓動,它由一個特定的線程來管理,也就是所謂的「事件調度器」。<br />事件和觸發器相似,都是在某些事情發生的時候啓動。當數據庫上啓動一條語句的時候,觸發器就啓動了,而事件是根據調度事件來啓動的。因爲它們彼此類似,因此事件也稱爲臨時性觸發器。事件調度器能夠精確到每秒鐘執行一個任務。

以下建立一個事件,週期性的在某個時刻調用存儲過程,來進行清理數據。

mysql> CREATE EVENT del_event  
    ->     ON SCHEDULE 
    ->     EVERY 1 DAY 
    ->     STARTS '2020-03-20 12:00:00'
    ->     ON COMPLETION PRESERVE ENABLE
    ->     DO CALL del_data(1);

建立一個名爲 del_event 的事件,該事件從 2020-03-20 開始,天天的 12:00:00 執行存儲過程 del_data(1)。

而後執行:

mysql> SET global event_scheduler = 1;

打開事件。這樣事件 del_event 就會在指定的時間自動在後臺執行。經過上述的存儲過程 del_data 和事件 del_event,來達到定時自動刪除過時數據的目的。

TTL(Time To Live) 清洗數據

經過上述存儲過程和事件的組合能夠定時清理數據庫中的過時數據。圖數據庫 Nebula Graph 提供了更加簡單高效的方式--使用 TTL 的方式來自動清洗過時數據

使用 TTL 方式自動清洗過時數據的好處以下:

  1. 簡單方便

  2. 經過數據庫系統內部邏輯進行處理,安全可靠<br />

  3. 數據庫會根據自身的狀態自動判斷是否須要處理,若是須要處理,將在後臺自動進行處理,無需人工干預。

TTL 簡介

TTL,全稱 Time To Live,用來指定數據的生命週期,數據時效到期後這條數據會被自動刪除。在圖數據庫 Nebula Graph 中,咱們實現 TTL 功能,用戶設置好數據的存活時間後,在預約時間內系統會自動從數據庫中刪除過時的點或者邊。

在 TTL 中,過時數據會在下次 compaction 時被刪除,在下次 compaction 以前,query 會過濾掉過時的點和邊。

圖數據庫 Nebula Graph 的 TTL 功能需 ttl_col  和 ttl_duration 兩個字段一塊兒使用,到期閾值是 ttl_col 指定的屬性對應的值加上 ttl_duration  設置的秒數。其中 ttl_col 指定的字段的類型應爲 integer 或 timestamp,ttl_duration 的計量單位爲秒。

TTL 讀過濾

針對 tag / edge,Nebula Graph 在 TTL 中將讀數據過濾邏輯下推到 storage 層進行處理。在 storage 層,首先獲取該 tag / edge 的 TTL 信息,而後依次遍歷每一個頂點或邊,取出 ttl_col 字段值,根據 ttl_duration 的值加上 ttl_col 列字段值,跟當前時間的時間戳進行比較,判斷數據是否過時,過時的數據將被忽略。

TTL compaction

RocksDB 文件組織方式

圖數據庫 Nebula Graph 底層存儲使用的是 RocksDB,RocksDB 在磁盤上的文件是分爲多層的,默認是 7 層,以下圖所示:

SST文件在磁盤上的組織方式

Level 0 層包含的文件,是由內存中的 Memtable flush 到磁盤,生成的 SST 文件,單個文件內部按 key 有序排列,文件之間無序。其它 Level 上的多個文件之間都是按照 key 有序排列,而且文件內也有序,以下圖所示:

非Level 0 層的文件數據劃分

RocksDB compaction 原理

RocksDB 是基於 LSM 實現,但 LSM 並非一個具體的數據結構,而是一種數據結構的概念和設計思想,具體細節參考LSM論文。而 LSM 中最重要部分就是 compaction,因爲數據文件採用 Append only 方式寫入,而對於過時的數據,重複的、已刪除的數據,須要經過 compaction 進行逐步的清理。<br />

RocksDB compaction 邏輯

咱們採用的 RocksDB 的 compaction 策略爲 Level compaction。當數據寫到 RocksDB 時,會先將數據寫入到一個 Memtable 中,當一個 Memtable 寫滿以後,就會變成 Immutable 的 Memtable。RocksDB 在後臺經過一個 flush 線程將這個 Memtable flush 到磁盤,生成一個 Sorted String Table (SST) 文件,放在 Level 0 層。當 Level 0 層的 SST 文件個數超過閾值以後,就會與Level 1 層進行 compaction。一般必須將 Level 0 的全部文件 compaction 到 Level 1 中,由於 Level 0 的文件的 key 是有交疊的。

Level 0 與 Level 1 的 compaction 以下:

Level 0 與 Level 1 的 compaction

其餘 Level 的 compaction 規則同樣,以 Level 1與 Level 2 的 compaction 爲例進行說明,以下所示:

Level 1 與 Level 2 的 compaction

當 Level 0 compaction 完成後,Level 1 的文件總大小或者文件數量可能會超過閾值,觸發 Level 1 與 Level 2 的 compaction。從 Level 1 層至少選擇一個文件 compaction 到 Level 2 的 key 重疊的文件中。compaction 後可能會觸發下一個 Level 的 compaction,以此類推。

若是沒有 compaction,寫入是很是快的,但這樣會形成讀性能下降,一樣也會形成很嚴重的空間放大問題。爲了平衡寫入、讀取、空間三者的關係,RocksDB 會在後臺執行 compaction,將不一樣 Level 的 SST 進行合併。

TTL compaction 原理

除了上述默認的compaction操做外(sst文件合併),RocksDB 還提供了CompactionFilter 功能,可讓用戶自定義個性化的compaction邏輯。Nebula Graph 使用了這個CompactionFilter來定製本文討論的TTL功能。該功能是 RocksDB 在 compaction 過程當中,每讀取一條數據時,都會調用一個定製的Filter 函數。TTL compaction 的實現方法就是在 Filter 函數中實現 TTL 過時數據刪除邏輯,具體以下:

  1. 首先獲取 tag / edge 的 TTL 信息

  2. 而後遍歷每一個頂點或邊數據,取出 ttl_col 列字段值

  3. 根據 ttl_duration 的值加上 ttl_col 列字段值,跟當前時間的時間戳進行比較,而後判斷數據是否過時,過時的數據將被刪除。

TTL 用法

在圖數據庫 Nebula Graph 中,edge 和 tag 實現邏輯一致,在這裏僅以 tag 爲例,來介紹 Nebula Graph 中 TTL 用法。

建立 TTL 屬性

Nebula Graph 中使用 TTL 屬性分爲兩種方式:

create tag 時指定 ttl_duration 來表示數據的持續時間,單位爲秒。ttl_col 指定哪一列做爲 TTL 列。語法以下:

nebula> CREATE TAG t (id int, ts timestamp ) ttl_duration=3600, ttl_col="ts";

當某一條記錄的 ttl_col 列字段值加上 ttl_duration 的值小於當前時間的時間戳,則該條記錄過時,不然該記錄不過時。

  • ttl_duration 的值爲非正數時,則點的此 tag 屬性不會過時

  • ttl_col 只能指定類型爲 int 或者 timestamp 的列名。鄭州哪家不孕不育醫院好:http://www.zztjby.com/

或者 create tag 時沒有指定 TTL 屬性,後續想使用 TTL 功能,可使用 alter tag 來設置 TTL 屬性。語法以下:

nebula> CREATE TAG t (id int, ts timestamp );
nebula> ALTER TAG t ttl_duration=3600, ttl_col="ts";

查看 TTL 屬性

建立完 tag 可使用如下語句查看 tag 的 TTL 屬性:

nebula> SHOW CREATE TAG t;
=====================================
| Tag | Create Tag                  |
=====================================
| t   | CREATE TAG t (
  id int,
  ts timestamp
) ttl_duration = 3600, ttl_col = id |
-------------------------------------

修改 TTL 屬性

可使用 alter tag 語句修改 TTL 的屬性:

nebula> ALTER TAG t ttl_duration=100, ttl_col="id";

刪除 TTL 屬性

當不想使用 TTL 屬性時,能夠刪除 TTL 屬性:

能夠設置 ttl_col 字段爲空,或刪除配置的 ttl_col 字段,或者設置 ttl_duration 爲 0 或者 -1。

nebula> ALTER TAG t1 ttl_col = ""; -- drop ttl attribute

刪除配置的 ttl_col 字段:

nebula> ALTER TAG t1 DROP (a); -- drop ttl_col

設置 ttl_duration 爲 0 或者 -1:

nebula> ALTER TAG t1 ttl_duration = 0; -- keep the ttl but the data never expires

舉例

下面的例子說明,當使用 TTL 功能,而且數據過時後,查詢該 tag 的數據時,過時的數據被忽略。

nebula> CREATE TAG t(id int) ttl_duration=100, ttl_col="id";
nebula> INSERT VERTEX t(id) values 102:(1584441231);

nebula> FETCH prop on t 102;
Execution succeeded (Time spent: 5.945/7.492 ms)

注意:

  1. 當某一列做爲 ttl_col 值的時候,不容許 change 該列。      必須先移除 TTL 屬性,再 change 該列。

  2. 對同一 tag,index 和 TTL 功能不能同時使用。即便 index 和 TTL 建立於不一樣列,也不能夠同時使用。

鄭州哪家醫院治療不孕不育好:http://jbk.39.net/yiyuanfengcai/tsyl_zztjyy/986/

相關文章
相關標籤/搜索