因转到人机对话项目上已经有一段时间了,甚是想念solr,所以特地来回顾一下solrcloud中的一些概念,内容不是很全,而且也没有逻辑,就当是备忘吧。

很多分布式系统都会选用zookeeper作为分布式的协调者,solr同样也不例外,在solr中zookeeper主要起到以下作用:

  • 依托于znode,实现集中配置存储
  • 依托于session以及watcher机制实现集群状态检测和提醒
  • overseer和shard leader选举

solr.xml

从我接触solr开始,solr中几个比较经典的配置文件:solrconfig.xml,managed-schema,solr.xml,虽然managed-schema名称变了,但是意义还是差不多,至于这里为什么不详说solrconfig.xmlmanaged-schema,主要是这两个文件实际上和solr core或者索引更加相关一点,和solrcloud并没有什么直接关系。

在早些版本的时候solr.xml主要用于solr core的发现,但是随着solr的发展,现在的solr.xml已经成为solrcloud的属性配置文件,SolrCloud模式下,solr默认从Zookeeper查找solr.xml,若没有则会从solr_home中加载。

<solr>
  <solrcloud>
    <str name="host">${host:}</str>
    <int name="hostPort">${jetty.port:8983}</int>
    <str name="hostContext">${hostContext:solr}</str>
    <int name="zkClientTimeout">${zkClientTimeout:15000}</int>
    <int name="leaderVoteWait">${leaderVoteWait:180000}</int>
    <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
  </solrcloud>

  <shardHandlerFactory name="shardHandlerFactory"
    class="HttpShardHandlerFactory">
    <int name="socketTimeout">${socketTimeout:0}</int>
    <int name="connTimeout">${connTimeout:0}</int>
  </shardHandlerFactory>
</solr>

更多关于solr.xml中属性的讲解,可以参考format-of-solr-xml

其实solr.xml中我们特别要注意一个参数:leaderVoteWait,官网的解释如下:

When SolrCloud is starting up,
how long each Solr node will wait for all known replicas for that shard to be found before assuming that any nodes that haven’t reported are down.

不是太好理解哈,其实就是一个节点等他其它节点投票成为shard_leader的时间,这个时间的设置,最根本就是为了保证数据的安全。

  • 防止脑裂的出现,很可能主节点只是网络震荡,其它副本节点立刻选举新的主,很可能导致多主
  • 防止引入旧数据,当只有两个节点时,node1为主,node2为从,node2宕机,但是node1正在处理写请求,在node2恢复前node1也宕机,如果不设置等待时间,那么node2直接成为主,那么node1将会recovery node2的数据,即老数据。

overseer

overseer为可以看做是solr集群的leader,负责对zookeeper中/clusterstate.json节点的维护,clusterstate.json中维护了整个集群中collection、分片、节点信息,同时非overseer也会注册监听clusterstate.json节点的变动。

overseer节点选举采用基于节点seq号选举的方式,每个节点连接至zookeeper后,都会在/overseer_elect下生成对应的seq号,原本的overseer不在服务时,则seq号大小重新选择最小的seq作为新的overseer。

shard leader

shard leader为collection中每个分片的主,主要负责:

  • 接受写请求
  • 对文档的_version_进行增长,同时落盘写日志。
  • 进行distribut update,即将更新的内容并行转发给其它副本,直到成功响应。

_version_增长其实是乐观锁的一种实现,在solr中的目的主要为了保证集群数据版本的一致性,如果将doc发送给副本时,副本发现该文档版本较低时,是不能允许进行更新的。

shard leader的选举和overseer的选举非常类似,但是需要注意上面所说的脑裂问题。

That's all!