• SolrCloud:依据Solr Wiki的译文


    本文是作者依据Apache Solr Document的译文。翻译不对或者理解不到位的地方欢迎大家指正!谢谢!

    Nodes, Cores, Cluster and Leaders

    Nodes and Cores

    在SolrCloud中,一个node就是一个JVM执行Solr的实例,通常称之为server。每一个Solrcore都能够被当作一个node。不论什么一个node都能够包括一个Solr的实例和多样化的数据在当中。

    Solr core中存储了基于一篇文章中发现的文本内容和字段的索引。

    一个单独的Solr实例能够包括多个core,这些core基于本地的标准彼此间分离。这些core针对不同的用户(在美国的用户或者在加拿大的用户)提供不同的搜索方式,提供私密关注点(某些用户不能訪问某些文档)。提供内容毫不相关或者非常难整合到一起的文档(鞋子的数据和DVD的数据)。

    当你在SolrCloud模式下启动一个新的core时,这个core会自己主动注冊到ZooKeeper其中。这一过程包含创建一个暂时node(假设Solr实例停止这个暂时node就会消失),注冊core和怎样连接core(比如Solr的URL。core名称等)的相关信息。

    client和集群中的nodes能够通过这些信息来决定为了运行请求须要訪问哪些信息。

    新的Solr cores能够通过CoreAdmin来创建和关联collection。新增的云相关參数将在Parameter Reference页面介绍。使用CREATE操作的对象:

    l  collection:core所属于的collection。默认是core的名称

    l  shard:shardid代表core

    l  collection.<param>=<value>:假设一个新的collection被创建就会设置一组<param>=<value>属性。

    比如collection.configName=<configname>用来指出新的collection的config。

    比如:

    curl 'http://localhost:8983/solr/admin/cores?action=CREATE&name=mycore&collection=my_collection&shard=shard2'

    Clusters

    一个cluster是被ZooKeeper管理的一组Solr nodes单独集合。

    当你拥有一个cluster,在不论什么时候你都能够向集群发请求,假设这个请求是公认的。你能够确保这个请求会被作为一个单元来管理和持久化。也就是你不会丢失数据。

    做完操作立即就能够看到状态的更新。集群能够被扩张或者收缩。

    Creating a Cluster

    仅仅要在Zookeeper上注冊的Solr实例超过一个,集群就被创建了。

    Resing a Cluster

    集群包括一个可设置shard数量的參数。

    当你启动solr的时候,通过传递系统參数numShards来设置新集群的shard数量。不管不论什么一个Solr node都必须在第一次启动的时候传递numShards參数。用来自己主动配置shard应该属于哪个实例的一部分。一旦你启动Solr node的数量超过numShards,nodes将会为每一个shard创建replicas。均匀的分布在node上仅仅要他们属于同一个collection。

    想要在你的collection中加入很多其它的core,只启动新的core。你能够在不论什么时候这样做,新的core会在激活之前与当前在shard中的replicas同步。

    假设你採用手动的给一个core赋予一个shard id,你相同能够绕过numShards。

    Shard的数量决定了你的索引数据有多么碎片化,所以在你初始化集群的设置之后你不能更改索引的shard数量。

    只是。你有机会将你的索引分离到多个shard中去。即使你仅仅有一台server。

    你能够在将来扩张到多台server上面。

    完毕这个操作仅仅要遵循下面几点:

    1.      在一台物理server上用多个core来设置你的collection。每一个shard都是那个shard下的leader。

    2.      当你准备好了,你能够通过启动每台新server上所属于那些shard新的replica来移动那些shard到新的server上。

    3.      删除原来server上的shard。ZooKeeper将会把replica升级为那个shard的leader。

    Leaders and Replicas

    leader的概念跟solr replication功能中的master非常相近。Leader负责确保replicas跟存储在leader中的信息保持一致。

    然后使用SolrCloud,你就不只拥有一个master和一到多个slave,反而你非常可能进行分布式查询和多server之间索引的通讯。假设你已经设置Solr的numShards=2,比如你的全部分别在两个shard上。这样的情况下。两个shard都将被视为leader。假设你在初始化两个之后启动了很多其它的node,那这些node就自己主动的被当做这些leader的replica。

    Replica归属于shard是为了他们在第一次增加到集群时保持启动状态。这是由round-robin方式完毕的,除非手动地将带有shardId參数的新node归属给一个shard在启动期间。这个參数通常作为系统的属性。-DshardId=1。新的node须要附上shard的ID值。

    在后期重新启动的时候,每一个node载入到node第一次启动时分配给他的shard中去(无论这个分配是手动的还是自己主动的)。假设一開始被分配为leader的node不可获取了。一个replica能够变成leader。

    思考:

    l  Node A伴随引导參数启动,指向一个独立的ZooKeeper,numShards设置为2.

    l  Node B启动并指向独立的ZooKeeper

    Node A和Node B都是shard,在启动Node A时定义满足2个shard插槽。

    假设我们查看Solr控制台。我们会发现两个node都包括leader(用一个实边的白圆表示)。

    l  Node C启动并指向独立的ZooKeeper

    Node C将会自己主动成为Node A的一个replica。由于我们没有指定他属于不论什么一个其它的shard,并且他也不可以成为一个新的shard由于我们仅仅定义了两个shard并且这两个都被占用了。

    l  Node D启动并指向独立的ZooKeeper

    Node D将会自己主动成为Node B的一个replica,道理与Node C同样。

    进行重新启动,如果Node C在Node A之前重新启动会发生什么?Node C会成为leader,Node A成为了NodeC的replica。

    Shards and IndexingData in SolrCloud

    当你的数据存储在一个node上数量过大,你能够分离这些数据通过创建一或多个shard来存储在section中。

    每个都是逻辑索引的一部分,或者是core,包括了全部node中section的索引。

    Shard是一种以一定数量的server或是node来分离core的方法。

    比如,如果你有一个shard包括各种状态的数据,或是不同种类的,将要被独立的检索,但一般是结合的。

    在SolrCloud之前。Solr提供分布式检索,同意从多个shard运行一个查询。所以运行的这个查询与solr所有索引对立并且查询结果中不会丢失documents。所以通过shard分离core并非Solrcloud独有的概念。然而,分布式方法伴随的一些问题SolrCloud非常有必要进行改进:

    1.      将core分离到shard中是手动的

    2.      不支持分布式索引,那就意味着你须要明白的发送document到特殊的shard中。Sole不能指出document发送到了自己哪一个shard。

    3.      没有负载均衡或者容错,所以假设你想大规模的查询,你须要指出请求发送到哪并且假设一个shard崩溃了就结束了。

    SolrCloud攻克了这些问题。支持分布式的索引和分布式自己主动查询,ZooKeeper提供容错和负载均衡。另外,每一个shard都能够有多个replica用来添加健壮性。

    在SolrCloud中没有master和slaves。

    取代他们的是leaders和replicas。Leaders是自己主动选举的,以first-come-first-served为基本原则,基于ZooKeeper处理描写叙述在http://zookeeper.apache.org/doc/trunk/recipes.html#sc_leaderElection

    假设leader停掉了。他的一个replica就会被自己主动选举为新的leader。每一个node都启动后,他会被分配到拥有最少replica的shard中。假设情况都一样。那就会被分配到shard ID最小的那个shard中。

    当一个document发送到server用于索引时,系统会先推断这台server是一个replica还是leader。

    l  假设server是replica,这个document会转发给leader进行处理。

    l  假设server是leader。SolrCloud决定document应该訪问哪个shard,然后将document转发给那个shard的leader。在这个shard生成这个document的索引。然后标记该索引并转发给其它的replica。

    Document Routing

    当创建你的collection时。Solr具备通过指定router.name參数的collection来实现router的能力。

    假设你使用“compositeId”router,你能够发送带document ID前缀的document,这将用于计算hash,Solr以此决定document发往哪个shard生成索引。这个前缀能够是随意的(不要是shard的名称),但必须始终如一这样solr性能才稳定。

    比如,你想要给客户同步数据。你能够使用客户名或ID作为前缀。

    比如。假设你的客户是IBM。document的ID是“12345”,你最好在document的id值中增加前缀:“IBM!12345”。“!”是一个边界。区分前缀用来决定哪个shard来管理这个document。

    那么在查询的时候。在你的查询语句中通过_route_參数(也就是,q=solr&_route_=IBM!)增加前缀来管理查询到指定的shard。在某些情况下。这样做会增强查询的性能,由于从全部shard查询时网络的潜在因素。

    提示:_route_參数取代shard.keys,shard.keys在Solr以后公布的版本号中弃用。

    这个compositeId支持2级前缀。

    比如:第一个是地区前缀。然后是客户前缀:“USA!IBM!12345”

    还有一种使用场景是假设IBM这个客户有大量的文档,你想要分布他们到多个shard中去。这样的使用方法的语法是:“shard_key/num!document_id”,这个num就是在复合hash使用shrad的key的bit的数量。

    因此“IBM/3!12345”将会在shard key中占用3bit,在唯一的doc id中占29bit。在collection中传播租户超过shard的1/8。

    比如num值为2就会跨1/4的shard传播该document。在查询的时候。直接到指定的shard中用_route_參数查询,将bit的num一起包括在前缀中(也就是q=solr&_route_=IBM/3!)。

    假设你不想影响document怎样存储,就不用在document ID中指定前缀。

    假设你创建了一个collection并且定义在创建的时候定义了“implicit”route,你能够加入定义一个router.field參数,通过各个document的这个field来确定document属于哪个shard。假设在document中丢失这个field指定,document将会被拒绝。

    你相同能够使用_route_參数来命名一个指定的shard。

    Shard Splitting

    当你在SolrCloud中创建一个collection,你要决定shard的初始化个数。可是非常难提前知道你所须要的shard个数,特别是当组织需求发生改变。这成本会非常高当事后发现你的选择是错误的,涉及创建新的core并且又一次生成全部数据的索引。

    Collection API提供拆分shard的能力。眼下同意拆分一个shard为两片。现有的shard保持不变,所以拆分操作实际上将两个切片的数据作为两个新的shard。当你准备好了易后你能够删除老的shard。

    很多其它关于拆分shard的内容在Collection API这一章节。https://cwiki.apache.org/confluence/display/solr/Collections+API

    Ignoring Commits fromClient Application in SolrCloud

    多数情况下我们在SolrCloud模式下执行,client应用不能直接发送提交索引数据的请求。

    当然,你能够通过配置openSearcher=false和soft-commits自己主动提交使近期更新在搜索请求中显示。这能够确保schedule集群中的提交定期发生。确保client应用不会发送直接提交的方案,你能够更新全部client应用的solr索引数据到SolrCloud中。

    然而这样的方法并非一直都可行,因此solr提供IgnoreCommitOptimizeUpdateProcessorFactory,能够同意你不用重构client应用的代码来忽略来自client应用的直接提交或者优化的请求。

    想要激活这个请求处理器,你须要在solrconfig.xml中加入一下配置:

    <updateRequestProcessorChainname="ignore-commit-from-client" default="true">

      <processorclass="solr.IgnoreCommitOptimizeUpdateProcessorFactory">

        <intname="statusCode">200</int>

      </processor>

      <processorclass="solr.LogUpdateProcessorFactory" />

      <processorclass="solr.DistributedUpdateProcessorFactory" />

      <processorclass="solr.RunUpdateProcessorFactory" />

    </updateRequestProcessorChain>

    在上面的样例中。处理器会返回给client200可是会忽略commit/optimize请求。注意你的SolrCloud相同须要接入隐式的处理器。由于这个定制的chain会覆盖默认的chain。

    在以下的这个样例其中,处理器会返回一个403 code异常的定制的错误信息:

    <updateRequestProcessorChainname="ignore-commit-from-client" default="true">

      <processorclass="solr.IgnoreCommitOptimizeUpdateProcessorFactory">

        <intname="statusCode">403</int>

        <str name="responseMessage">Thoushall not issue a commit!</str>

      </processor>

      <processor class="solr.LogUpdateProcessorFactory"/>

      <processorclass="solr.DistributedUpdateProcessorFactory" />

      <processorclass="solr.RunUpdateProcessorFactory" />

    </updateRequestProcessorChain>

    最后,你能够通过下面配置来忽略优化使提交通过:

    <updateRequestProcessorChain name="ignore-optimize-only-from-client-403">

      <processorclass="solr.IgnoreCommitOptimizeUpdateProcessorFactory">

        <str name="responseMessage">Thoushall not issue an optimize, but commits are OK!</str>

        <boolname="ignoreOptimizeOnly">true</bool>

      </processor>

      <processorclass="solr.RunUpdateProcessorFactory" />

    </updateRequestProcessorChain>

    Distributed Requests

    Limiting Which Shardsare Queried

    SolrCloud的一大长处就是能够在各个包括或不包括你要找的数据的shrad间进行分布式查询。

    你能够选择查询所有的数据或者仅仅是部分数据。

    从全部shard查询collection看起来非常熟悉。好像SolrCloud甚至没有发挥作用:

    http://localhost:8983/solr/gettingstarted/select?q=*:*

    你仅仅想从一个shard查询,你能够指定通过那个shard的逻辑ID来指定shard:

    http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=shard1

    假设你想查询一组shard ids,你能够同一时候指定他们:

    http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=shard1,shard2

    上面的两个样例,shard Ids会随机选取对应shard下的replica。

    下面两者任选其一,你能够明白的指定shard中你希望使用的replica:

    http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=localhost:7574/solr/gettingstarted,localhost:8983/solr/gettingstarted

    或者。你能够从一个单独的shard中指定一个replica的集合通过使用符号“|”(为了达到负载均衡的目的):

    http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=localhost:7574/solr/gettingstarted|localhost:7500/solr/gettingstarted

    当然。你能够通过“。”来指定一个shard集合,集合中成员又能够是通过“|”来指定的多个shard。

    比如这个样例其中须要2个shard,第一个是从shard1从随机选取的replica,第二个是通过“|”明白划分的集合:

    http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=shard1,localhost:7574/solr/gettingstarted|localhost:7500/solr/gettingstarted

    Configuring theShardHandlerFactory

    在Solr分布式搜索应用方面你能够直接配置并发和线程池。

    这同意更细粒度的控制,你能够依据你紫的详细要求来调整他的目标。默认的配置有利于延迟的吞吐量。

    能够在solrconfig.xml中来配置标准的处理程序:

    <requestHandler name="standard" class="solr.SearchHandler" default="true">

      <!-- other params go here -->

      <shardHandler class="HttpShardHandlerFactory">

        <int name="socketTimeOut">1000</int>

        <int name="connTimeOut">5000</int>

      </shardHandler>

    </requestHandler>

    Configuring statsCache(Distributed IDF)

    为了计算关联度,须要文档和长期统计。Solr提供四种模式来进行文档的统计计算:

    LocalStatsCache: 这仅仅使用本地术语和文档统计来计算相关性。

    为了从各个shard统一分布的术语。这样的配置的效果非常好。

    假设没有配置<statsCache>,默觉得这项。

    ExactStatsCache: 此实现使用全局值(跨collection)为文档频率。

    ExactSharedStatsCache: 功能与ExactStatsCache非常像。但在同一条件下。对于兴许的请求来说,全局数据是可重用的。

    LRUStatsCache:通过LRU缓存全局统计,在请求之间共享。

    通过在solrconfig.xml中配置<statsCache>来实现。

    比如以下这行Solr使用ExactStatsCache实现:

    <statsCache class="org.apache.solr.search.stats.ExactStatsCache"/>

    Avoiding DistributedDeadlock

    每一个碎片是顶级的查询请求进行子要求其它全部的碎片。

    应注意确保服务的HTTP请求的线程的最大数量是大于从顶级客户和其它碎片的请求的数量。

    假设不是这样的情况。则配置可能会导致分布式死锁。

    比如,死锁可能在两个碎片的情况下发生的,每个与仅仅是一个单一的线程服务的HTTP请求。两个线程能够同一时候接收一个顶层请求,并将请求分为彼此。由于没有很多其它的剩余的线程来服务请求,传入请求将被堵塞,直到其它的等待请求被完毕。但他们不会完毕。由于他们等待的子请求。通过确保Solr配置足够数量的线程来处理,就能够避免死锁。这样。

    Prefer Local Shards

    Solr同意你通过一个可选的布尔型參数命名preferLocalShards表明分布式查询,当一个本地shard可用时,倾向于这个shard的replica。

    换句话说,假设查询包含preferLocalShards= true,然后查询控制器将本地replica运行查询而不是选择随机从整个集群的查询服务。这是实用的,当一个查询请求多个字段或大的字段被返回,由于它避免了在网络上移动大量的数据时,它是在本地。此外,此功能能够是实用的,用于最大限度地降低的影响的问题的副本与退化的性能,由于它降低的可能性,退化的副本将被击中的其它健康的副本。

    最后。它表明这一特征的价值降低集合中添加shard数由于查询控制器将直接查询到大部分的非本地replica的shard。换句话说,这一特征对与一个小数量的shard和很多replica集合的查询优化是很实用的。另外。假设你要求从collection全部nodes的replica中进行负载均衡的查询仅仅能用这个选项。如Solr的CloudSolrClient会做。假设不负载平衡,这个功能能够在集群中引入一个热点。由于查询将不均匀分布在整个集群中。


    https://cwiki.apache.org/confluence/display/solr/SolrCloud

    http://wiki.apache.org/solr/FrontPage

    未完待续...

  • 相关阅读:
    二、java 与 scala相互调用
    Gradle Tips#1-tasks
    Guice 学习(六)使用Provider注入服务( Provider Inject Service)
    C++第15周(春)项目3
    cocos2d-x3.2中怎样优化Cocos2d-X游戏的内存
    jqGrid源代码分析(一)
    OCP-1Z0-051-题目解析-第6题
    PHP连接sql server 2005环境配置
    【剑指offer】替换字符串中的空格
    android 推断Apk是否签名和 签名是否一致
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7344872.html
Copyright © 2020-2023  润新知