即時同步MongoDB Oplog開發指南

來源:互聯網
上載者:User

標籤:mongodb   表示   bsp   注意   發送   query   set   (())   儲存   

轉載請註明joymufeng,歡迎訪問PlayScala社區(http://www.playscala.cn/)

Capped Collections

MongoDB有一種特殊的Collection叫Capped collections,它的插入速度非常快,基本和磁碟的寫入速度差不多,並且支援按照插入順序高效的查詢操作。Capped collections的大小是固定的,它的工作方式很像環形緩衝器(circular buffers), 當剩餘空間不足時,會覆蓋最先插入的資料。

Capped collections的特點是高效插入和檢索,所以最好不要在Capped collections上添加額外的索引,否則會影響插入速度。Capped collections可以用於以下情境:

  • 儲存日誌: Capped collections的first-in-first-out特性剛好滿足日誌事件的儲存順序;
  • 緩衝小量資料:因為緩衝的特點是讀多寫少,所以可以適當使用索引提高讀取速度。

Capped collections的使用限制:

  • 如果更新資料,你需要為之建立索引以防止collection scan;
  • 更新資料時,文檔的大小不能改變。比如說name屬性為‘abc‘,則只能修改成3個字元的字串,否則操作將會失敗;
  • 資料不允許刪除,如果非刪除不可,只能drop collection
  • 不支援sharding
  • 預設只支援按自然順序(即插入順序)返回結果

Capped collections可以使用$natural操作符按插入順序的正序或反序返回結果:

db[‘oplog.rs‘].find({}).sort({$natural: -1})
Oplog

Oplog是一種特殊的Capped collections,特殊之處在於它是系統級Collection,記錄了資料庫的所有操作,叢集之間依靠Oplog進行資料同步。Oplog的全名是local.oplog.rs,位於local資料下。由於local資料不允許建立使用者,如果要訪問Oplog需要藉助其它資料庫的使用者,並且賦予該使用者訪問local資料庫的許可權,例如:

db.createUser({   user: "play-community",   pwd: "******",   "roles" : [    {      "role" : "readWrite",       "db" : "play-community"    },     {      "role" : "read",       "db" : "local"    }  ]})

Oplog記錄的操作記錄是等冪的(idempotent),這意味著你可以多次執行這些操作而不會導致資料丟失或不一致。例如對於$inc操作,Oplog會自動將其轉換為$set操作,例如未經處理資料如下:

{   "_id" : "0",   "count" : 1.0}

執行如下$inc操作:

db.test.update({_id: "0"}, {$inc: {count: 1}})

Oplog記錄的日誌為:

{   "ts" : Timestamp(1503110518, 1),   "t" : NumberLong(8),   "h" : NumberLong(-3967772133090765679),   "v" : NumberInt(2),   "op" : "u",   "ns" : "play-community.test",   "o2" : {    "_id" : "0"  },   "o" : {    "$set" : {      "count" : 2.0    }  }}

這種轉換可以保證Oplog的等冪性。另外Oplog為了保證插入效能,不允許額外建立索引。

Timestamps格式

MongoDB有一種特殊的時間格式Timestamps,僅用於內部使用,例如上面Oplog記錄:

Timestamp(1503110518, 1)

Timestamps長度為64位:

  • 前32位是time_t值,表示從epoch時間至今的秒數
  • 後32位是ordinal值,該值是一個順序增長的序數,表示某一秒內的第幾次操作
開始同步Oplog

在開始同步Oplog之前,我們需要注意以下幾點:

  • 由於Oplog不使用索引,所以初始查詢代價可能很大
  • 當Oplog資料量很大時,可以儲存ts,系統重啟時利用該ts可以減少首次查詢開銷
  • oplogReplay標誌可以顯著加快包含ts條件過濾的查詢,但是只對oplog查詢有效
val tailingCursor = oplogCol  .find(Json.obj("ns" -> Json.obj("$in" -> Set(s"${db}.common-doc", s"${db}.common-article")), "ts" -> Json.obj("$gte" -> lastTS)))  .options(QueryOpts().tailable.oplogReplay.awaitData.noCursorTimeout)  .cursor[BSONDocument]()tailingCursor.fold(()){ (_, doc) => try {  val jsObj = doc.as[JsObject]  jsObj("op").as[String] match {   case "i" => // 插入   case "u" => // 更新   case "d" => // 刪除  }  // 儲存ts值,以備後用  if (tailCount.get() % 10 == 0) { } } catch {  case t: Throwable =>   Logger.error("Tail oplog Error: " + t.getMessage, t) }}

另外提醒大家注意,ReactiveMongo-Streaming的Akka Stream實現有bug,如果首次查詢沒有資料返回,則會持續發送查詢請求,大約每秒中發送幾十次至幾百次請求,因為Oplog的查詢開銷很大,最終會導致MongoDB記憶體溢出。詳情參考Keep sending queries while the initial query result of a tailable cursor is empty.

參考
  • MongoDB Doc - Replica Set Oplog
  • MongoDB Doc - Capped Collections
  • MongoDB Doc - Tailable Cursors

即時同步MongoDB Oplog開發指南

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.