MongoD副本集(一)
1 副本集的目的?
1.提供冗余备份,因为一份数据会复制多份放在不同的服务器上
2.避免单点故障,一旦副本集中主服务器挂掉,其余成员会迅速选举出新的primary,对外提供服务。
3.实现读写分离。可以设置在主服务器上进行写操作,在剩余从服务器上进行读操作,大大减轻主服务器的负担。但是这样可能会存在数据不实时的问题。
2 副本集中成员类别?
1.primary:
副本集中的主服务器,只有它才能进行写操作,其他成员都只能从它进行数据同步
2.普通secondary
副本集中的从服务器,从服务器同步数据,可以接受读操作,在一定条件下可以成为primary
3.Priority 0,优先级设为0的服务器。可以同步数据,接受读操作,但是永远不会变成primary,一般仅仅用于数据备份。
4.Hidden Replica Set Members,这种服务器和上面的priority 0 服务器类似,但是有一点不同的是,客户端无法对它进行读操作。
db.isMaster()命令也看不到它。
{
"setName" : "sh1",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"192.168.69.41:10001",
"192.168.69.42:10001",
"192.168.69.40:10001"
],
"primary" : "192.168.69.41:10001",
"me" : "192.168.69.41:10001",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"localTime" : ISODate("2013-07-16T08:01:37.145Z"),
"ok" : 1
}
5.Delayed members,和上面的隐藏节点有相同属性,不过,延迟节点会延迟同步数据。
6.Arbiter,仲裁节点。上面几种类型的成员都会从主节点同步数据,仲裁节不会同步数据,他也参与投票,但是不会成为primary。如果集群里有多台服务器,而且数据冗余已经足够,为了增强容差,可以在副本集中添加多个仲裁节点。
3 最大成员数目:
副本集一般最多可以有12个成员,同时投票的成员数最多为7个。添加副本集成员或者是为了分担读压力,或者是为了增加冗余。但是要注意添加后成员数量是否是奇数,否则需要添加仲裁节点。以后的版本应该会取消这些限制。
由于投票成员最多为7个,可以设置剩余的为非投票成员,这些成员不参与投票,但是他可以否决投票,从而成为primary。
4 影响primary选举的因素
影响选举的因素有4个:
心跳:
副本集成员之间每两秒相互发送一次心跳,心跳包含状态映射表,例如,优先级信息,是否有新节点加入,是否有节点宕机。如果心跳发出后十秒,对方没有返回,节点会认为对方已经宕机,把他标记为不可达,同时通过心跳向其他节点发送这个重要信息。
优先级:
优先级不言自明。副本集中的成员收到心跳后,将会投票给优先级最高的成员。没有设置优先级时,默认是1。如果设置优先级是0,那么这个成员参与投票,同步数据,但是不可能成为primary。
Optime:
optime代表成员上次从primary应用日志的时间戳。在优先级相同的情况下,没有最新的optime则无法成为primary。所以,优先级相同情况下,一般谁的optime最新,谁就最可能成为primary。也是是说,谁最先启动,谁就是primary。
sh0:SECONDARY> rs.status().members
[
{
"_id" : 1,
"name" : "192.168.69.40:10000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 422043,
"optime" : {
"t" : 1373954309,
"i" : 139
},
"optimeDate" : ISODate("2013-07-16T05:58:29Z"),
"lastHeartbeat" : ISODate("2013-07-16T07:14:20Z"),
"lastHeartbeatRecv" : ISODate("2013-07-16T07:14:21Z"),
"pingMs" : 0
},
网络连接:
如果一个加点不能和一半以上的节点进行通信,他无法成为primary。所以,在三个成员的情况下,如果坏掉两个(都是secondly),原来的primary将会变成secondary。这个时候,副本集就变成只读的了。这点尤其需要注意。副本集成员个数与容错性(fault tolerance)如下:
所以,设置了三个成员(一主二副)的情况下,如果还有别的机器,可以在其他机器上添加几个仲裁节点,保证是奇数个即可。对于一个副本集,仲裁节点一般不建议配置在已经是primary或者secondary的机器上。
网络分割:如果成员被分立,但是配置未改变,这会造成投票量不能过半的问题,导致无法选举出primary,副本集变成只读。
例如:有个副本集有7个成员,现在由于物理原因分成了两部分,分别包含4个和3个成员。那么,第二个副本集由于投票成员是3,不到4(7的一半),这个副本集就会变成只读。
5 什么时候发生选举:
1.副本集初始化
2.Primary宕机或者用命令把他剔除出副本集。
3.副本集中一个Secondary无法与primary通信的情况下,将会触发选举。
选举期间,由于没有primary,副本集无法提供写服务,但是可以提供读服务。
6 具备选举资格的成员
PRIMARY, SECONDARY, RECOVERING, ARBITER, and ROLLBACK.,不要通过修改vote来禁掉其选举资格。
7 选举过程
上面谈到选举发生的条件,下面介绍选举的具体过程:
各节点每两秒向其他节点发送心跳,每个节点收到心跳后会更新自己的状态映射表,包括:各节点优先级,各节点的optime,是否有新节点加入,是否有老节点宕机等等
sh0:PRIMARY> rs.status()
{
"set" : "sh0",
"date" : ISODate("2013-07-16T09:31:04Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "192.168.69.40:10000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 503001,
"optime" : {
"t" : 1373954309,
"i" : 139
},
"optimeDate" : ISODate("2013-07-16T05:58:29Z"),
"self" : true
},
如果primary节点状态映射表发生变化则会通过心跳做以下判断:
自己是否能和其他大多数节点(一半以上的节点)进行通信,如果不能则自动降级为secondary
是否有更高优先级的成员,如果有,自己降级,同时准备投票给他。
如果secondary节点状态表发生变化则会检测自己是否需要成为primary,它会进行三项检测,如果任意一个是否定的则不会成为primary
是否集群中有其它节点认为自己是 primary
自己是否有资格成为 primary
其他节点收到想要成为primary节点的信息包后会进行三项检测,如果任意一个满足都会投否定票
他们自己的数据是否比发送节点更新
是否有其它节点的数据比发送节点更新
集群中是否已经有primary,他们的优先级是否比已经有的primary低
如果确认后则节点宣布自己为primary并向其他节点发布,其余节点进行最终一致性确认。也就是说,要成为primary,必须要自己得到票数多余总票数的一半,然后向其他成员确认。
8 什么时候primary降级
1. 执行replSetStepDown()命令
2. 当前一个sescondary更有成为primary的资格和更高优先级。(手动切换,修改在主服务器上修改优先级,然后reconfig)
3. Primary无法与一半以上的机器通信