天天看點

java mongodb ttl_通過mongodb TTL機制讓集合中的資料自動過期删除

MongoDB的集合有衣蛾 TTL (即 time to live,即生存的時間) 的特性。TTL可以讓mongodb自動移除過期了的資料,(咦,這豈不是正好符合日志類的資料訴求)。這種機制便比較适合一些 日志資料 機器産生的事件資料 甚至可以用來做 session會話 。

MongoDB 通過一個 TTL 索引來實作這種所謂的 TTL 集合。該特性的實作機制是: mongod 通過一個背景線程去不斷的讀取集合中某個日期類型的索引,并且移除掉滿足過期條件的文檔documents。

下面我們來看如何實操:

建立 TTL 索引

我們是通過 db.collection.createIndex() 指令配合 expireAfterSeconds 選項來對集合中某個字段做TTL索引。這個字段必須是 date 類型或者是一個包含 date 類型值的數組字段。

建立 TTL 過期規則的話,有 2 種模式:一種是類似于前端的maxAge模式,即設定一個時長,當mongodb發現目前時間與時間索引字段的時差超過了maxAge,則認為過期

另一種是類似前端的 expireTime 模式。即設定一個過期時間點,當mongodb發現目前系統時間已經超過那個時間點,則認為記錄過期

下面我們分别看下兩種模式的設定方式。

在一個特定的時長之後删除文檔

假如我們 db 中有一個 logs 的集合,其中的記錄格式為:{

"_id": "5f43d5c00b34962beb026aad",

"createdAt": Date(),

"requestTime": 1598281152423,

"reportId": "1598281152423-6245975993217447",

}

接下來,我們針對 createdAt 這個字段建立一個 TTL 索引:db.logs.createIndex({ "createdAt": 1 }, {expireAfterSeconds: 3600 })

其中 createdAt: 1 表示對 createdAt 字段建立正序的索引。選項 expireAfterSeconds 表示 3600秒(即1小時) 之後過期。其含義是,在createdAt字段的值的時刻基礎上,再加上 3600秒 之後的那個時間過期。

測試一把。我讓過期時間是 10 秒,做了下測試,以下是測試結果:

java mongodb ttl_通過mongodb TTL機制讓集合中的資料自動過期删除

在一個特定的時間點來删除文檔

有時候,我們不希望在文檔建立時刻之後的多少秒再删除。而是希望在每天淩晨某個時刻(例如避開使用者的通路高峰期) 進行日志删除。是以,我們希望給文檔指定一個特定的過期時間點。這種規則,mongodb也是可以設定的。我們在建立 TTL 索引時,隻需把 expireAfterSeconds 配置的值設為 0 即可.

當然,為了我們的索引字段可以 顧名思義,是以我們重新設計一下資料源(例如我們把這個TTL索引字段取名叫做 expireDeleteTime)。

資料記錄的結構現在如下所示:{

"_id": "5f43d5c00b34962beb026aad",

"expireDeleteTime": ISODate("2020-09-02T11:44:11.528Z"),

"requestTime": 1598281152423,

"reportId": "15982811524236245975993217447",

}

然後,我們建立expireDeleteTime字段的 TTL 索引,方法如下:db.logs.createIndex({ "expireDeleteTime": 1 }, {"expireAfterSeconds": 0})

這樣我們就把 expireDeleteTime 字段配置為 TTL 索引,其 expireAfterSeconds 是 0,是以這意味着mongodb 将用索引字段 【expireDeleteTime 裡的時間值 加 0秒 後的時間】作為判斷依據,此時的判斷依據其實就是 expireDeleteTime 字段本身。

此時,我們向庫中插入一條目前時間的記錄(這意味着該記錄将會馬上過期)。 然後我不斷的查詢集合,看到結果如下:

java mongodb ttl_通過mongodb TTL機制讓集合中的資料自動過期删除

最終,資料記錄被自動删除了。但是實際上我插入的這條資料應該在插入的那一刻就過期了(因為其 expireAfterSeconds時間是此刻),但可以發現 mongodb 并不是立刻删除該資料的,而是在大概 60秒之後才删除,這是因為 mongodb 背景線程的檢測間隔是 60 秒。

第二種過期模式對我們的日志資料來說,是很有價值的。我們可以在每條記錄入庫的時候,就給他添加一個 expireTime 字段,用來标記該記錄的過期時間。例如我們期望保留日志記錄 15 天,則可以借用 moment 類庫這樣做:// 計算出過期時間點

const expireTime = moment().add(15, 'days').endOf('day')

// 将過期時間點和日志資料入庫

db.insert({

expireTime,

...logData

})

MongoDB 将自動删除集合中 expireTime 字段晚于目前時間的記錄。是以,可以實作日志15天後自動删除的效果。

總結MongoDb 可以通過建立 TTL 索引的方式實作過期資料删除

當把索引配置項 expireAfterSeconds 即過期時長設定為 0秒,也就實作了靈活設定文檔的過期時間的目的。