充分獲知資料庫的資料變動是從MongoDB向其他資料服務進行資料同步的關鍵點。與直接查詢collection來獲取資料變動相比,通過流式的方式進行監聽會有效並及時的多。這是一種非常強大的“響應式程式設計”模式。隨著MongoDB的版本更新,流式的獲取方式將變得原來越易用。
讓我們來一同回顧一下。在MongoDB3.6之前,如果我們希望對MongoDB資料庫中的資料變動進行監聽,我們通常是通過 “監聽並回放oplog”(“tail the oplog”)的模式(oplog表將會記錄複製集中的資料變動)。在生產環境中這種方式(“監聽並回放oplog”)通常較為複雜,並且難以保證其穩定與可靠性。
Change Streams and Collections
從MongoDB3.6開始支援的 Change Streams打破了這個僵局。 Change Streams使得資料的變動監聽變得簡單易用。以下是一個示例,該示例演示了通過Node.js對“movieDetails”表的變動監聽。
javascript const MongoClient = require("mongodb").MongoClient; const uri = "MONGODBURL"; const client = new MongoClient(uri, { useNewUrlParser: true }); client.connect().then(db => { const changeStream = client.db("video").collection("movieDetails").watch(); changeStream.on("change", next => { console.log(next); }); });
上述程式碼首先連線進入了資料例項,並通過watch()函式對“video”庫的“movieDetails”表建立了change stream。而後通過.on(“change”,… 建立了一個事件trigger,該事件將監聽該change stream上的所有變動並呼叫對應的後續函式。在上述示例中,監聽到變動後將會將變動事件列印出來。下面是我們在 MongoDB Compass中進行對應修改後的輸出示例:
javascript { _id: { _data: '825C51D03F0000000129295A1004E515B4338C574BA2B9603CB1C7FB3B0446645F696400645C0EC4B74B052F9E2EF0C3810004' }, operationType: 'replace', clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1548865599 }, fullDocument: { _id: 5c0ec4b74b052f9e2ef0c381, title: 'PS I Love You', year: 2007, ... awards: { wins: 2, nominations: 4, text: '2 wins & 4 nominations.' }, type: 'movie' }, ns: { db: 'video', coll: 'movieDetails' }, documentKey: { _id: 5c0ec4b74b052f9e2ef0c381 } }
在上述的返回中可以快速的找到此次change stream的重要資訊,即通過operationType瞭解到變動的型別,有關完整的返回說明請參考 [Change Events documentation]。當監聽某一個collection的時候,operationType的值通常是 insert , update , replace , delete 或 invalidate ,前四種的含義通過名字可以清楚的獲知,上述返回的replace型別是我們通過Compass同collection進行replace操作的反饋。
當我們監聽的collection被drop、改名或者其所屬的db被drop的時候,我們將會看到型別為invalidate的operationType。於此同時這也意味著是時候關閉change stream了。上述返回中剩下的部分是變動的詳細資訊,變動發生在什麼namespace,資料是什麼樣的,何時發生的變更。
以上的示例是在MongoDB4.x版本中生成的,相比3.6版本,4.x版本新增了一個_data欄位。該欄位是一個恢復token(resume token),應用程式能夠在重連後從該點進行繼續監聽。
Beyond Collections
如果你只需要針對某一個collection進行變動監聽,MongoDB3.6就可以滿足你的需求,但是對於那些此前通過oplog來進行變動監聽的同學,他們的訴求往往是希望監聽資料庫中的所有變動,以此來將變動應用到其他系統中。MongoDB4.0很好的滿足了這個訴求,在4.0版本中我們可以針對若干個資料庫或者整個例項(複製集或者sharding)進行變動監聽。與
watch()
某一個collection不同,4.0中我們可以
watch()
某個資料庫或者整個例項。
javascript const MongoClient = require("mongodb").MongoClient; const uri ="MONGODBURL"; undefined const client = new MongoClient(uri, { useNewUrlParser: true }); client.connect().then(db => { const changeStream = client.watch(); changeStream.on("change", next => { console.log(next); });
上述示例將對於任何資料庫、任何表的任何變動進行輸出,這些也不是我們所捕獲的全部資訊。由於我們將監聽範圍放到了最廣,我們也將會看到在刪除collection時候的刪除事件、刪除資料庫的時間以及重新命名collection的事件。
What Next?
我們可以根據實際需要選擇監聽某一個collection的變動、或者某個資料庫中所有collection的變動又或者是整個例項中所有的資料庫與collection的變動。需要注意的是建立新collection、資料庫的變動將不會被直接監聽到,不過我們可以通過變動中的內容間接獲知。
當然,這也不是什麼大問題,如果我們希望監聽資料庫或者collection的建立,我們可以通過變動內容中的collection來判斷是否該表為此前未建立的新表這一方法進行。另外,索引的建立由於不是為表資料變動也不會被監聽捕獲。
MongoDB4.0為我們帶來了一個全新且強大的資料變動監聽方式,尤其是該方式可以實時進行變動捕獲。我們十分建議你去嘗試下這個功能。Change Stream的詳細文件可以參考[Change Streams]。如果你還未安裝MongoDB4.0例項,你也可以在MongoDB Atlas中[註冊]並獲取M0的免費叢集節點進行學習和測試。
譯者:周李洋
Teambition運維總監
MongoDB中文社群組委會成員