MongoDB集群卡死问题
ijxo2226
8年前
<p>一年前搭了个MongoDB集群,跑得还算不错,但是有几次遇到过服务卡死的问题。处理起来已经得心应手了,拿来跟大家分享一下:</p> <h2>故障现象</h2> <p>业务查询缓慢,而且会有连接异常:</p> <pre> { "serverUsed" : "/10.6.19.80:10013" , "errmsg" : "exception: could not run map command on all shards for ns tloc.fileprops and query { author: { $in: [ \"exception\" ] }, type: { $in: [ 0, 1 ] } } :: caused by :: socket exception [CONNECT_ERROR] for shard2/10.6.19.91:10016" , "code" : 11002 , "ok" : 0.0} </pre> <pre> { "serverUsed" : "/10.6.19.108:10013" , "ok" : 0.0 , "errmsg" : "MR post processing failed: { errmsg: \"exception: could not initialize cursor across all shards because : socket exception [SEND_ERROR] for 10.6.19.91:10016 @ shard2/10.6.19.91:10016\", code: 14827, ok: 0.0 }"} </pre> <p>当时各个Mongo分片、路由、配置服务器进程有在运行,而且查看路由服务的IO也不算高,内存、CPU也是可以接受的。但是业务查询却会卡死,导致服务不可用。</p> <h2>故障原因</h2> <p>能通过本地连接上mongo,切到业务db,通过“db.currentOp()”查看到执行的操作,发现操作数已经开始积累,呈阻塞状态。而且通过观察可以发现一般操作累积的都是同一个分片下的任务,估计是这个分片出现了问题,有几种可能性:</p> <p>1、磁盘IO异常</p> <p>2、任务参数不合理,查询确实很慢</p> <p>总之,不可能因为一个分片问题,导致整个集群不可用。</p> <h2>故障恢复</h2> <p>如果是线上可用性,一般都会很急的,现在知道了原因,应立即恢复。这里有两种办法:</p> <p>1、一个一个地用db.killOp("opid")去杀掉某个操作(mongo没有群杀,即使你重启了路由,那些操作还在配置服务器里存着),但是这个不大合理,因为它的增长阻塞很快,而且很可能你连mongo都登不上,整个服务都瘫痪掉了;</p> <p>2、暴力重启分片,这个是目前我在使用的,也是比较快速有效的方法</p> <p>具体重启服务,也不是所有服务器都要重启,只需要把引起阻塞的分片重启即可:</p> <p>1、通过db.currentOp()或分片mongd日志确认可疑分片</p> <p>2、直接上分片机器,kill掉mongod进程</p> <p>3、再启动mongod进程</p> <p>4、进入各个路由服务器,依次执行db.shutdownServer(),再启动mongos进程</p> <p>此时,应用里那些阻塞的操作应该都没了,可以通过在路由服务上执行db.xxx.find()来确认是否集群可用。</p> <p> </p> <p><a href="/misc/goto?guid=4959675359540177459">阅读原文</a></p> <p> </p>