MongoDB shard相关源码分析

 

MongoDB源码分析

由于应用场景的需要, 我们需要对MongoDB具体实现机制进行进一步的了解,作为开源软件, 直接查看源代码, 肯定是最好的选择, 由于我们最关注的是,mongos作为一个转发的代理服务器, 是否可能会成为整个系统中的一个单点和实现瓶颈, 因此,在这次源码阅读过程中,最主要是关注了和mongos相关的几个类,其实也是整个mongoDB实现shard机制的最主要的类, 包括"s/config.cpp" , "s/grid.cpp" , "s/chunk.cpp" , "s/shard.cpp" , "s/shardkey.cpp" 通过查看这几个主要的类以及它里面使用的一些类, 真正了解mongoDB内部的运作协调机制。

 

1shard

shard机制, 是mongoDB非常重要的一个机制, 实际上, mongoDB就是将database分布到多个shard上, 来实现数据的切分并提高数据的访问效率, 那么shard是如何实现的呢?


1.1shardStatus

为了更好的表示shard当前的状态, mongoDB定义了一个shardStatus的类, 里面主要包含了

一个shard, 一个表示当前时间状态的信息, 一个是否有回写的队列信息, 以及一个是否被加上写锁的信息, 通过这几个信息, 来表示。

 

1.2 shard

shard主要包含了以上几个member, 包括shard的名字, shard的地址, 包括ip port shard的最大值, 如果shard的大小达到最大值, config server 不会继续将数据分配到这个节点, _isDrain表示当前的的shard是否正在被移除。

 

1.3 StaticShardInfo

而实际上, 所有的shard的信息, 是保存在这给staticshardInfo的的静态遍历中。它的成员非常见到,一个互斥锁和一个map<string,Shard> _lookup;, 这个map通过名字,可以很方便查找出所有的shard的信息。方便在整个程序中进行共享。

shard中, 主要包括了以上几个关键类, reload()方法, 通过连接config server中的primary, 读取configuration server所有有关shard的信息, 并保存到shard中。 _lookup()方法, 主要实现了查询当前的一个shard是否是在我们程序的一个成员shard

find()方法实现查询, 如果是一个复制集, 那么根据复制集的名字来查询是否在shard中。getAllShard就比较见名知义, 获取当前所有的shard.

shards实际上就是调用了staticshardinfo中的方法, 来实现了大部分的方法。

 

2chunks

shards, 实际上是从比较宏观的角度 去看那些数据的分割,但是实际上, chunks才是mongoDB在不同shards之间交互的最小单位, 只有了解了chunks在整个mongoDB的流通, 才能真正了解整个mongoDB的实现细节。chunks里面, 实际上是包含了一定数量的,根据shard

keys排好序的collection 。由于这个类太重要,太复杂, 因此它有很多的辅助类, 且听我一一到来。

 

2.1 chunkRange

chunkRangemember, 很清楚的表明了这个类的意义, 首先是有一个shard, 然后上面 包含了一个collection上的shardkey的最大值和最小值, 同时还包含了一个chunkManager  的指针, 指向所有chunk的所有相关信息

 

 

2.2chunkRangeManager

chunkRanageManger, 这是一个管理chunkRange的辅助类, 它有一个map的成员, 主要保存了所有的chunkRange的指针。

 

  23chunk

chunk主要保存了以下数据成员, 主要就是一个最大值,一个最小值, 还有一个shard, 指向他保存的shard的地址, 还有一个chunkMange的指针,用于对chunk进行操作,最主要的操作类都是在chunk chunkManage中。还有个shardchunkversion,用于进行版本控制,确保在多个写之后, 服务器知道哪个是最新的更新数据, 从而保证了最终一致性。

chunk中, 主要包括了以下的方法

1.contains, 判断一个key值是否在shards

2.  pickMedianKey mongod发出一个关于chuks 分隔点的查询, 返回中位的key

3.singleSplit 对当前的shards进行分割,  获取适合的的分割点

4.multiSplit 根据多个key值,将shard里面的chunk, 分割成多个chunk分割成多个chunk

5.   moveAndCommit chunk, 从当前的shard ,移动到指定的shards如果移动成功,就需要reload,获取当前chunk的元数

6. moveIfShould 如果当前shardchunk数小于1???这个countObjects的不是非常理解 从shard中选一个最适合的shardchunk移动到新的位置

7. splitIfShould 当需要的时候切分, 切分的门槛的数字, 根据当前chunk的数字, 得出需要切分的一个限制, 如果是需要分割, 那么用singleSplit进行分割得到需要移动到的新shard,调用moveIfShould,进行移动

 

  24 chunkManager

首先是chunkManager的几个member, 首先在一个chunManager中, 包含了命名空间, 关键字, 是否唯一等基本信息, 同时包括了一个管理的所有chunk的一个map, 一个包含所有shard的一个set , 同时还有一个chunkRanagegManager ,,管理所有的chunkRange, 一个sequenceNumber,进行版本管理。

主要的方法包括

1._load() 连接primary confige server 查询"config.chunks"

获取所有的chunk信息和shards信息 并保存到_chukMap shards

2. _isValid 确保chunkMap中的所有chunks没有间隔和交

3._reload_inlock() 最少尝试3_load() 直到_isvald()

_chunkRangs.reloadAll(_chunkMap);序列号+1 通过版本控制的机制, 来跟踪chunkManager 重新load的次数 通过触发 checkShardVersion 来达到连接级的版本达到最新的状态

4.ceateFirstChunk在指定的shard上面,增加一个chunk,指定min max 获取一个version号, 并增加1 获取一个连接, 修改chunk collection的信息  config.chunks 序列数的号码增加1 每一个chunkmanager 有个唯一的数字 通过检查chunkmange 的序列号, 来确定 chunk的配置信息是否更改 将chunk 存到chunkMap

chunkRange 进行reloadAll chunk所在的shard存到shard

修改chunk当前的版本号 确保shardKey中需要index的建index

5.findChunk  获取key值, 查询_chunkMap, 如果存在,并且chunk中包含了对应的obj那么返回。如果要求retry, 可以进行第二次尝试 每次尝试, 都会进行_reload_inlock()

6.findChunkOnServer( ) 通过遍历_chunkMap ,找到在指定shard上的chunk

7.getShardsForRange 变量所有从minmax的所有的shard并保存到shards里面 ensureIndex_inlock 变量shards中所有的shard, 对key建立索引 每次都需要啊?所有key都需要

8. getVersioin  通过遍历chunkMap上面的所有chunk, 获取当前最大的版本号 并返回。

 

3小结

小结, 代码看到这里, 也就大概知道了整个 mongoDB内部如何对根据chunk进行合理的管理的 。这一切的最高管理者,当然是chunkManager, 它掌控着所有的生杀大权。从load开始, 读取config server,所有chuk的信息, 并建立所有相关的chunkchunkRange shards等相关的信息, 并根据chunk的需要比如负载不均衡,或者有新的shard加入的适合,将一些chunk移到适当的shard上面, 从而保证shard上面既不会爆满, 又能够达到负载均衡。而chunk中的方法, 有保证了可以将chunk按照较为平均的比例切分到不同的shards上面。同时, chunk上面包含了版本控制的信息, 保证了W+R>N的原理, 来保证整个写入的最终一致性。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值