MongoDB复制集简介(四)--复制集的写关注
来源:互联网 发布:9wifi九维网络登入不了 编辑:程序博客网 时间:2024/04/30 04:11
一、概念介绍
“Write Concern(写关注)”描述了当系统反馈写成功后MongoDB提供数据持久性保证程度,写关注越强,MongoDB提供的保证程度越高。当写操作具有弱写关注时,写操作会迅速返回,但是写操作可能不具有持久性;具有强写关注的客户端在发出写操作后需要等待MongoDB确认写操作成功。在单机环境下,Journaled为最高写关注级别,表示MongoDB只在写操作已经成功且日志已经写到磁盘后,才确认写成功;Acknowledged为次一等级的写关注,表示MongoDB已经确认收到了正确的写操作,应用可以排除网络故障或者重复键值等错误,这是MongoDB默认的写关注。
在复制集环境下,基本级别的写关注只能影响一台机器上的写操作。应用程序可以通过在getLastError提供w参数的不同配置,将复制集的写关注级别设置为Replica Acknowledged。通过Replica Acknowledged,我们可以保证写操作已经传播到复制集的成员中。
如下图所示,在一个3节点的复制集中,客户端在发出写请求后使用带w:2的getLastError进行写操作确认。w:2表示至少写操作已经传播到了复制集中的两个成员(包括主机),图中在第二成员已经收到主机传播来的日志且已经获得应用后对getLastError做出反馈,不需要等待日志传播到第三成员。如果我们将w的值设置超过了当前拥有数据拷贝的复制集成员个数,会导致getLastError被阻塞,直到其他数据成员变得可用满足了w的设置要求。当然,我们可以对getLastError设置一个超时阈值,以防止getLastError一直被阻塞。
在复制集配置中,有两个设置和复制集的写关注有很大关系,一个为成员的tags,另一个为复制集的getLastErrorModes设置。通过修改这两个设置,我们可以定制自己的复制集写关注,当然tags也可以用于设置读喜好,这里就不涉及了。当我们定制写关注模式时,需要注意的是该模式需要指定一个域名和一个值,如果该值为n,则要求至少有n个成员反馈接受了写操作且这n个成员对应tag的名字与模式指定的域名相同,但是每个tag的值不同,这时才能确认写成功。
二、应用举例
1、假设一个具有5个成员的复制集,每个复制成员的tags依次如下:
cfg=rs.conf()
cfg.members[0].tags={ "use": "reporting" }
cfg.members[1].tags={ "use": "backup" }
cfg.members[2].tags={ "use": "application" }
cfg.members[3].tags={ "use": "application" }
cfg.members[4].tags={ "use": "application" }
cfg.settings = { getLastErrorModes: { use2: { "use": 2 } } }
上面的getLastErrorModes要求至少有两个不同值的“use” tag成员反馈,才给应用反馈写结果,比如第一、第二个成员反馈写操作,主机就可以给应用反馈写结果。如果第三、第四个成员反馈写操作,还不能给应用反馈,因为他们两个的"use“tag值相同,必须要等到第一或者第二个成员反馈写操作后,才能给应用反馈。
2、假设一个具有三个成员的复制集,每个复制成员的tags依次如下:
{ "disk": "ssd" }
{ "disk": "ssd" }
{ "disk": "ssd" }
我们可以将getLastErrorModes设置如下:
cfg.settings = { getLastErrorModes: { disk2: { "disk": 2 } } }
getLastErrorModes配置要求至少具有两个不同的disk tag值的成员反馈才向应用反馈写结果,而实际成员的tag配置完全相同,不可能具有两个不同值的成员反馈,因此这种配置将会失败,如下所示。
test:PRIMARY> rs.reconfig(cfg)
{
"errmsg" : "exception: mode { disk: 2.0 } requires 2 tagged with disk, but only 1 with this tag were found",
"code" : 14831,
"ok" : 0
}
3、假设一个具有三个成员的复制集,每个复制成员的tags依次如下:
{ "disk": "ssd" }
{ "disk": "san" }
{ "disk": "spinning" }
根据上面的tags,如果我们想配置成在写操作传播到SAN后才反馈成功,这种配置方案在现有tags下无法实现。如果我们想实现上述写关注策略,需要额外的tags才能实现,如下:
cfg=rs.conf()
cfg.members[0].tags={ "disk": "ssd" }
cfg.members[1].tags={ "disk": "san","disksan":"san" }
cfg.members[2].tags={ "disk": "spinning" }
cfg.settings = { getLastErrorModes: { disksan1: { "disksan": 1 } } }
rs.reconfig(cfg)
上述配置成功后,我们可以看到复制集的配置如下,端口号27217对应的成员具有两个tag,而其他成员只有一个tag,我们可以使用disksan的tag来控制写操作必须传播到27217对应的成员
test:PRIMARY> rs.conf()
{
"_id" : "test",
"version" : 19,
"members" : [
{
"_id" : 0,
"host" : "localhost.localdomain:27117",
"tags" : {
"disk" : "ssd"
}
},
{
"_id" : 1,
"host" : "localhost.localdomain:27217",
"tags" : {
"disk" : "san",
"disksan" : "san"
}
},
{
"_id" : 2,
"host" : "localhost.localdomain:27317",
"tags" : {
"disk" : "spinning"
}
}
],
"settings" : {
"getLastErrorModes" : {
"disksan1" : {
"disksan" : 1
}
}
}
}
在端口号为27217的成员可用的情况下,我们使用上述写关注模式,得到以下结果,表示写已经成功。
test:PRIMARY> use test
test:PRIMARY> db.test.insert({empno:100,name:100})
test:PRIMARY> db.runCommand( { getLastError: 1, w: "disksan1" } )
{
"n" : 0,
"lastOp" : Timestamp(1382978081, 1),
"connectionId" : 957,
"writtenTo" : [
{
"_id" : 1,
"host" : "localhost.localdomain:27217",
"tags" : {
"disk" : "san",
"disksan" : "san"
}
},
{
"_id" : 0,
"host" : "localhost.localdomain:27117",
"tags" : {
"dis" : "ssd"
}
},
{
"_id" : 2,
"host" : "localhost.localdomain:27317",
"tags" : {
"disk" : "spinning"
}
}
],
"wtime" : 0,
"err" : null,
"ok" : 1
}
如果端口号为27217的成员不可用了,此事还使用该写关注模式,会发生什么?
我们通过kill进程的方法模拟端口号为27217的成员不可用,当该mongd进程被kill掉以后,复制集的状态如下:
test:SECONDARY> rs.status()
{
"set" : "test",
"date" : ISODate("2013-10-28T16:40:08Z"),
"myState" : 2,
"syncingTo" : "localhost.localdomain:27317",
"members" : [
{
"_id" : 0,
"name" : "localhost.localdomain:27117",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1274,
"optime" : Timestamp(1382978081, 1),
"optimeDate" : ISODate("2013-10-28T16:34:41Z"),
"errmsg" : "syncing to: localhost.localdomain:27317",
"self" : true
},
{
"_id" : 1,
"name" : "localhost.localdomain:27217",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(1382978081, 1),
"optimeDate" : ISODate("2013-10-28T16:34:41Z"),
"lastHeartbeat" : ISODate("2013-10-28T16:40:06Z"),
"lastHeartbeatRecv" : ISODate("2013-10-28T16:39:56Z"),
"pingMs" : 0
},
{
"_id" : 2,
"name" : "localhost.localdomain:27317",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1017,
"optime" : Timestamp(1382978081, 1),
"optimeDate" : ISODate("2013-10-28T16:34:41Z"),
"lastHeartbeat" : ISODate("2013-10-28T16:40:07Z"),
"lastHeartbeatRecv" : ISODate("2013-10-28T16:40:08Z"),
"pingMs" : 0
}
],
"ok" : 1
}
我们使用mongo工具连接到主机,执行插入操作后再调用getLastError,并增加超时10秒参数,以防止getLastError被阻塞。执行结果显示getLastError发生超时,表示设置的写关注模式未成功,这是由于具有disksan的tag成员已经不可用,写操作不可能传播到该成员上。但是这时在主机上查询empno为109的文档时,还是能够显示查询成功的,表明主机上已经写入该数据。
test:PRIMARY> db.test.insert({empno:109,name:109})
test:PRIMARY> db.runCommand( { getLastError: 1, w: "disksan1",wtimeout:10000 } )
{
"n" : 0,
"lastOp" : Timestamp(1382978744, 1),
"connectionId" : 964,
"wtimeout" : true,
"waited" : 10001,
"writtenTo" : [
{
"_id" : 2,
"host" : "localhost.localdomain:27317",
"tags" : {
"disk" : "spinning"
}
},
{
"_id" : 0,
"host" : "localhost.localdomain:27117",
"tags" : {
"disk" : "ssd"
}
}
],
"err" : "timeout",
"ok" : 1
}
test:PRIMARY> db.test.find({empno:109}))
{ "_id" : ObjectId("526e94b82e59202b33f85752"), "empno" : 109, "name" : 109 }
- MongoDB复制集简介(四)--复制集的写关注
- MongoDB复制集深入(设计复制集,日志,写关注,读关注,标签)
- MongoDB复制集(Replication Sets)简介
- MongoDB复制集简介(三)--复制集中的回滚
- MongoDB的复制集
- MongoDB的复制集
- MongoDB的主从复制与复制集
- MongoDB实战-复制(副本集的复制原理)
- MongoDB复制集简介(一)--初步认识
- MongoDB复制集简介(二)--内部信息
- mongodb复制集的搭建
- mongodb复制集的监控
- MongoDB复制集的概念
- mongodb复制集的实现
- MongoDB 复制(副本集)
- MongoDB 复制(副本集)
- MongoDB:mongodb的主从复制(二) 副本集
- mongodb复制集搭建
- 求职宝典:职场新人赶紧卸掉“假成熟”
- 如何在 SVG 和 Canvas 之间进行选择
- Linux命令 -- ps
- 运营商Pos接口连接IP网与SDH网络
- DWORD
- MongoDB复制集简介(四)--复制集的写关注
- Deep learning with word2vec and gensim
- Mac App Sandbox的问题.
- 解决connection to server failed, probable Oracle Net admin error
- android上一些类型转换
- Java跨平台中的平台
- 如何在安卓虚拟机中安装本地的apk
- 0和1的故事
- cocos2dx功能框架概述