Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)

时间:2021-10-31 06:04:32
  • Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)

题记:  前文<Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)>中提到Recovery有两种策略,一是PeerSync和Replication。本节将具体介绍下PeerSync策略。

PeeySync是Solr的优先选择策略,每当需要进行recovery了,Solr总是会先去判断是否需要进入PeerSync,只有当PeerSync被设置为跳过或者PeerSync时候发现没符合条件才会进入到Replication。这是由PeeySync的特性决定的,PeeySync是面向中断时间短,需要recovery的document个数较少时使用的策略,因此它Recovery的速度较快,对Solr的影响较小。而Replication则是对中断时间长,需要recovery数量多的情况下进行的,耗时较长。

前文已经介绍了Recovery的总体流程,那么本文就直接来介绍PeerSync的流程了,请看下图所示:

Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)

  • 首先 Solr会向所有Replica发送getversion的请求,来获取最新的nupdate个version(默认是100个)。
     // Fire off the requests before getting our own recent updates (for better concurrency)
// This also allows us to avoid getting updates we don't need... if we got our updates and then got their updates, they would
// have newer stuff that we also had (assuming updates are going on and are being forwarded).
for (String replica : replicas) {
requestVersions(replica);
} private void requestVersions(String replica) {
SyncShardRequest sreq = new SyncShardRequest();
sreq.purpose = 1;
sreq.shards = new String[]{replica};
sreq.actualShards = sreq.shards;
sreq.params = new ModifiableSolrParams();
sreq.params.set("qt","/get");
sreq.params.set("distrib",false);
sreq.params.set("getVersions",nUpdates);
shardHandler.submit(sreq, replica, sreq.params);
}
  • 获取本分片最新的nupdate个version(默认是100个),并对这些version进行排序。
     recentUpdates = ulog.getRecentUpdates();
try {
ourUpdates = recentUpdates.getVersions(nUpdates);
} finally {
recentUpdates.close();
} Collections.sort(ourUpdates, absComparator);
  • 获取recovery之前的version信息startingversions。通过比较startingversions与ourUpdates可以来比较recovery期间是否有索引更新。
  • 检查ourUpdates和startingversions是否有交集,由于ourUpdates和startingversions的version个数是限制为nUpdates的,也就是判断索引更新的个数是否大于nUpdate。如果需要更新的索引太多即ourUpdates和startingversions无交集,则进入Replication。
       // now make sure that the starting updates overlap our updates
// there shouldn't be reorders, so any overlap will do. long smallestNewUpdate = Math.abs(ourUpdates.get(ourUpdates.size()-1)); if (Math.abs(startingVersions.get(0)) < smallestNewUpdate) {
log.warn(msg() + "too many updates received since start - startingUpdates no longer overlaps with our currentUpdates");
return false;
}
  • 如果ourUpdates和startingversions有交集,则合并两个列表,即求并集。
       // let's merge the lists
List<Long> newList = new ArrayList<>(ourUpdates);
for (Long ver : startingVersions) {
if (Math.abs(ver) < smallestNewUpdate) {
newList.add(ver);
}
} ourUpdates = newList;
  • 本分片的version比别的分片低,则进入Replication策略。这里进行分片version的比较,并没有按version的最大或者最小值,而是比较0.8和0.2比例处的version。
     long otherHigh = percentile(otherVersions, .2f);
long otherLow = percentile(otherVersions, .8f); if (ourHighThreshold < otherLow) {
// Small overlap between version windows and ours is older
// This means that we might miss updates if we attempted to use this method.
// Since there exists just one replica that is so much newer, we must
// fail the sync.
log.info(msg() + " Our versions are too old. ourHighThreshold="+ourHighThreshold + " otherLowThreshold="+otherLow);
return false;
}
  • 如果本分片的version比其他分片高,则说明不需要进行recovery直接退出peersync。
     if (ourLowThreshold > otherHigh) {
// Small overlap between windows and ours is newer.
// Using this list to sync would result in requesting/replaying results we don't need
// and possibly bringing deleted docs back to life.
log.info(msg() + " Our versions are newer. ourLowThreshold="+ourLowThreshold + " otherHigh="+otherHigh);
return true;
}
  • 对本分片的version和其他分片的version求差,获取本分片缺少的version。
     for (Long otherVersion : otherVersions) {
// stop when the entries get old enough that reorders may lead us to see updates we don't need
if (!completeList && Math.abs(otherVersion) < ourLowThreshold) break; if (ourUpdateSet.contains(otherVersion) || requestedUpdateSet.contains(otherVersion)) {
// we either have this update, or already requested it
// TODO: what if the shard we previously requested this from returns failure (because it goes
// down)
continue;
} toRequest.add(otherVersion);
requestedUpdateSet.add(otherVersion);
}
  • 最后向其他分片发送getupdate命令,根据处理后的version获取相应的document,至此完成peersync过程
   private boolean requestUpdates(ShardResponse srsp, List<Long> toRequest) {
String replica = srsp.getShardRequest().shards[0]; log.info(msg() + "Requesting updates from " + replica + "n=" + toRequest.size() + " versions=" + toRequest); // reuse our original request object
ShardRequest sreq = srsp.getShardRequest(); sreq.purpose = 0;
sreq.params = new ModifiableSolrParams();
sreq.params.set("qt", "/get");
sreq.params.set("distrib", false);
sreq.params.set("getUpdates", StrUtils.join(toRequest, ','));
sreq.params.set("onlyIfActive", onlyIfActive);
sreq.responses.clear(); // needs to be zeroed for correct correlation to occur shardHandler.submit(sreq, sreq.shards[0], sreq.params); return true;
}

总结:

本文具体介绍PeerSync的过程,由此可见PeerSync策略的recovery过程还是比较简单的,下一节将具体介绍Replication策略,这个较PeerSync复杂。

Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)的更多相关文章

  1. Solr4&period;8&period;0源码分析&lpar;24&rpar;之SolrCloud的Recovery策略&lpar;五&rpar;

    Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五) 题记:关于SolrCloud的Recovery策略已经写了四篇了,这篇应该是系统介绍Recovery策略的最后一篇了 ...

  2. Solr4&period;8&period;0源码分析&lpar;23&rpar;之SolrCloud的Recovery策略&lpar;四&rpar;

    Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四) 题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面 ...

  3. Solr4&period;8&period;0源码分析&lpar;22&rpar;之SolrCloud的Recovery策略&lpar;三&rpar;

    Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及P ...

  4. Solr4&period;8&period;0源码分析&lpar;20&rpar;之SolrCloud的Recovery策略&lpar;一&rpar;

    Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一) 题记: 我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明Solr ...

  5. Solr4&period;8&period;0源码分析&lpar;25&rpar;之SolrCloud的Split流程

    Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...

  6. Solr4&period;8&period;0源码分析&lpar;14&rpar;之SolrCloud索引深入&lpar;1&rpar;

    Solr4.8.0源码分析(14) 之 SolrCloud索引深入(1) 上一章节<Solr In Action 笔记(4) 之 SolrCloud分布式索引基础>简要学习了SolrClo ...

  7. Solr4&period;8&period;0源码分析&lpar;15&rpar; 之 SolrCloud索引深入&lpar;2&rpar;

    Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2) 上一节主要介绍了SolrCloud分布式索引的整体流程图以及索引链的实现,那么本节开始将分别介绍三个索引过程即LogUpdat ...

  8. Solr4&period;8&period;0源码分析&lpar;17&rpar;之SolrCloud索引深入&lpar;4&rpar;

    Solr4.8.0源码分析(17)之SolrCloud索引深入(4) 前面几节以add为例已经介绍了solrcloud索引链建索引的三步过程,delete以及deletebyquery跟add过程大同 ...

  9. Solr4&period;8&period;0源码分析&lpar;16&rpar;之SolrCloud索引深入&lpar;3&rpar;

    Solr4.8.0源码分析(16)之SolrCloud索引深入(3) 前面两节学习了SolrCloud索引过程以及索引链的前两步,LogUpdateProcessorFactory和Distribut ...

随机推荐

  1. 【BZOJ-3956】Count ST表 &plus; 单调栈

    3956: Count Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 173  Solved: 99[Submit][Status][Discuss] ...

  2. HttpLib - 一个对 Http 协议进行封装的库

    今日,在 Codeplex 上看到一个开源项目,对 Http 协议进行了封装,这下可以方便这些在 .NET 平台下访问 Web 服务器的同学们了,比如,从 Web 服务器抓取一个页面,使用 .NET ...

  3. 借鉴网上的winform模仿QQ窗口停靠功能稍作改动

    2015-07-11 15:24:04 1 using System; using System.Collections.Generic; using System.ComponentModel; u ...

  4. 我的Android 4 学习系列之创建应用程序和Activity:Manifest、Application、Activity

    目录 介绍Android应用程序组件,以及使用这些组件构建的各种Android应用程序 Android应用程序的生命周期 如何创建应用程序Manifest 如何使用外部资源提供对位置.语言和硬件配置的 ...

  5. 配置 php-fpm 监听的socket

    一般现在我们配置的PHP的web环境,如LNMP(linux+Nginx+Mysql+PHP), 这里linux可能是centos, ubuntu..., 数据库可能是mysql, postgresq ...

  6. html阶段测试

    1.简述src和href的区别? 2.在html页面的head中定义属性<meta http-equiv="X-UA-Compatible" content="IE ...

  7. GO安全并发之无锁原子操作

    声明:本文是<Go并发编程实战>的样章,禁止以任何形式转载此文. 摘要: 我们已经知道,原子操作即是进行过程中不能被中断的操作.也就是说,针对某个值的原子操作在被进行的过程当中,CPU绝不 ...

  8. Python基础面试,看这篇文章画重点吧,Python面试题No1

    为什么有这个系列的文章 一直想写一些更加基础的文章,但是总是想不到好的点子,最近到了就业季,一大堆学生面临就业了,正好,从Python的面试题出发,分析和解答一些常见的面试题,并且总结一些文字. 每一 ...

  9. GIT和SVN版本控制

    Git 与SVN SVN 是集中式版本控制系统: 先说集中式版本控制系统,版本库是集中存放在*服务器的,而干活的时候,用的都是自己的电脑,所以要先从*服务器取得最新的版本,然后开始干活,干完活了, ...

  10. BFS与DFS算法解析

    1)前言 和树的遍历类似,图的遍历也是从图中某点出发,然后按照某种方法对图种所有顶点进行访问,且仅访问一次. 但是图的遍历相对树的遍历更为复杂,因为图中任意顶点都能与其他顶点相邻,所以在图的遍历中必须 ...