關於mongo原子操作的探討

積木村の研究所發表於2015-12-13

眾所周知,Redis採用的是非同步I/O非阻塞的單程式模型,每一條Redis命令都是原子性的。那麼mongoDB呢? mongo有哪些原子操作呢?有哪些實現事務性操作的技巧呢?

1.對單個文件的原子性修改

mongoDB保證了對單個document的多個filed的原子性修改。如果需要對單個文件進行原子性的CAS操作(check and set),可以使用findAndModify操作。

比如下面就是一條原子性的CAS操作,首先選擇_id為123的文件(注意這裡只選擇了一個文件),然後對計數器count加1,將status欄位變為true,並返回修改後的結果。

db.colleciton.findAndModify({query:{_id:'123'},$inc:{count:1},$update:{status:true}},new:true);

2.對多個文件使用$isolate操作符

$isolate操作符可以對多個文件的修改提供隔離性。針對其他執行緒的併發寫操作,$isolate保證了提交前其他執行緒無法修改對應的文件。針對其他執行緒的讀操作,$isolate保證了其他執行緒讀取不到未提交的資料。

但是$isolate有驗證的效能問題,因為這種情況下執行緒持有鎖的時間較長,嚴重的影響mongo的併發性。另外,$isolate也無法保證多個文件修改的一致性(all-or-nothing),$isolate失敗是可能只修改了部分文件。

3.從語意層面實現事務性操作

mongoDB官方提供了一種做法,即兩階段提交(two-phase commit),基本的原理就是利用了寫操作的冪等性。具體實現可以看官網的詳細講解。但是利用冪等性來實現事務性有一個重要的前置條件:業務不在乎中間態的不一致。冪等性可以保證最終的一致性,但是會出現中間的不一致狀態。

本文同時發表在我的部落格積木村の研究所http://foio.github.io/mongo-atom/

相關文章