标签:des style blog http io ar color os 使用
我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明SolrCloud的数据存在着不一致性,需要进行Recovery,这个时候的SolrCloud建索引是不会写入索引文件中的(每个shard接受到update后写入自己的ulog中)。关于Recovery的内容包含三篇,本文是第一篇介绍Recovery的原因以及总体流程。
Recovery一般发生在以下三个时候:
前面两种情况暂时不介绍,本文先介绍下第三种情况。大致原理如下图所示:
之前在<Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2)>中讲到,不管update请求发送到哪个shard 分片中,最后在solrcloud里面进行分发的顺序都是从Leader发往Replica。Leader接受到update请求后先将document放入自己的索引文件以及update写入ulog中,然后将update同时转发给各个Replica分片。这就流程在就是之前讲到的add的索引链过程。
那么在索引链的add过程完毕后,SolrCloud会再依次调用finish()函数用来接受每一个Replica的响应,检查Replica的update操作是否成功。如果一旦有一个Replica没有成功,就会向update失败的Replica发送RequestRecovering命令强迫该分片进行Recoverying。
1 private void doFinish() { 2 // TODO: if not a forward and replication req is not specified, we could 3 // send in a background thread 4 5 cmdDistrib.finish(); 6 List<Error> errors = cmdDistrib.getErrors(); 7 // TODO - we may need to tell about more than one error... 8 9 // if its a forward, any fail is a problem - 10 // otherwise we assume things are fine if we got it locally 11 // until we start allowing min replication param 12 if (errors.size() > 0) { 13 // if one node is a RetryNode, this was a forward request 14 if (errors.get(0).req.node instanceof RetryNode) { 15 rsp.setException(errors.get(0).e); 16 } else { 17 if (log.isWarnEnabled()) { 18 for (Error error : errors) { 19 log.warn("Error sending update", error.e); 20 } 21 } 22 } 23 // else 24 // for now we don‘t error - we assume if it was added locally, we 25 // succeeded 26 } 27 28 29 // if it is not a forward request, for each fail, try to tell them to 30 // recover - the doc was already added locally, so it should have been 31 // legit 32 33 for (final SolrCmdDistributor.Error error : errors) { 34 if (error.req.node instanceof RetryNode) { 35 // we don‘t try to force a leader to recover 36 // when we cannot forward to it 37 continue; 38 } 39 // TODO: we should force their state to recovering ?? 40 // TODO: do retries?? 41 // TODO: what if its is already recovering? Right now recoveries queue up - 42 // should they? 43 final String recoveryUrl = error.req.node.getBaseUrl(); 44 45 Thread thread = new Thread() { 46 { 47 setDaemon(true); 48 } 49 @Override 50 public void run() { 51 log.info("try and ask " + recoveryUrl + " to recover"); 52 HttpSolrServer server = new HttpSolrServer(recoveryUrl); 53 try { 54 server.setSoTimeout(60000); 55 server.setConnectionTimeout(15000); 56 57 RequestRecovery recoverRequestCmd = new RequestRecovery(); 58 recoverRequestCmd.setAction(CoreAdminAction.REQUESTRECOVERY); 59 recoverRequestCmd.setCoreName(error.req.node.getCoreName()); 60 try { 61 server.request(recoverRequestCmd); 62 } catch (Throwable t) { 63 SolrException.log(log, recoveryUrl 64 + ": Could not tell a replica to recover", t); 65 } 66 } finally { 67 server.shutdown(); 68 } 69 } 70 }; 71 ExecutorService executor = req.getCore().getCoreDescriptor().getCoreContainer().getUpdateShardHandler().getUpdateExecutor(); 72 executor.execute(thread); 73 74 } 75 }
Replica接收到来自Leader的RequestRecovery命令后就会开始进行RecoveryStrategy线程,然后进行Recovery。总体流程如下图索引:
1 // if true, we are recovering after startup and shouldn‘t have (or be receiving) additional updates (except for local tlog recovery) 2 boolean recoveringAfterStartup = recoveryStrat == null; 3 4 recoveryStrat = new RecoveryStrategy(cc, cd, this); 5 recoveryStrat.setRecoveringAfterStartup(recoveringAfterStartup); 6 recoveryStrat.start(); 7 recoveryRunning = true;
1 zkController.publish(core.getCoreDescriptor(), ZkStateReader.RECOVERING);
1 if (recoveringAfterStartup) { 2 // if we‘re recovering after startup (i.e. we have been down), then we need to know what the last versions were 3 // when we went down. We may have received updates since then. 4 recentVersions = startingVersions; 5 try { 6 if ((ulog.getStartingOperation() & UpdateLog.FLAG_GAP) != 0) { 7 // last operation at the time of startup had the GAP flag set... 8 // this means we were previously doing a full index replication 9 // that probably didn‘t complete and buffering updates in the 10 // meantime. 11 log.info("Looks like a previous replication recovery did not complete - skipping peer sync. core=" 12 + coreName); 13 firstTime = false; // skip peersync 14 } 15 } catch (Exception e) { 16 SolrException.log(log, "Error trying to get ulog starting operation. core=" 17 + coreName, e); 18 firstTime = false; // skip peersync 19 } 20 }
本文主要介绍了Recovery的起因以及Recovery过程,由于是简述所以内容较简单,主要提到了两种不同的Recovery策略,后续两文种将分别详细介绍。
Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)
标签:des style blog http io ar color os 使用
原文地址:http://www.cnblogs.com/rcfeng/p/4145349.html