Ticket #79 (closed 总结: fixed)

Opened 14 years ago

Last modified 14 years ago

mongodb 重建发现的问题

Reported by: chenchongqi Owned by:
Priority: major Milestone:
Component: 报价库 Version: 报价库4.0
Keywords: mongodb,脏数据,碎片整理 Cc:
Due Date:

Description (last modified by chenchongqi) (diff)

报价前台索引集群的几个服务器陆续出现磁盘碎片,因此我们决定逐个重建一下,按照原来的经验,数据量不大的情况下,直接drop掉重新加入是比较快的彻底的方式,但是今天出现了新的情况:

drop掉111以后,一直加不回来持续了一个小时,日志没有被报异常,但始终是UNK的状态,同时83的负载非常高,同时swap也很高。

top - 16:09:01 up 139 days,  6:46,  5 users,  load average: 57.88, 37.94, 18.54
Tasks:  88 total,   1 running,  86 sleeping,   1 stopped,   0 zombie
Cpu(s): 26.6%us, 12.6%sy,  0.0%ni,  2.6%id, 53.6%wa,  1.9%hi,  2.7%si,  0.0%st
Mem:   7141016k total,  7100332k used,    40684k free,      220k buffers
Swap:  2096472k total,   133528k used,  1962944k free,  6756148k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                         
21270 root      15   0 19.1g 6.6g 6.4g S 136.7 96.3  40:17.32 mongod                                                                                         
  423 root      10  -5     0    0    0 D 24.0  0.0 166:22.93 kswapd0                                                                                         
   86 root      10  -5     0    0    0 S  0.3  0.0   0:13.25 kblockd/0   

同时83的fault也很高

                        insert  query update delete getmore command flushes mapped  vsize    res faults locked % idx miss %     qr|qw   ar|aw  netIn netOut  conn             set repl       time 
192.168.237.111:5506        *0     *0     *0     *0       0     0|0       0  12.2g  12.4g   1.2g      0        0          0       0|0     0|0    68b   342b    13 itpricelibindex  UNK   16:12:37 
192.168.237.112:5506         0      0      0      0       0       0       0  14.2g  15.7g  3.72g      0        0          0       0|0     3|0    90b   587b   287 itpricelibindex    M   16:12:37 
192.168.237.117:5506        *0    129     *0     *0       0    38|0       0  14.2g  17.5g  2.41g      0        0          0       0|0     2|0    30k    61k   382 itpricelibindex  SEC   16:12:37 
 192.168.237.83:5506        *0    234     *0     *0       0    37|0       0  14.2g  19.2g  6.55g    235        0          0       0|0    82|0    49k   103k   341 itpricelibindex  SEC   16:12:37 
      localhost:5506         0      0      0      0       0       0       0  14.2g  15.7g  3.72g      0        0          0       0|0     3|0    90b   587b   287 itpricelibindex    M   16:12:37 

我们认为是83有问题,于是把83重启,结果此时变成112负载很高和刚才83的情况一样,而且83重启后也不正常,处于REC状态,所以之前的判断有问题,此时所有的读访问都集中在112上,而且还受111UNK的影响,112的负载很高,但是有83的情况在前,此时也不能轻易重启112.反倒有可能出问题的是111的同步拖累了其他服务器,所以暂时停掉了111.

好在mongo的机制还算不错,在只有一台SEC和M的服务器下,M也转成了SEC,变成两台服务器提供服务,而且停掉111后,没有了同步的影响,这两台剩下的服务器负载都比较低了。

这时候基本上能确定是同步的问题,之前同步速度都很快而且不会拖累其他服务器。但是现在最紧要的是恢复111和83的服务,然后再查找问题。欧彬提出把服务正常的112的data文件拷贝去111先看看能否直接用正常的数据文件恢复111,经过一番操作后111成功起来并加入了集群,这是个好消息,同样的方法把83也恢复起来加入了集群。

通过查看111的日志我们发现,在生成索引表price_front的时候都很正常,但是多了一个price_front_cache表,而且在处理这个表的时候就卡住等待83读数据:

Wed Jan  4 15:59:56 [replica set sync] replSet initial sync cloning db: price_front_cache
Wed Jan  4 15:59:56 [FileAllocator] allocating new datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.ns, filling with zeroes...
Wed Jan  4 15:59:56 [FileAllocator] done allocating datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.ns, size: 16MB,  took 0.017 secs
Wed Jan  4 15:59:56 [FileAllocator] allocating new datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.0, filling with zeroes...
Wed Jan  4 15:59:56 [FileAllocator] done allocating datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.0, size: 64MB,  took 0.065 secs
Wed Jan  4 15:59:56 [FileAllocator] allocating new datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.1, filling with zeroes...
Wed Jan  4 15:59:56 [replica set sync] replauthenticate: no user in local.system.users to use for authentication
building new index on { _id: 1 } for price_front_cache.cache_info
Wed Jan  4 15:59:56 [replica set sync] done for 7 records 0.001secs
Wed Jan  4 15:59:56 [replica set sync] replSet initial sync cloning db: admin
Wed Jan  4 15:59:56 [replica set sync] replauthenticate: no user in local.system.users to use for authentication
replSet initial sync query minValid
Wed Jan  4 15:59:56 [replica set sync] replSet initial sync initial oplog application
Wed Jan  4 15:59:57 [FileAllocator] done allocating datafile /data/PRG/mongodb/data/price_front_cache/price_front_cache.1, size: 128MB,  took 0.206 secs

但是price_front_cache是硬缓存表,照理说不应该出现在索引表专用的实例里,结果查了一下,当时83是从硬缓存实例挪过来的服务器,当时产品库动态那边的应用配置没有跟着相应改过来,但是mongo客户端的容错性比较强一直都还能正常用,然后写了一部分不正常的price_front_cache到83来:

<env-entry>
        <description>MongoDB Config</description>
        <env-entry-name>mongoConfig4RClient</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>mongodb://price_front_app:mongoprice_front_app@192.168.237.81:5506,192.168.237.82:5506,192.168.237.83:5506/price_front_cache?replica
Set=itpricelib;slaveOk=true;maxPoolSize=64;w=1</env-entry-value>
      </env-entry>
这里的83应该配为92

会不会是这部分数据是不正常的,导致111在跟83拿这部分数据的时候,83翻天覆地的找不到呢,这也解释得通83内容用满,还到磁盘上找,导致swap很高负载很高。我们把产品库动态的配置都改回来,并且在mongo的master服务器上把price_front_cache彻底删除,再次drop 111 并且同步。结果用15分钟左右111就同步完成加入了集群,同样117和83都很快完成了重做,基本上都是10分钟左右,可见问题确实出在price_front_cache这部分数据上。

  • 总结
    • 由于硬缓存和索引实例的用户密码都一样,导致客户端配置不正确的时候还能带病运行,交叉写了一些脏数据。
    • 这些脏数据的存在,导致在做集群同步操作的时候,数据输出方出现内存用满swap高负载高的现象,并且无法完成同步操作。
    • 直接拷贝data文件可以快速恢复mongo服务器并加入集群,这种方式可以考虑做为备份的一种手段。
    • 磁盘碎片用repair和重建索引没有改善,重做还是最彻底的方法(xxx was empty, skiping ahead ....).
    • 集群同步的时候把mongo增量同步任务暂停,这样没有数据写入对同步干扰会少一点。

Change History

comment:1 Changed 14 years ago by chenchongqi

  • Status changed from new to closed
  • Component changed from 产品库 to 报价库
  • Resolution set to fixed

comment:2 Changed 14 years ago by chenchongqi

  • Description modified (diff)

comment:3 Changed 14 years ago by oubin

1.在原基础上,mongodb在同步数据的时候,会找它认为最近的节点进行数据同步的拉取,这个同步是根据local库下面的记录进行恢复,如果local中存在相应记录的条数,但实际的数据文件里面没有相应的数据,mongodb就会进行全盘查找(包含内存),这导致io、cpu排队等情况出现,从而导致负载高(上面描述的第一个数据图)。
2.建索引问题,索引不是进行同步相应的数据,而是需要进行恢复的机器发现其具有索引标识,那需同步的机器会在本机进行自身索引的建立。所以,我们在数据恢复过程中看到building new index 停滞不动,不一定是本地建索引有问题,也可能是在同步数据过程中卡住,从而导致本地索引也无法进行。
3.恢复步骤,把相应文件数据文件(一定要包含local库)拷贝到目标机器的mongodb数据目录中(并一定要保持文件的属性权限),把启动脚本中#sets 额外配置的选项进行如下配置,然后启动,那这个实例也正常加入集群。
SETS_OTHER_PARA="--rest --fastsync"
#SETS_OTHER_PARA="--rest"
因为在昨天的操作在集群中已存在脏数据,所以在进行重建节点前需要把脏数据先删除。
use price_front_cache;
db.dropDatabase();
这两命令需在primary node上进行。
4.删除文件进行全同步(重建节点),从而消除碎片,具体操作步骤为:
停止实例节点
封端口ipdrop xxx down ; 主要是为了不让实例立刻加入集群中,从而有相应的时间做最后确定,这个不需要,但需要操作者在启动mongodb前要保证所做配置已完全正确。
1.rm -fr $MONGODB_HOME/data/*
2.调整启动脚本
#SETS_OTHER_PARA="--rest --fastsync"
SETS_OTHER_PARA="--rest"
3.启动节点
4.ipdrop xxx off 如果前面有封端口动作,这一定要进行解封端口,如果没解封primary node会拿不到相应的心跳包
5.通过rs.stats();查看节点是否在进行同步。
6.通过观察日志文件查看同步的情况。
7.同步完成中,切记调整启动脚本:
SETS_OTHER_PARA="--rest --fastsync"
#SETS_OTHER_PARA="--rest"
PS:运维程序中,有一套监控硬件的程序,在mongodb 集群中请不要打开,防止监控程序自动重启mongodb(某些情况下需要顶一下,重启会让事情更糟糕),切记。

Last edited 14 years ago by chenchongqi (previous) (diff)

comment:4 Changed 14 years ago by chenchongqi

陈崇锜(陈崇锜) 09:57:30
另外这个我没明白

PS:运维程序中,有一套监控硬件的程序,在mongodb 集群中请不要打开,切记。
欧彬(Sky(gz4046)) 09:57:40
proc的一个程序
欧彬(Sky(gz4046)) 09:57:48
我们平时对应用会有重启的
欧彬(Sky(gz4046)) 09:58:02
但对mongodb replicate 这边不建议打开
陈崇锜(陈崇锜) 09:58:11
哦,就是防止监控程序重启mongodb是吧
林浩(林浩#gz4046) 09:58:14
注释掉mods就可以了
欧彬(Sky(gz4046)) 09:58:14
是的
陈崇锜(陈崇锜) 09:58:24

欧彬(Sky(gz4046)) 09:58:32
我在mongodb集群上是没填mods
李思亮(李思亮) 09:58:38

欧彬(Sky(gz4046)) 09:58:47
我主要是想提醒运维方面的同事而已

comment:5 Changed 14 years ago by chenchongqi

另外还有个补充,当时想把83单独拿出来顶一下,但是当时rec状态的83就算以单机启动,查询的结果也不正常,当时封住237.45,修改配置只访问83,以雷波笔记本为例,正常是28条,但是页面上查出来的只有1条,但是直接在mongodb后台查询数量又是对的,感觉应该是某些索引已经有问题了。这里当时没有再纠结下去,因为只有112提供服务的情况下负载已经非常高,还是赶紧拷贝数据直接恢复比较快。

Note: See TracTickets for help on using tickets.