设为首页 收藏本站
查看: 1457|回复: 0

[经验分享] Solr In Action 笔记(4) 之 SolrCloud分布式索引基础

[复制链接]

尚未签到

发表于 2015-7-17 07:10:04 | 显示全部楼层 |阅读模式
  Solr In Action 笔记(4) 之 SolrCloud Index 基础
  SolrCloud Index流程研究了两天,还是没有完全搞懂,先简单记下基础的知识,过几天再写个深入点的。先补充上前文来不及写的内容。

1. Solr.xml的重要配置
  Solr.xml的内容如下:



1
2   
3     ${host:}
4     ${jetty.port:8983}
5     ${hostContext:solr}
6     ${zkClientTimeout:15000}
7     ${genericCoreNodeNames:true}
8   
9   
11     ${socketTimeout:0}
12     ${connTimeout:0}
13   
14

  • host , host 指的是Solr节点的IP地址,当Solr节点上线时候,它会向Zookeeper进行注册,注册信息如IP地址就会存储在/clusterstate.json中。这里不但可以直接使用host IP地址如192.168.1.0,也可以使用机器的hostname比如bigdata01。
  • port , port 指的时Solr用来监听的端口,默认是8983,同样它会存储在/clusterstate.json中。
  • Solr Host Context, 指的是Solr.war部署的环境路径,多数情况下不用修改。
  • zookeeper client timeout,上一节讲到过,zookeeper Znode节点变化最大反应时间。
  • core node name, 该节点控制Solr core的命名策略,如果genericCoreNodeNames为true,那么Solr会给core取普通的名字比如,core_node1 ;如果设为true,则会给core取容易辨别的名字,比如带上host信息,比如10.0.1.7:8983_solr_logmill
  • Leader Vote Wait Period:
  该参数并未直接在solr.xml中列出来,SolrCloud的leader和其他replica下线只剩最后一个replica的时候,这个Replica并不会立马选举leader,他会等待一段时间,查看leader是否上线,如果上线了,那么leader仍然还是leader,replica仍然还是replica,如果在这个时间段外leader没有上线,那么replica就变为leader了。这个时间就是Leader Vote Wait Period,它的存在防止了当leader和其他replica下线时候,具有旧的数据的node选为leader。
  比如以下一个例子,一个shard有两个node,X为leader,Y为replica,如果X在线,Y下线,那么X仍然可以接受update请求,SolrCloud仍然继续正常运行,只不过leader X不需要再把数据分发给Y了,Y上线后X只需要简单将数据同步给Y就行(Peer sync 策略)。如果X下线,Y在线,那么这个时候因为没有leader接受update请求以及没有leader转发数据,Y是不会接收到update请求的,所以这个时候的SolrCloud的所以建立是无法进行的,所以一旦X挂了SolrCloud就会进行leader选举,但是我们不能立马让Y变为leader,因为Y的数据相比较X来说是旧的数据。如果Y选举为Leader了,那么后续的update他就会接受,过段时间X上线了,由于Y已经是leader了所以X只能是replica,数据的流向变成了Y转发到X,这个时候就发现了奇怪的现象就是X中有部分数据新于Y(Y当选为leader前的数据),Y中有部分数据也新于X(Y当选为leader后的数据),这个时候就需要启动Snapshot replication 策略进行数据复原了,比较麻烦。如果设置了leaderVoteWait 那么X下线后,Y会等待leaderVoteWait时间,这个时间内update操作都是失败的,如果在这时间内X上线了,那么X立马恢复leader状态继续工作,否则就会Y就会变成leader。
  要改善这种情况,可以增加shard和replica的数量,较少leader和replica同时挂掉的可能性。


  • zkHost,同样没有出现在上面的solr.xml上,它可以在solr.xml的zkHost配置中设置zookeepr集群信息比如192.168.0.1:2181,192.168.0.2:2181表示两个zookeeper组成一个zookeeper集群。

2. SolrCloud的分布式建索引

2.1 Document的Hash
  建好的SolrCloud集群每一个shard都会有一个Hash区间,当Document进行update的时候,SolrCloud就会计算这个Document的Hash值,然后根据该值和shard的hash区间来判断这个document应该发往哪个shard,所以首先让我们先来学习下SolrCloud的hash算法。Solr使用document route组件来进行document的分发。目前Solr有两个DocRouter类的子类CompositeIdRouter(Solr默认采用的)类和ImplicitDocRouter类,当然我们也可以通过继承DocRouter来定制化我们的document route组件。
       之前我们学习过,当Solr Shard建立时候,Solr会给每一个shard分配32bit的hash值的区间,比如SolrCloud有两个shard分别为A,B,那么A的hash值区间就为 80000000-ffffffff ,B的hash值区间为0-7fffffff  。默认的CompositeIdRouter hash策略会根据document ID计算出唯一的Hash值,并判断该值在那个shard的hash区间内。
  SolrCloud对于Hash值的获取提出了以下几个要求:


  • hash计算速度必须快,因为hash计算是分布式建索引的第一步,SolrCloud不可能在这一不上花很多时间。
  • hash值必须能均匀的分布于每一个shard,如果有一个shard的document数量大于另一个shard,那么在查询的时候前一个shard所花的时间就会大于后一个,SolrCloud的查询是先分后汇总的过程,也就是说最后每一个shard查询完毕才算完毕,所以SolrCloud的查询速度是由最慢的shard的查询速度决定的。我们有理由让SolrCloud做好充分的负载均衡。
  基于以上两点,SolrCloud采用了MurmurHash 算法,那么让我们先来看下该算法的代码,说实话这个代码我真没看懂,等下次独立写个章节学习下MurmurHash算法吧。



  1 /** Returns the MurmurHash3_x86_32 hash of the UTF-8 bytes of the String without actually encoding
  2    * the string to a temporary buffer.  This is more than 2x faster than hashing the result
  3    * of String.getBytes().
  4    */
  5   public static int murmurhash3_x86_32(CharSequence data, int offset, int len, int seed) {
  6
  7     final int c1 = 0xcc9e2d51;
  8     final int c2 = 0x1b873593;
  9
10     int h1 = seed;
11
12     int pos = offset;
13     int end = offset + len;
14     int k1 = 0;
15     int k2 = 0;
16     int shift = 0;
17     int bits = 0;
18     int nBytes = 0;   // length in UTF8 bytes
19
20
21     while (pos < end) {
22       int code = data.charAt(pos++);
23       if (code < 0x80) {
24         k2 = code;
25         bits = 8;
26
27         /***
28          // optimized ascii implementation (currently slower!!! code size?)
29          if (shift == 24) {
30          k1 = k1 | (code > 17);  // ROTL32(k1,15);
34          k1 *= c2;
35
36          h1 ^= k1;
37          h1 = (h1 >> 19);  // ROTL32(h1,13);
38          h1 = h1*5+0xe6546b64;
39
40          shift = 0;
41          nBytes += 4;
42          k1 = 0;
43          } else {
44          k1 |= code > 6))
53             | ((0x80 | (code & 0x3F))  0xDFFF || pos>=end) {
57         // we check for pos>=end to encode an unpaired surrogate as 3 bytes.
58         k2 = (0xE0 | (code >> 12))
59             | ((0x80 | ((code >> 6) & 0x3F)) > 12) & 0x3F))) > 6) & 0x3F)))  17);  // ROTL32(k1,15);
86         k1 *= c2;
87
88         h1 ^= k1;
89         h1 = (h1 >> 19);  // ROTL32(h1,13);
90         h1 = h1*5+0xe6546b64;
91
92         shift -= 32;
93         // unfortunately, java won't let you shift 32 bits off, so we need to check for 0
94         if (shift != 0) {
95           k1 = k2 >>> (bits-shift);   // bits used == bits - newshift
96         } else {
97           k1 = 0;
98         }
99         nBytes += 4;
100       }
101
102     } // inner
103
104     // handle tail
105     if (shift > 0) {
106       nBytes += shift >> 3;
107       k1 *= c1;
108       k1 = (k1 >> 17);  // ROTL32(k1,15);
109       k1 *= c2;
110       h1 ^= k1;
111     }
112
113     // finalization
114     h1 ^= nBytes;
115
116     // fmix(h1);
117     h1 ^= h1 >>> 16;
118     h1 *= 0x85ebca6b;
119     h1 ^= h1 >>> 13;
120     h1 *= 0xc2b2ae35;
121     h1 ^= h1 >>> 16;
122
123     return h1;
124   }
  最后我们再简单地学习下hash计算的源码吧:


  • SolrCloud 利用CompositeIdRouter.sliceHash来计算document的hash



1   public int sliceHash(String id, SolrInputDocument doc, SolrParams params, DocCollection collection) {
2     String shardFieldName = getRouteField(collection);
3     if (shardFieldName != null && doc != null) {
4       Object o = doc.getFieldValue(shardFieldName);
5       if (o == null)
6         throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No value for :" + shardFieldName + ". Unable to identify shard");
7       id = o.toString();
8     }
9     if (id.indexOf(SEPARATOR) < 0) {
10       return Hash.murmurhash3_x86_32(id, 0, id.length(), 0);
11     }
12
13     return new KeyParser(id).getHash();
14   }

  • 根据计算出来的hash值计算应该将document发往哪些节点



1 public Collection getSearchSlicesSingle(String shardKey, SolrParams params, DocCollection collection) {
2     if (shardKey == null) {
3       // search across whole collection
4       // TODO: this may need modification in the future when shard splitting could cause an overlap
5       return collection.getActiveSlices();
6     }
7     String id = shardKey;
8
9     if (shardKey.indexOf(SEPARATOR) < 0) {
10       // shardKey is a simple id, so don't do a range
11       return Collections.singletonList(hashToSlice(Hash.murmurhash3_x86_32(id, 0, id.length(), 0), collection));
12     }
13
14     Range completeRange = new KeyParser(id).getRange();
15
16     List targetSlices = new ArrayList(1);
17     for (Slice slice : collection.getActiveSlices()) {
18       Range range = slice.getRange();
19       if (range != null && range.overlaps(completeRange)) {
20         targetSlices.add(slice);
21       }
22     }
23
24     return targetSlices;
25   }

  • 最后,看下SolrCloud是怎么划分shard的hash值区间的。以下代码需要注意几点,


    • boolean round = rangeStep >= (1 = (1

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-87393-1-1.html 上篇帖子: Windows下 建立solr时 出现 问题解答(转 ) 下篇帖子: Ubuntu 14.04下安装solr 4.10以及集成Mysql方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表