23 Change Stream
一,什麼是Change Stream
Change Stream 是MongoDB 用於實現變更追蹤的解決方案,類似於關係數據庫的觸發器,但原理不完全相同
Change stream | 觸發器 | |
觸發方式 | 異步 | 同步(事務保證) |
觸發位置 | 應用回調時間 | 數據庫觸發器 |
觸發次數 | 每個訂閱時間的客戶端 | 1次(觸發器) |
故障恢復 | 從 上次斷電重新觸發 | 事務回滾 |
二,Change stream 的實現原理
Change Stream 是基於oplog 實現的。它在oplog 上開啓一個tailable cursir 來追蹤所有複製集上的變更操作,最終調用應用中定義的回調函數。
被追蹤的變更事件主要包括:
1. insert/update/delete : 插入,更新,刪除
2. drop: 集合被刪除
3. rename: 集合被重命名
4. dropDatabase: 數據庫被刪除
5. invalidate: drop/rename/dropDatabase 將導致invilidate被觸發。並關閉Change Stream
三,Change Stream 與可重複讀
Change Stream 只推送已經在大多數節點上提交的變更操作。即“可重複讀”的變更。
這個驗證是通過{readConcern:"majority"} 實現的。因此:
1.未開啓majority readConcern 的集羣無法使用 Change Stream
2. 當集羣無法滿足{w: "majority"} 時間,不會觸發Change Stream(例如PSA架構中的S因故障宕機)
四, Change Stream 變更過濾
如果只對某些類型的變更事件感興趣,可以使用聚合管道的過濾步驟過濾事件
例如
``````
var cs=db.collection.watch([{
$match: {
operationType: {
$in: [ 'insert','delete']
}
}
}])
五, Change Stream 示例
>db.collection.watch([],{maxAwaitTimeMS: 30000}).pretty()
>db.collection.insert({_id:1,text: 'hello'})
六, Change Stream 故障恢復
假設在一列寫入操作的過程中,訂閱 Change Stream的應用在接收到“寫3”之後於t0 時刻奔潰,重啓後後續的變更怎麼辦
想要從上次中斷的地方繼續獲取變更流,只需要保留上次變更通知中的_id 即可,下面所示是一次Change Stream回調所返回
的數據。每條這樣的數據都帶有一個_id,這個id 可以用於斷點恢復。例如
var cs= db.collection.watch([].{resumeAfter:<_id>})
即可從上一條通知中斷處繼續獲取後續的變更通知
{
_id: {"_data":
BinData(0,"dsadsfewsadsafeklcmancieuw+3GBA==")},
operationType: "insert",
ns: {
db:"test",
coll:"collection"
}
documentKey:{
_id:1
}
fullDocument: {
_id: 1,
text: "hello"
}
}
七,Change Stream 使用場景
1. 跨集羣的變更復制-----在源集羣訂閱Change Stream,一旦得到任何變更立即寫入目標集羣
2.微服務聯動----當一個微服務變更數據庫時,其他微服務得到通知並作出相應的變更
3. 其他任何需要系統聯動的場景
八,注意事項
1. Change Stream 依賴於oplog, 因此中斷時間不可超過oplog回收的最大時間窗;
2. 在執行update 操作時,如果只更新了部分數據,那麼Change Stream 通知的也是增量部分
3. 同理,刪除數據時通知的僅是刪除數據的_id