mongodb叢集的分布式鎖的實現研究

來源:互聯網
上載者:User

標籤:io   os   ar   for   檔案   資料   2014   art   問題   

分布式鎖的作用

一般來講,鎖的作用是在於解決不同的執行流之間對於同一個資源的競爭而產生的問題。分布式鎖的作用就在於解決分布式程式中,分布在不同機器上的執行流對於資源的競爭問題。在mongodb的cluster上, 多個mongos都會發起balance這個過程。而一個時期內,只能有一個balance過程的存在。因此,如何解決多個mongos進程都要發起balance這個過程,需要分布式鎖。

代碼位置

代碼版本採用的是2.4.11版本,這個比較接近我們線上啟動並執行stable版本。

主要涉及的代碼檔案:

mongo/client/distlock.cpp

mongo/s/type_locks.h

mongo/s/type_lockpings.h

鎖的實體

分布式鎖一定會有一個儲存鎖的位置。無論檔案鎖或者是核心中的mutex或者自旋鎖、讀寫鎖,都有一個鎖的"實體“, 通過代碼對這個”實體“進行一些保護性質的運算,來實現鎖定或者是解鎖的功能。

mongodb採用的將資料庫作為鎖的”實體“。在mongodb sharding cluster中有一個重要的資料庫config,

在這個db中有兩個collection和分布式鎖有關。

一個是config.locks


mongos> db.locks.find().pretty(){        "_id" : "configUpgrade",        "process" : "i-qikzt805:50000:1390191129:1804289383",        "state" : 0,        "ts" : ObjectId("52dca219420e5e3bb3e63ee9"),        "when" : ISODate("2014-01-20T04:12:09.751Z"),        "who" : "i-qikzt805:50000:1390191129:1804289383:mongosMain:846930886",        "why" : "upgrading config database to new format v4"}{        "_id" : "balancer",        "process" : "qc24:50000:1399171433:1804289383",        "state" : 2,        "ts" : ObjectId("54115f46274b8459f178c927"),        "when" : ISODate("2014-09-11T08:37:26.462Z"),        "who" : "qc24:50000:1399171433:1804289383:Balancer:846930886",        "why" : "doing balance round"}{        "_id" : "user_data.user_data",        "process" : "qc-clouddb1:30001:1409913195:236929073",        "state" : 0,        "ts" : ObjectId("5409c74dc3a03d987a4a2d88"),        "when" : ISODate("2014-09-05T14:23:09.190Z"),        "who" : "qc-clouddb1:30001:1409913195:236929073:conn40:1485371859",        "why" : "migrate-{ _id: \"824cb5db-6cbd-c90c-95ad-915bd7880c31\" }"}{        "_id" : "user_data.device_info",        "process" : "qc24:30005:1399282507:1672775172",        "state" : 0,        "ts" : ObjectId("5406f9e738d2c06115a4e475"),        "when" : ISODate("2014-09-03T11:22:15.837Z"),        "who" : "qc24:30005:1399282507:1672775172:conn1498556:2012981408",        "why" : "migrate-{ _id: \"40acae65-45de-ce42-daf6-63fe1b0e8052\" }"}mongos>


可以看到有4個鎖的存在, "_id" : "configUpgrade" 顧名思義吧。"_id" : "balancer"是整個balancer過程的鎖。"_id" : "user_data.user_data"和"_id" : "user_data.device_info"對應具體的進行sharding的collection的balance鎖。

另一個是config.lockpings

mongos> db.lockpings.find().pretty(){        "_id" : "i-qikzt805:50000:1390191129:1804289383",        "ping" : ISODate("2014-01-20T09:26:20.903Z")}{        "_id" : "qc14:50000:1398961193:1804289383",        "ping" : ISODate("2014-09-11T08:41:07.546Z")}{        "_id" : "qc24:50000:1399171433:1804289383",        "ping" : ISODate("2014-09-11T08:40:56.833Z")}{        "_id" : "qc23:50000:1399172957:1804289383",        "ping" : ISODate("2014-09-11T08:40:55.083Z")}{        "_id" : "qc15:50000:1399173835:1804289383",        "ping" : ISODate("2014-09-11T08:40:54.947Z")}{        "_id" : "qc16:50000:1399174043:1804289383",        "ping" : ISODate("2014-09-11T08:41:04.574Z")}{        "_id" : "qc24:30005:1399282507:1672775172",        "ping" : ISODate("2014-09-05T08:50:18.879Z")}{        "_id" : "qc-clouddb6:50000:1409730027:1804289383",        "ping" : ISODate("2014-09-11T08:40:54.966Z")}{        "_id" : "qc-clouddb7:50000:1409730657:1804289383",        "ping" : ISODate("2014-09-11T08:40:54.868Z")}{        "_id" : "qc-clouddb8:50000:1409730659:1804289383",        "ping" : ISODate("2014-09-11T08:40:56.802Z")}{        "_id" : "qc-clouddb8:30008:1409813212:1448386028",        "ping" : ISODate("2014-09-11T08:40:54.989Z")}{        "_id" : "qc-clouddb1:30001:1409913195:236929073",        "ping" : ISODate("2014-09-11T08:40:54.947Z")}{        "_id" : "qc-clouddb3:30003:1409918540:1296167705",        "ping" : ISODate("2014-09-11T08:40:55.232Z")}{        "_id" : "qc-clouddb7:30007:1409919636:1928209546",        "ping" : ISODate("2014-09-11T08:40:54.762Z")}{        "_id" : "qc-clouddb2:30002:1409919744:42373342",        "ping" : ISODate("2014-09-11T08:40:52.771Z")}{        "_id" : "qc-clouddb6:30006:1409920835:1027944352",        "ping" : ISODate("2014-09-11T08:40:54.932Z")}{        "_id" : "qc-clouddb5:30005:1409920983:1186461301",        "ping" : ISODate("2014-09-11T08:40:54.949Z")}{        "_id" : "qc-clouddb4:30004:1409921811:221589655",        "ping" : ISODate("2014-09-11T08:40:55.083Z")}
i-qikzt805:50000:1390191129:1804289383 是進程id, 由hostname:port:timestamp:random()組成。

叢集中每個mongos和mongod會每隔一段時間修改自己進程id的ping時間。相當於保持heartbeat。


lockping會單獨起一個線程,每隔一段時間去更新config.lockpings。

LockPinger線程

LockPinger線程只是做3件事:

1 更新進程在config.lockpings中的時間。

2 檢查config.locks中所有鎖定時間超過4天的鎖,如果存在則釋放掉。

3 清除掉本進程之前沒有成功釋放掉的鎖。(待解鎖列表中的所有的鎖)

擷取鎖的步驟

擷取鎖的代碼主要在這個函數DistributedLock::lock_try

1 從locks collection中查詢鎖是否存在(_id==鎖名稱)如果不存在,則可以獲得鎖.

2 如果鎖存在, 分4種情況討論:

    A. 可重新進入,逾時

    B. 可重新進入,不逾時

    C. 不可重新進入, 逾時

    D. 不可重新進入,不逾時

 B可以獲得鎖, A/C/D都不可以獲得鎖

另外還涉及一個是否釋放鎖的問題。C情況下會釋放鎖, 其他情況下不會。而為什麼C釋放,而A不釋放的原因我沒有想明白。誰可以指點一下?

另外在擷取鎖的時候會分成兩步提交: 第一步先把狀態設定成1, 如果成功則再將狀態設定成2。
   

鎖逾時的判斷條件

鎖的擁有者進程的上一次ping抵達的時間已經超過15分鐘

解鎖的步驟

解鎖步驟比較簡單:

1 查詢鎖是否存在

2 如果存在將狀態改成2

3 失敗後重試n次, 如果不成功則放在待解鎖列表中


mongodb叢集的分布式鎖的實現研究

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.