mongodb集群的分布式锁的实现研究

分布式锁的作用

一般来讲,锁的作用是在于解决不同的执行流之间对于同一个资源的竞争而产生的问题。分布式锁的作用就在于解决分布式程序中,分布在不同机器上的执行流对于资源的竞争问题。在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次, 如果不成功则放在待解锁列表中

时间: 2024-08-28 06:01:25

mongodb集群的分布式锁的实现研究的相关文章

Redis官网——如何利用Redis做服务器集群的分布式锁

链接:http://redis.io/topics/distlock 原理很简单,一段时间内轮询加锁的key 重点,不同语言的开源实现 Before describing the algorithm, here are a few links to implementations already available that can be used for reference. Redlock-rb (Ruby 实现). There is also a fork of Redlock-rb th

搭建高可用mongodb集群—— 分片

从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的.而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题. 传统数据库怎么做海量数据读写?其实一句话概括:分而治之.上图看看就清楚了,如下 taobao岳旭强在infoq中提到的 架构图: 上图中有个TDDL,是taobao的一

搭建高可用mongodb集群(四)—— 分片

转载自LANCEYAN.COM 按照上一节中<搭建高可用mongodb集群(三)—— 深入副本集>搭建后还有两个问题没有解决: 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的.而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题. 传统数据库怎么做海量数据读写?其实一句

搭建高可用mongodb集群(三)—— 深入副本集内部机制

http://www.lanceyan.com/tech/mongodb_repset2.html 在上一篇文章<搭建高可用mongodb集群(二)—— 副本集> 介绍了副本集的配置,这篇文章深入研究一下副本集的内部机制.还是带着副本集的问题来看吧! 副本集故障转移,主节点是如何选举的?能否手动干涉下架某一台主节点. 官方说副本集数量最好是奇数,为什么? mongodb副本集是如何同步的?如果同步不及时会出现什么情况?会不会出现不一致性? mongodb的故障转移会不会无故自动发生?什么条件会

MongoDB集群解决方案-分片技术

MongoDB,NoSQL技术的实现,基于分布式文件存储的数据库,由C++语言编写.主要是解决海量数据的访问效率问题,为web应用提供可扩展的高性能数据库存储解决方案 MongoDB集群的实现方式: 1.Replica Set:也叫作副本集,简单来说就是集群中的服务器包含了多分数据,保证主节点挂掉了.备节点能够继续的提供服务,但是提供的前提就是数据必须要和主节点的一致,如下图: MongoDB(M)表示主节点,MongoDB(S)表示从节点,MongoDB(A)表示仲裁节点: M节点存储数据并提

搭建高可用mongodb集群(一)——配置mongodb

搭建高可用mongodb集群(一)--配置mongodb 在大数据的时代,传统的关系型数据库要能更高的服务必须要解决高并发读写.海量数据高效存储.高可扩展性和高可用性这些难题.不过就是因为这些问题Nosql诞生了. NOSQL有这些优势: 大数据量,可以通过廉价服务器存储大量的数据,轻松摆脱传统mysql单表存储量级限制. 高扩展性,Nosql去掉了关系数据库的关系型特性,很容易横向扩展,摆脱了以往老是纵向扩展的诟病. 高性能,Nosql通过简单的key-value方式获取数据,非常快速.还有N

搭建高可用mongodb集群

搭建高可用mongodb集群(一)——配置mongodb Posted on 17 十一月, 2013 by lanceyan | 9条评论 在大数据的时代,传统的关系型数据库要能更高的服务必须要解决高并发读写.海量数据高效存储.高可扩展性和高可用性这些难题.不过就是因为这些问题Nosql诞生了. NOSQL有这些优势: 大数据量,可以通过廉价服务器存储大量的数据,轻松摆脱传统mysql单表存储量级限制. 高扩展性,Nosql去掉了关系数据库的关系型特性,很容易横向扩展,摆脱了以往老是纵向扩展的

Mongodb集群部署以及集群维护命令

Mongodb集群部署以及集群维护命令 http://lipeng200819861126-126-com.iteye.com/blog/1919271 mongodb分布式集群架构及监控配置 http://freeze.blog.51cto.com/1846439/884925/ 见文中: 七.监控配置:      早在去年已经出现MongoDB和Redis的Cacti模板,使用它,你可以对你的MongoDB和Redis服务进行流量监控.cacti的模板一直在更新,若企业已经用到nosql这种

Spring+Quartz框架实现定时任务(集群,分布式)

1.定时任务的必要性: 定时任务在应用中的重要性不言而喻,大多是应用,特别是金融应用更是离不开定时任务,能用定时任务来处理异常订单,完成跑批,定时活动(双11)等.在初期应用的访问量并不是那么大,一台服务器完全满足使用,但是随着用户量.业务量的逐日增加,应用中会有很多定时任务需要执行,一台服务器已经不能满足使用,因此需要把应用给部署到集群中,前端通过nginx代理实现访问. 2.集群使用定时任务的问题:目前大部分在集群中处理定时任务的方式不是正真的分布式处理方式,而是一种伪分布式,这种方式存在一