设为首页 收藏本站
查看: 1296|回复: 0

[经验分享] Mongodb源码分析--Mongos之分布式锁

[复制链接]

尚未签到

发表于 2015-7-6 05:14:04 | 显示全部楼层 |阅读模式
  在之前的一篇文章中,介绍了balancer会声明使用分布式锁来协调分布式环境下的信息沟通并确保事务一致性,有关分布式锁的一些原理性信息可以参见这几篇文章:
     http://wenku.baidu.com/view/19ce3085b9d528ea81c77982.html
     http://wenku.baidu.com/view/d94ac11ffc4ffe473368ab27.html
  
     http://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95
  
     http://en.wikipedia.org/wiki/Paxos_%28computer_science%29
  
  下图是mongod使用sharding机制时的一个系统架构图(有关如果配置sharding并进行数据存储参见我的这篇文章):

  这里Mongod实现的比较简单,它主要是通过在config服务器结点上创建并维护两个lock集合(lockpings和lock),并mongos启动时会在这两个集合中各创建一条数据记录,然后通过维护该记录的状态(包括时间戳,state)来标识当前mongos结点的锁使用情况。如果多台机器之间想使用一个锁,只要确保锁的名称一致就行,这里就会在configsvr结点的相应集合中共享这一条记录以确保只有一个mongos结点获得了该锁。

      首先mongod会在配置为configsvr结点上创建并维护两个集合,如下图:


  config.lockpings:
      _id:  存储mongos发送来的balancer的标识信息(格式=> "机器名称:时间戳:随机数")
      ping: 以及发送ping指令时的时间(日期时间格式)

config.lock:      _id: 存储锁的名称(如balancer)
      process: 关联config.lockpings中_id的字段(并与其保持一致)
      state: 锁状态(是否有操作使用该锁)。0为未锁定,1为锁定。
      ts: 锁转为使用状态时的时间戳
      when :锁转为使用状态时的时间(日期时间格式)
      who: 谁使用了该锁(格式为process + 线程名称 + 随时数)
      why: 使用锁的原因(如:doing balancer round)
  
  了解上面内容之后,我们看一下mongos分布式锁的类关系图:

  其中DistributedLock类就是分布式锁的结构,它包括如下信息:
    _name:锁名称,与config.lock中的_id相绑定
    _conn:要链接到的mongod服务器地址
    _ns:  使用的锁集合名称,构造函数将其初始化为"config.locks"
    _takeoverMinutes: 强制接管的时间(当某个lock长时间不被解锁或无响应信息时),这时系统会回收该lock(通过将state置1)
    lock_entry() : 当系统开始获取lock时所执行的操作
    unlock():解除锁定
  dist_lock_try类主要用于对上面的DistributedLock类操作进行封装,以便于使用.
     其构造函数和析构函数与DistributedLock类的lock_entry()和unlock()方法对应。
  
     下面我们就通过源码来进一步分析其底层的实现原理, 首先我们看一下DistributedLock的构造函数:


//distlock.cpp
DistributedLock::DistributedLock( const ConnectionString& conn , const string& name , unsigned takeoverMinutes )
        : _conn(conn),_name(name),_takeoverMinutes(takeoverMinutes) {
        _id = BSON( "_id"  0 )
                return;
   //线程方式执行distLockPingThread()方法
            boost::thread t( boost::bind( &distLockPingThread , conn ) );
            _seen.insert( s );
        }
        set _seen;
        mongo::mutex _mutex;
    } distLockPinger;  
      它使用线程方式来执行distLockPingThread()方法来发送ping指令,并最终执行下面方法:


//distlock.cpp
void _distLockPingThread( ConnectionString addr ) {
     //设置当前线程名称
        setThreadName( "LockPinger" );
        
        log()

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83457-1-1.html 上篇帖子: mongoDB研究笔记:分片集群部署 下篇帖子: MongoDB数据访问[C#]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表