??xml version="1.0" encoding="utf-8" standalone="yes"?>国精品**一区二区三区在线蜜桃,成人成人成人在线视频,国产三级视频在线看http://www.aygfsteel.com/wangxinsh55/category/52093.htmlzh-cnMon, 09 Jul 2012 08:40:38 GMTMon, 09 Jul 2012 08:40:38 GMT60Searching http://www.aygfsteel.com/wangxinsh55/archive/2012/07/09/382584.htmlSIMONESIMONEMon, 09 Jul 2012 02:29:00 GMThttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/09/382584.htmlhttp://www.aygfsteel.com/wangxinsh55/comments/382584.htmlhttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/09/382584.html#Feedback0http://www.aygfsteel.com/wangxinsh55/comments/commentRss/382584.htmlhttp://www.aygfsteel.com/wangxinsh55/services/trackbacks/382584.htmlhttp://beijingit.blog.163.com/blog/static/29639092201212145312231/
Solr's XML response format
statusQ始lؓ0。除非查询发生错误,返回错误码
QTime: 查询耗时。由于有内部~存Q所以两个相同的查询的QTime是相同的Q但是查询速度更快
numFound: d查询到的l果?br />start:查询q回l果集的起始?br />maxScore:查询l果中所有数据的最高得分,如果查询h的flh参数没有指定score,那么q回l果中doc中是不会有得分字D늚
q回的结果中的每一个doc对应的就是一条查询出来的数据Q一一对应于烦引中的documentQ数据类型用solr中的基本数据cd呈现Q如果是多值字D,则以排序的多个字D呈玎ͼ每个字段同样是简单类型?br />result节点之后可能会有facet highlight{?br />
Parsing the URL
url中的文本必须是utf-8~码Q?br />
Request handlers
在solrconfig.xml中配|,允许配置两g事情1.配置默认的参数和一些不会改变的帔R?。注册solr查询lgQ例如faceting highlighting{?br />在实际应用中针对每一U类型的查询配置单独的request handlerQ这样做的好处是可以通过配置修改参数Qƈ且对于查询统计提供更好的_度
qt="handler name";

<requestHandler name="bands" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">none</str>
<int name="rows">20</int>
</lst>
<lst name="appends">
<str name="fq">a_type:group</str>
</lst>
<lst name="invariants">
<str name="facet">false</str>
</lst>
</requestHandler>
1。defaults: 默认参数讄Q请求时参数会覆盖此?br />2。appends:可以讄多次的参数。像fq,除了h参数中指定的同时此g会被讄?br />3.invariants:此值是帔R|q且不会被覆盖(此值用于安全目?.
4.first-components, components, last-components:注册当前handler可能会用到的handler。默认情况下已经注册了一些组Ӟ例如faceting highlighting{。设|first-components和last-components会分别前|或q加到这个列表中Q设|?components会完全覆盖默认的列表讄?br />
Query parameters
对于booleancd的参敎ͼ真值可以是true,on,yesQ假值可以ؓfalse,off,no.

Search criteria related parameters
q: query的简写,指查询字W串Q查询语法用defType的设?/div>
defTypeQ默认是lucene,大多数情况下会使用dismax 或edismax
dismax和edismax支持许多增强的功能,更少的语法限制可以防止用户得C希望的结果或者是不小心用lucene语法时提C出错?/div>
fqQ用h询时qo条g的范_cM于sql中的whereQ此参数不会影响得分(scoring),此参数可以重复?/div>
qtQ查询类型。就是前Ҏ到的request handler,一U方法就是用/aaa来命名,然后可以在url中用aaa?....来访?/div>
Result pagination related parameters
startQ默认是0Q返回结果集中的起始位置Q如果此值大于结果集的LQ那么将不会q回MdocumentQ但是solr也不认ؓq是一个错?/div>
rowsQ默认是10Q?/div>
Output related parameters
flQ返回的字段列表Q值用Q? 或空格分|使用*W号q回所有字D但是不包括scoreQ要惌回此字段必须d
sortQ排序字D,例如r_name asc,score descQ默认是score desc,也可以用functionq行排序
wtQ返回的格式Q在solrconfig.xml中定义,目前支持的有xmlQ默认的Q,json,phthon,php,phps,ruby,javabin,csv,xslt,velocity.
versionQ不是很有用?/div>
Diagnostic related parameters
用于开发调试,
indentQboolean|用于使输出更Ҏ阅读?/div>
debugQueryQ?如果为true,那么接下来的查询l果会有<lst name="debug">的调试信息,其中包括转换的查询字W串Qscore的计,以及处理faceting所耗时 _explainOtherQ如果想知道Z么某个document没有被匹配,或者得分不高,那么可以讄此值来q行查询Q例?id:"Release:12345",q样debugQuery的输定会包含W一个匹配此查询的结果?/div>
echoHandlerQ如果ؓtrueQ将输出与solr request handler匚w的java cd?/div>
echoParamsQ?控制是否在response header中包含查询参敎ͼ可以用来调试url~码q的查询字符Ԍnone用Q默认的request handler讄此属性ؓexplicit,可以使用all来包含所有request handler中的配置参数Q除了url中的?/div>
timeAllowedQ用来指定查询的最长时_以毫Uؓ单位?/div>
Query parsers and local-params
solr中默认的query parser是lucene,
Query syntax (the lucene query parser)
solr完整的查询语法是实现的lucene query parser.
lucene不支持查询所有文档,solr使用*:*可以查询所有文?/div>
mandatory(强制性)prohibited(止Q和优化
mandatoryQ?/strong>+aaa:只匹配包含aaa?nbsp;
prohibitedQ?/strong> -aaaQ匹配所有的,但是除了包含aaa?/span>
optional: aaa 可选的
如果查询语句臛_有一个mandatoryQ那么optional是可选的Q但是他有一个很有用的功能就是文得分,会匹配更多的Q也是说文档中可以包含optional也可以没有)
如果查询语句没有mandatory,那么臛_要匹配一个optionalQ也是说文档中必须要包含optionalQ?/div>
optional也可以指定一个确定的数或癑ֈ比来q行匚w或不匚wQ这L话就必须用dismax的min-should-match功能?/div>
solr4不再用这U方?/div>
Boolean operators
AND OR NOT
如果没有明确标记为prohibitedQ那么AND or && 两边的操作会被认为是mandatoryQ例如aaa AND bbb {同?aaa +bbb
同样的,OR操作会被认ؓ是optional?NOT{同于prohibited
Sub-queries
(aaa AND bbb) OR (cccc || ddd )
Limitations of prohibited clauses is sub-queries
lucene 不支持纯_的否定查询Q例?Smashing -Pumpkins。solr对luceneq行增强来支持这U查询,但是仅仅只能在顶层查询,看下面这个例?Smashing (-Pumpkins),q个查询是在问:那个document包含Smashing或者不包含pumpkins吗?无论怎样Q这样写都不会有正确l果 的。正的写法应该是让子表辑ּ只包含否定语句,q且d查询所有的查询“*:*"像q样Smashing (-Pumpkins *:*)Q这个限制只能应用在edismax查询中?/div>
Field qualifier
member_name:aaa  
+member_name:aaa +member_name:bbb 也可以用写Ş?member_name:(+aaa +bbb),圆括号代表的是子查询Q这个查询的目标字段都是同一个?/div>
Wildcard queries
要注意的几点
1. 不要对包含通配W的查询字符串应用文本分析,甚至是小写,假如你想查找Sma开头的单词Qƈ且烦引中的字D늱型包含小写,那么应该用sma*而不能用 Sma*。这是SOLR-219中的一个缺炏V此外,假如你要使用的字D|应用了文本分析的Q那么smashing*是不会匹配到Smashing的,?为文本分析会把Smash转换为smashQ因此,不要应用文本分析?/div>
2.通配W查询是很慢的,使用ReversedWildcardFilterFactory可以提高很多Q最坏的情况是在单词两端应用*受?/div>
3.起始通配W应?L话结果会q回错误Q除非?span style="line-height: 22px;">ReversedWildcardFilterFactory?/span>
例子Qsma* ,sma*ing, sma??*(臛_后边跟两个或者更?
每一个匹配项都会得到相同的scoreQ不他使用那种查询模式。lucene以牺牲性能来支持多UscoreQ不q得q行一些设|让solr来完?/div>
有一个问题只是一?号会怎么样呢Q结果取决于schema文g中是否有M一个字D늱型,即索引链中没有应用一个ReversedWildcardFilterFactory,*号都会应用所有fieldQ如果不是这P那么会得C?#8221;不支持前导通配W?#8220;的错误?/div>
Fuzzy queries
例子: Smashing~
波浪L于模p查询,可以通过修改怼度(0-1Q默?.5Q来q行查询如:Smashing~0.7
像使用通配W查询一P如果要用模p查询就应该查询字W串转ؓ写?/div>
Range queries
例如Qa_type:2 AND a_begin_date:[1990-01-01T00:00:00.000Z TO 1999-02-02T22:59:59.999Z] 
"[]"包含两端的|”{}“不包含两端的|solr3中,要么都包含,要么都不包含。solr4两个都允许?/div>
也可以用a_duration:[3000 TO *] 此处"*"L方式lucene是不支持?/div>
范围查询也可用于文本字段Q不常用Q,此时所应用的烦引字D只能有一个term 例如:somefield:([B TO C] -C)
Date math
solr 扩展了lucene原始的查询{换器Qdate应用范围查询时再加方便,像数字计算一栗另外还可以通过”NOW“(_到毫U)来获取当前时_ 其语法还提供了补充,如减法,四舍五入Ҏ不同的粒度,如年Q秒{。操作可以链接到一Pq且从左向右执行Q不允许有空根{例
r_event_date:[* TO NOW-2YEAR]
因ؓNOW是精到毫秒U的Q所以如果只是想到天的话可以?#8221;/"向下舍入Q此W号只会向下舍入Q?/div>
r_event_date:[* To NOW/DAY-2YEAR]
可选的单位有YEAR,MONTH,DAY,DATE(与DAY相同)QHOUR,MINUTE,SECOND,MILISECOND,MILIT(与MILISECOND相同)
DateMath 不只是用于查询,同样用于索引Q用于烦引时应该使用正确的精度,否则_到毫U的话不仅占用更多的磁盘空_而且也会降低查询速度Q常用的索引日期字段 是这L<field name="indexedAt" type="tdate" default="NOW/SECOND" />
Score boosting
通过d乘数可以修改查询字符串中的条文A献给最l得分的E度Q这叫做增强Q??之间的值减得分,大于1的值增加得分,
例:a_member_name:Billy^2 OR Smashing 或?+Billy Bob Corgan^0.7

Existence (and non-existence) queries
如果要查询某个字D下的所有文可以这样a_name:[* TO * ]
也可以查询某个字D下没有值的所有文档,-a_name:[* TO *]
Escaping special characters
+ - && || ! () {} [] ^ '' ~ * ? : \ 要想使用q些字符的原意可以用"\" 例id:artist\:aaa 通过双引号也可以实现同样效果id:"artist:aaa"
如果使用solrj与solr交互Q可以用ClientUtils.escapeQueryChars()q行转义
The Dismax query parser
dismax 是lucene的DisjunctionMaxQuery之后的名?q个query parser对于scoring 有直接关p?
edismax中的e是extended的意思,q个parser是在solr3.1中增加的Q他由dismax的演化而来?/div>
Searching multiple fields
<str name="qf">a_name a_alias^0.7 a_member_name^0.4</str>如果x据scoring排序Q可以将scoring讑֤一点,q样׃排在最上边
?于schema中定义的stop words的效果,如果qf指定的字D中其中一些字D用stop words而别一些没有用,那么查询stop words不会返回Q何结果。edismax把查询字W串中的stop words认ؓ都是可选的Q也是可有可无Q,除非查询字符串中全部使用stop wordsQ用dismax 你可以确保查询字D中的查询分杉Kqo出相同的stop words倹{?/div>
Limited query syntax
edismax首先会把用户的查询用lucene支持的所有语法进行{换,q行两次调整Q如果{换失败,它接下来会蟩到原始的dismax的语法规则?/div>
or和andq有布尔q算可以用小写Ş式,q且支持U否定子查询?/div>
如果使用dismaxQ对于terms,phrase它都会限制可以用的语法,q且使用+?Q而不是AND,OR,&&,||Q来Ҏ文应用强制应用和止应用?/div>
q有是是否需要对相关查询的有效性进行{义。ؓ了不触发错误Q除非用edismax否则必ȝ码来处理某些H出的问题?/div>
Min-should-match
lucene query parser有两U操作,一是默认操作是or,也就是说只要有一个条文匹配就可以Q另一个就是用AND来所有条文匹配。它不能使用+?q行明确?定。这是两U极端的情况。dismax有一个方法叫min-should-mathc,它用来指定多条文必d配,或者有多少个是止的。这个值可以设 |ؓ癑ֈ比或定的数倹{在配置文g中可以通过查询参数“mm"来设|。语法也比较单?/div>
Basic rules
mm参数的四个基本语法如下:
1Q?  必须匚w3个条文,其余的是可选的?/div>
2Q?2 2个条文是可选的Q其余的是必ȝ?/div>
3Q?6% 66%的条文是必须的,其余的是可选的?/div>
4Q?25% 25%的条文是可选的Q其余的是必ȝ?/div>
?意:-是对必须的除以可选的的逆向取|它在q儿的定义其实没有否定多的意思。虽?5%?25%看v来一P但是在rounding的时候就不一?了,例如有五个查询条文,W一个条文需要三ơ,W二个条文需要四ơ,q也p明如果要q行rounding计算Q那么就需要反转标志再?00减去此倹{?/div>
另外两点Q?.如果mm的值是一个确定的值nQ但是查询的条文数小于此|那么n会减到查询l果中的条文L。例如mmgؓ-5但是查询中的条文一共只?个,所以结果就是所有条文都是可选的?/div>
2.C一?不管是luceneq是solrQ在所有查询中Q必L一个条文是匚w的,即所有条文都是可选的Q?/div>
Multiple rules
?以空格分隔的一个串Q例如number<basicmm Q意思是说如果条文的数量大于number, 那么应用basicmm规则。(规则的从左向叛_序排列的Q。只有最右端的规则才会被计算Q执行的规则肯定是满x大的条文L。如果不满M一个规 则,那么所有条文都是必ȝ。例如:
2<75% 9<-3 q个规则的意思是_如果条文L大于9Q那么其?个是可选的Q其它的都是必须的。如果条文L大于2Q那?5%是必ȝ。其它情况(也就是条文L只有1个或2个)那么所有条文都是必ȝQ这是默认)?/div>
What to choose
Min-should-match的简单配|是使所有terms都是可选的。它的效果相当于默认的Lucene query parser 的OR操作Q默认是0%。反q来的另一U极端就是所有terms都是必须的,q个q当于AND操作Q就?00%?/span>
?意:你可能想让所有terms都匹配,实事上这也是默认讄。但是如果有一个term没有扑ֈQ那么不会返回Q何结果。当你设|一些terms是可选的?候,匚w的结果会以score排序Q包含最多terms的结果会排在剙。还有一Ҏ是在没有返回结果的时候进行二ơ查询,但是solr是不支持的,?q可以通过客户端很Ҏ的实现?/span>

A default search
dismax 查询支持一个默认查询。也是用户没有指定q的时候。参数是q.alt。例?lt;str name="q.alt">*:*</str>。这个参数通常讄在solrconfig.xml文g的request handler中来查询所有文档。在faceting中会使用到这个设|。如果不惌回Q何结果可以设|ؓ-*:*;

Filtering
filter查询不会影响scoringQ不像用h询。要d一个filterQ只要用fq参数。用filter可以改进执行效率Q因为每一个filter查询都会~存在solr的filter cache中ƈ且执行速度相当快?/span>
solr 3.4通过本地参数cache来控制是否启用缓?/span>

Sorting
使用sort参数Q默认是score desc。例Qsort=a_type desc,score desc
q行排序字段的数值类型必Lsingle valued,indexed,q且是not-tokenized?/div>
另外solrq支持function query Q它通常用来计算I间地理位置的距,或现在与字段值的旉差等。例sort=sub(begin_time,end_time) desc


SIMONE 2012-07-09 10:29 发表评论
]]>深入剖析SolrCloudQ四Q?/title><link>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382220.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Wed, 04 Jul 2012 10:42:00 GMT</pubDate><guid>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382220.html</guid><wfw:comment>http://www.aygfsteel.com/wangxinsh55/comments/382220.html</wfw:comment><comments>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/wangxinsh55/comments/commentRss/382220.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/wangxinsh55/services/trackbacks/382220.html</trackback:ping><description><![CDATA[     摘要: http://www.cnblogs.com/phinecos/archive/2012/02/29/2372682.html      在上一中介绍了连接Zookeeper集群的方法,q一将围绕一个有的话题---来展开Q这是ReplicationQ烦引复ӞQ关于Solr Replication的详l介l,可以参考http://wiki.apache.org...  <a href='http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382220.html'>阅读全文</a><img src ="http://www.aygfsteel.com/wangxinsh55/aggbug/382220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wangxinsh55/" target="_blank">SIMONE</a> 2012-07-04 18:42 <a href="http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Phinecos(z庭散h) 专注于开源技术的研究与应?深入剖析SolrCloudQ三Q?http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382219.htmlSIMONESIMONEWed, 04 Jul 2012 10:41:00 GMThttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382219.htmlhttp://www.aygfsteel.com/wangxinsh55/comments/382219.htmlhttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382219.html#Feedback0http://www.aygfsteel.com/wangxinsh55/comments/commentRss/382219.htmlhttp://www.aygfsteel.com/wangxinsh55/services/trackbacks/382219.htmlhttp://www.cnblogs.com/phinecos/archive/2012/02/16/2354834.html

?/span>上一?/span>中介l了SolrCloud的第一个模?/span>---构徏理solr集群状态信息的zookeeper集群。当我们?/span>solr服务器启动时拥有了这样一?/span>Zookeeper集群后,昄我们需要连接到Zookeeper集群的方便手D,在这一中我将?/span>Zookeeper客户端相关的各个装c进行分析?/span>

SolrZkClientcLSolr服务器用来与Zookeeper集群q行通信的接口类Q它包含的主要组件有Q?/span>

  private ConnectionManager connManager;
  private volatile SolrZooKeeper keeper;
  private ZkCmdExecutor zkCmdExecutor = new ZkCmdExecutor();

    其中ConnectionManager?/span>Watcher的实现类Q主要负责对客户端与Zookeeper集群之间q接的状态变化信息进行响应,关于Watcher的详l介l,可以参?/span>http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatchesQ?/span>

SolrZooKeepercL一个包装类Q没有实际意义,ZkCmdExecutorcL负责在连接失败的情况下,重试某种操作特定ơ数Q具体的操作?/span>ZkOperationq个抽象cȝ具体实现子类Q其executeҎ中包含了具体操作步骤Q这些操作包括新Z?/span>Znode节点Q读?/span>Znode节点数据Q创?/span>Znode路径Q删?/span>Znode节点{?/span>Zookeeper操作?/span>

首先来看它的构造函敎ͼ先创?/span>ConnectionManager对象来响应两端之间的状态变化信息,然后ZkClientConnectionStrategycL一个连接策略抽象类Q它包含q接和重q两U策略,q且采用模板Ҏ模式Q具体的实现是通过静态篏不类ZkUpdate来实现的Q?/span>DefaultConnectionStrategy是它的一个实现子c,它覆写了connect?/span>reconnect两个q接{略Ҏ?/span>

复制代码
  public SolrZkClient(String zkServerAddress, int zkClientTimeout,
      ZkClientConnectionStrategy strat, final OnReconnect onReconnect, int clientConnectTimeout) throws InterruptedException,
      TimeoutException, IOException {
    connManager = new ConnectionManager("ZooKeeperConnection Watcher:"
        + zkServerAddress, this, zkServerAddress, zkClientTimeout, strat, onReconnect);
    strat.connect(zkServerAddress, zkClientTimeout, connManager,
        new ZkUpdate() {
          @Override
          public void update(SolrZooKeeper zooKeeper) {
            SolrZooKeeper oldKeeper = keeper;
            keeper = zooKeeper;
            if (oldKeeper != null) {
              try {
                oldKeeper.close();
              } catch (InterruptedException e) {
                // Restore the interrupted status
                Thread.currentThread().interrupt();
                log.error("", e);
                throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
                    "", e);
              }
            }
          }
        });
    connManager.waitForConnected(clientConnectTimeout);
    numOpens.incrementAndGet();
  }
复制代码

值得注意的是Q构造函C生成?/span>ZkUpdate匿名cd象,它的updateҎ会被调用Q?/span>

在这个方法里Q会首先已有的老的SolrZooKeeperg关闭掉,然后攄上一个新?/span>SolrZooKeeper。做好这些准备工作以后,׃去连?/span>Zookeeper服务器集,

connManager.waitForConnected(clientConnectTimeout);//q接zk服务器集,默认30U超时时?/span>

其实具体的连接动作是new SolrZooKeeper(serverAddress, timeout, watcher)引发的,上面那句代码只是在等待指定时_看是否已l连接上?/span>

如果q接Zookeeper服务器集成功,那么可以进?/span>Zookeeper的常规操作了Q?/span>

1Q?nbsp;是否已经q接

  public boolean isConnected() {
    return keeper != null && keeper.getState() == ZooKeeper.States.CONNECTED;
  }

2Q?nbsp;是否存在某个路径?/span>Znode

复制代码
  public Stat exists(final String path, final Watcher watcher, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (retryOnConnLoss) {
      return zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public Stat execute() throws KeeperException, InterruptedException {
          return keeper.exists(path, watcher);
        }
      });
    } else {
      return keeper.exists(path, watcher);
    }
  }
复制代码

3Q?nbsp;创徏一?/span>Znode节点

复制代码
  public String create(final String path, final byte data[], final List<ACL> acl, final CreateMode createMode, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (retryOnConnLoss) {
      return zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public String execute() throws KeeperException, InterruptedException {
          return keeper.create(path, data, acl, createMode);
        }
      });
    } else {
      return keeper.create(path, data, acl, createMode);
    }
  }
复制代码

4Q?nbsp;获取指定路径下的孩子Znode节点

复制代码
  public List<String> getChildren(final String path, final Watcher watcher, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (retryOnConnLoss) {
      return zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public List<String> execute() throws KeeperException, InterruptedException {
          return keeper.getChildren(path, watcher);
        }
      });
    } else {
      return keeper.getChildren(path, watcher);
    }
  }
复制代码

5Q?nbsp;获取指定Znode上附加的数据

复制代码
  public byte[] getData(final String path, final Watcher watcher, final Stat stat, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (retryOnConnLoss) {
      return zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public byte[] execute() throws KeeperException, InterruptedException {
          return keeper.getData(path, watcher, stat);
        }
      });
    } else {
      return keeper.getData(path, watcher, stat);
    }
  }
复制代码

6Q?nbsp;在指?/span>Znode上设|数?/span>

复制代码
  public Stat setData(final String path, final byte data[], final int version, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (retryOnConnLoss) {
      return zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public Stat execute() throws KeeperException, InterruptedException {
          return keeper.setData(path, data, version);
        }
      });
    } else {
      return keeper.setData(path, data, version);
    }
  }
复制代码

7Q?nbsp;创徏路径

复制代码
  public void makePath(String path, byte[] data, CreateMode createMode, Watcher watcher, boolean failOnExists, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    if (log.isInfoEnabled()) {
      log.info("makePath: " + path);
    }
    boolean retry = true;
    
    if (path.startsWith("/")) {
      path = path.substring(1, path.length());
    }
    String[] paths = path.split("/");
    StringBuilder sbPath = new StringBuilder();
    for (int i = 0; i < paths.length; i++) {
      byte[] bytes = null;
      String pathPiece = paths[i];
      sbPath.append("/" + pathPiece);
      final String currentPath = sbPath.toString();
      Object exists = exists(currentPath, watcher, retryOnConnLoss);
      if (exists == null || ((i == paths.length -1) && failOnExists)) {
        CreateMode mode = CreateMode.PERSISTENT;
        if (i == paths.length - 1) {
          mode = createMode;
          bytes = data;
          if (!retryOnConnLoss) retry = false;
        }
        try {
          if (retry) {
            final CreateMode finalMode = mode;
            final byte[] finalBytes = bytes;
            zkCmdExecutor.retryOperation(new ZkOperation() {
              @Override
              public Object execute() throws KeeperException, InterruptedException {
                keeper.create(currentPath, finalBytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, finalMode);
                return null;
              }
            });
          } else {
            keeper.create(currentPath, bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
          }
        } catch (NodeExistsException e) {
          
          if (!failOnExists) {
            // TODO: version ? for now, don't worry about race
            setData(currentPath, data, -1, retryOnConnLoss);
            // set new watch
            exists(currentPath, watcher, retryOnConnLoss);
            return;
          }
          
          // ignore unless it's the last node in the path
          if (i == paths.length - 1) {
            throw e;
          }
        }
        if(i == paths.length -1) {
          // set new watch
          exists(currentPath, watcher, retryOnConnLoss);
        }
      } else if (i == paths.length - 1) {
        // TODO: version ? for now, don't worry about race
        setData(currentPath, data, -1, retryOnConnLoss);
        // set new watch
        exists(currentPath, watcher, retryOnConnLoss);
      }
    }
  }
复制代码

8Q?nbsp;删除指定Znode

复制代码
  public void delete(final String path, final int version, boolean retryOnConnLoss) throws InterruptedException, KeeperException {
    if (retryOnConnLoss) {
      zkCmdExecutor.retryOperation(new ZkOperation() {
        @Override
        public Stat execute() throws KeeperException, InterruptedException {
          keeper.delete(path, version);
          return null;
        }
      });
    } else {
      keeper.delete(path, version);
    }
  }
复制代码

         我们再回q头来看?/span>ConnectionManagercL如何响应两端的连接状态信息的变化的,它最重要的方法是processҎQ当它被触发回调Ӟ会从WatchedEvent参数中得C件的各种状态信息,比如q接成功Q会话过期(此时需要进行重q)Q连接断开{?/span>

复制代码
  public synchronized void process(WatchedEvent event) {
    if (log.isInfoEnabled()) {
      log.info("Watcher " + this + " name:" + name + " got event " + event + " path:" + event.getPath() + " type:" + event.getType());
    }

    state = event.getState();
    if (state == KeeperState.SyncConnected) {
      connected = true;
      clientConnected.countDown();
    } else if (state == KeeperState.Expired) {
      connected = false;
      log.info("Attempting to reconnect to recover relationship with ZooKeeper...");
      //试重新q接zk服务?/span>
      try {
        connectionStrategy.reconnect(zkServerAddress, zkClientTimeout, this,
            new ZkClientConnectionStrategy.ZkUpdate() {
              @Override
              public void update(SolrZooKeeper keeper) throws InterruptedException, TimeoutException, IOException {
                synchronized (connectionStrategy) {
                  waitForConnected(SolrZkClient.DEFAULT_CLIENT_CONNECT_TIMEOUT);
                  client.updateKeeper(keeper);
                  if (onReconnect != null) {
                    onReconnect.command();
                  }
                  synchronized (ConnectionManager.this) {
                    ConnectionManager.this.connected = true;
                  }
                }
                
              }
            });
      } catch (Exception e) {
        SolrException.log(log, "", e);
      }
      log.info("Connected:" + connected);
    } else if (state == KeeperState.Disconnected) {
      connected = false;
    } else {
      connected = false;
    }
    notifyAll();
  }
复制代码

 

 



SIMONE 2012-07-04 18:41 发表评论
]]> Phinecos(z庭散h) 专注于开源技术的研究与应?深入剖析SolrCloudQ一Q?http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382217.htmlSIMONESIMONEWed, 04 Jul 2012 10:40:00 GMThttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382217.htmlhttp://www.aygfsteel.com/wangxinsh55/comments/382217.htmlhttp://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382217.html#Feedback0http://www.aygfsteel.com/wangxinsh55/comments/commentRss/382217.htmlhttp://www.aygfsteel.com/wangxinsh55/services/trackbacks/382217.htmlhttp://www.cnblogs.com/phinecos/archive/2012/02/10/2345634.html


    SolrCloud是基?/span>Solr?/span>Zookeeper的分布式搜烦ҎQ是正在开发中?/span>Solr4.0的核心组件之一Q它的主要思想是?/span>Zookeeper作ؓ集群的配|信息中心。它有几个特色功能:1Q集中式的配|信?/span> 2Q自动容?/span> 3Q近实时搜烦 4Q查询时自动负蝲均衡 

 

基本可以用上面这q图来概qͼq是一个拥?/span>4?/span>Solr节点的集,索引分布在两?/span>Shard里面Q每?/span>Shard包含两个Solr节点Q一个是Leader节点Q一个是Replica节点Q此外集中有一个负责维护集状态信息的Overseer节点Q它是一个L制器。集的所有状态信息都攑֜Zookeeper集群中统一l护。从图中q可以看刎ͼM一个节炚w可以接收索引更新的请求,然后再将q个h转发到文所应该属于的那?/span>Shard?/span>Leader节点Q?/span>Leader节点更新l束完成Q最后将版本号和文转发l同属于一?/span>Shard?/span>replicas节点?/span>

下面我们来看一个简单的SolrCloud集群的配|过E?/span>

首先?/span>https://builds.apache.org/job/Solr-trunk/lastSuccessfulBuild/artifact/artifacts/下蝲Solr4.0的源码和二进制包Q注?/span>Solr4.0现在q在开发中Q因此这里是Nightly Build版本?/span>

CZ1Q简单的包含2?/span>Shard的集?/span>

q个CZ中,我们把一?/span>collection的烦引数据分布到两个shard上去Q步骤如下:

Z?/span>2?/span>solr服务器,我们拯一?/span>example目录

cp -r example example2

然后启动W一?/span>solr服务器,q初始化一个新?/span>solr集群Q?/span>

cd example
java -Dbootstrap_confdir=./solr/conf -Dcollection.configName=myconf -DzkRun -DnumShards=2 -jar start.jar

-DzkRun参数是启动一个嵌入式?/span>Zookeeper服务器,它会作ؓsolr服务器的一部分Q?/span>-Dbootstrap_confdir参数是上传本地的配置文g上传?/span>zookeeper中去Q作为整个集共用的配置文gQ?/span>-DnumShards指定了集的逻辑分组数目?/span>

然后启动W二?/span>solr服务器,q将其引向集所在位|?/span>

cd example2
java -Djetty.port=7574 -DzkHost=localhost:9983 -jar start.jar

-DzkHost=localhost:9983是指明?/span>Zookeeper集群所在位|?/span>

我们可以打开http://localhost:8983/solr/collection1/admin/zookeeper.jsp 或?/span>http://localhost:8983/solr/#/cloud看看目前集群的状态,

现在Q我们可以试试烦引一些文,

cd exampledocs
java -Durl=http://localhost:8983/solr/collection1/update -jar post.jar ipod_video.xml
java -Durl=http://localhost:8983/solr/collection1/update -jar post.jar monitor.xml
java -Durl=http://localhost:8983/solr/collection1/update -jar post.jar mem.xml

最后,来试试分布式搜烦?/span>:

http://localhost:8983/solr/collection1/select?q

Zookeeperl护的集状态数据是存放?/span>solr/zoo_data目录下的?/span>

现在我们来剖析下q样一个简单的集群构徏的基本流E:

先从W一?/span>solr服务器说P

1)       它首先启动一个嵌入式?/span>Zookeeper服务器,作ؓ集群状态信息的理者,

2Q?/span> 自p个节Ҏ册到/node_states/目录?/span>

3Q?/span> 同时自己注册到/live_nodes/目录?/span>

4Q创?/span>/overseer_elect/leaderQؓ后箋Overseer节点的选D做准备,新徏一?/span>OverseerQ?/span>

5) 更新/clusterstate.json目录?/span>json格式的集状态信?/span>

6) 本机?/span>Zookeeper中更新集状态信息,l持?/span>Zookeeper上的集群信息一?/span>

7Q上传本地配|文件到Zookeeper中,供集中其他solr节点使用

8) 启动本地?/span>Solr服务器,

9) Solr启动完成后,Overseer会得?/span>shard中有W一个节点进来,更新shard状态信息,q将本机所在节点设|ؓshard1?/span>leader节点Qƈ向整个集发布最新的集群状态信息?/span>

10Q本ZZookeeper中再ơ更新集状态信息,W一?/span>solr服务器启动完毕?/span>

然后来看W二?/span>solr服务器的启动q程Q?/span>

1Q?nbsp;本机q接到集所在的ZookeeperQ?/span>

2Q?nbsp;自p个节Ҏ册到/node_states/目录?/span>

3Q?nbsp; 同时自己注册到/live_nodes/目录?/span>

4Q?nbsp;本机?/span>Zookeeper中更新集状态信息,l持?/span>Zookeeper上的集群信息一?/span>

5Q?nbsp;从集中保存的配|文件加?/span>Solr所需要的配置信息

6Q?nbsp;启动本地solr服务器,

7Q?nbsp;solr启动完成后,本节点注册为集中?/span>shardQƈ本|ؓshard2?/span>Leader节点Q?/span>

8Q?nbsp;本机?/span>Zookeeper中再ơ更新集状态信息,W二?/span>solr服务器启动完毕?/span>

CZ2Q包?/span>2?/span>shard的集,每个shard中有replica节点

如图所C,集群包含2?/span>shardQ每?/span>shard中有两个solr节点Q一个是leaderQ一个是replica节点Q?/span>

cp -r example exampleB
cp -r example2 example2B
cd exampleB
java -Djetty.port=8900 -DzkHost=localhost:9983 -jar start.jar
cd example2B
java -Djetty.port=7500 -DzkHost=localhost:9983 -jar start.jar

我们可以打开http://localhost:8983/solr/collection1/admin/zookeeper.jsp  看看包含4个节点的集群的状态,

 

 

q个集群现在具备容错性了Q你可以试着q掉一?/span>Solr服务器,然后再发送查询请求。背后的实质是集的ov erseer会监各?/span>shard?/span>leader节点Q如?/span>leader节点挂了Q则会启动自动的定w机制Q会从同一?/span>shard中的其他replica节点集中重新选DZ?/span>leader节点Q甚臛_?/span>overseer节点自己也挂了,同样会自动在其他节点上启用新?/span>overseer节点Q这样就保了集的高可用性?/span>

CZ3 包含2?/span>shard的集,?/span>shard备䆾?/span>zookeeper集群机制

 

上一个示例中存在的问题是Q尽?/span>solr服务器可以容忍挂掉,但集中只有一?/span>zookeeper服务器来l护集群的状态信息,单点的存在即是不E_的根源。如果这?/span>zookeeper服务器挂了,那么分布式查询还是可以工作的Q因为每?/span>solr服务器都会在内存中维护最q一ơ由zookeeperl护的集状态信息,但新的节Ҏ法加入集,集群的状态变化也不可知了。因此,Z解决q个问题Q需要对Zookeeper服务器也讄一个集,让其也具备高可用性和定w性?/span>

有两U方式可选,一U是提供一个外部独立的Zookeeper集群Q另一U是每个solr服务器都启动一个内嵌的Zookeeper服务器,再将q些Zookeeper服务器组成一个集?/span> 我们q里用后一U做CZQ?/span>

cd example
java -Dbootstrap_confdir=./solr/conf -Dcollection.configName=myconf -DzkRun -DzkHost=localhost:9983,localhost:8574,localhost:9900 -DnumShards=2 -jar start.jar
cd example2
java -Djetty.port=7574 -DzkRun -DzkHost=localhost:9983,localhost:8574,localhost:9900 -jar start.jar
cd exampleB
java -Djetty.port=8900 -DzkRun -DzkHost=localhost:9983,localhost:8574,localhost:9900 -jar start.jar
cd example2B
java -Djetty.port=7500 -DzkHost=localhost:9983,localhost:8574,localhost:9900 -jar start.jar

我们可以打开http://localhost:8983/solr/collection1/admin/zookeeper.jsp  看看包含4个节点的集群的状态,可以发现其实和上一个没有Q何区别?/span>

后箋的文章将从实现层面对SolrCloudq个分布式搜索解x案进行进一步的深入剖析?/span>



SIMONE 2012-07-04 18:40 发表评论
]]>深入剖析SolrCloudQ二Q?/title><link>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382218.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Wed, 04 Jul 2012 10:40:00 GMT</pubDate><guid>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382218.html</guid><wfw:comment>http://www.aygfsteel.com/wangxinsh55/comments/382218.html</wfw:comment><comments>http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382218.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/wangxinsh55/comments/commentRss/382218.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/wangxinsh55/services/trackbacks/382218.html</trackback:ping><description><![CDATA[<div>http://www.cnblogs.com/phinecos/archive/2012/02/15/2353007.html</div><br /><div>  <a ><span style="font-family: 宋体">上一?/span></a><span style="font-family: 宋体">介绍?/span>SolrCloud<span style="font-family: 宋体">的基本概念,从这一开始我深入到其实C码中q行剖析?/span> <p><span style="white-space:pre"> </span>SolrCloud<span style="font-family: 宋体">最重要的一点就是引入了</span>ZooKeeper<span style="font-family: 宋体">来统一理各种配置和状态信息?/span><a >zookeeper</a><span style="font-family: 宋体">是一个开源分布式的服?/span>,<span style="font-family: 宋体">它提供了分布式协?/span>,<span style="font-family: 宋体">分布式同?/span>,<span style="font-family: 宋体">配置理{功?/span>. <span style="font-family: 宋体">其实现的功能?/span>google<span style="font-family: 宋体">?/span><a >chubby</a><span style="font-family: 宋体">基本一?/span>.zookeeper<span style="font-family: 宋体">的官方网站已l写了一非常经典的概述性文?/span>,<span style="font-family: 宋体">请大家参?/span>:<a >ZooKeeper: A Distributed Coordination Service for Distributed Applications</a>.</p> <p>        <a ><span style="font-family: 宋体">上一?/span></a><span style="font-family: 宋体">的示例中是在启动每个</span>solr<span style="font-family: 宋体">服务器前Q内嵌启动了一?/span>Zookeeper<span style="font-family: 宋体">服务器,再将q几?/span>Zookeeper<span style="font-family: 宋体">服务器组成一个集,保</span>Solr<span style="font-family: 宋体">集群信息的高可用性和定w性?/span></p><p><span style="font-family: 宋体">      构徏一个可用的</span>Zookeeper<span style="font-family: 宋体">集群Q这是</span>SolrCloud<span style="font-family: 宋体">要做的第一件工作?/span><span style="font-family: 宋体">下面来看?/span>SolrCloud<span style="font-family: 宋体">是如何实现这一功能的:</span></p> <p style="text-indent: -18pt; margin: 0cm 0cm 0pt 39pt">1Q?nbsp;<span style="font-family: 宋体">首先?/span>web.xml<span style="font-family: 宋体">中配|了一?/span>filter</p> <div> <div><span style="color: #0000ff"><</span><span style="color: #800000">filter</span><span style="color: #0000ff">></span><br />    <span style="color: #0000ff"><</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">></span>SolrRequestFilter<span style="color: #0000ff"></</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">></span><br />    <span style="color: #0000ff"><</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">></span>org.apache.solr.servlet.SolrDispatchFilter<span style="color: #0000ff"></</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">></span><br />      <span style="color: #0000ff"></</span><span style="color: #800000">filter</span><span style="color: #0000ff">></span></div></div> <p style="text-indent: -18pt; margin: 0cm 0cm 0pt 39pt"><span>   </span><span style="font-family: 宋体;">?/span>web<span style="font-family: 宋体;">容器启动时会d载ƈ初始?/span>SolrDispatchFilter<span style="font-family: 宋体;">q个</span>filter,<span style="font-family: 宋体;">它的</span>init<span style="font-family: 宋体;">Ҏ会被调用Q这个方法中做的最主要的事情是初始化一?/span>Solr<span style="font-family: 宋体;">核容器?/span></p> <div> <div>  CoreContainer.Initializer init = createInitializer();<br />    <span style="color: #008000">//</span><span style="color: #008000"> web.xml configuration</span><span style="color: #008000"><br /></span>    <span style="color: #0000ff">this</span>.pathPrefix = config.getInitParameter( "path-prefix" );<br /><span style="color: #0000ff">this</span>.cores = init.initialize();</div></div> <p style="text-indent: -18pt; margin: 0cm 0cm 0pt 39pt"> 2) <span style="font-family: 宋体">初始?/span>Solr<span style="font-family: 宋体">核容器时Q首先找?/span>solr<span style="font-family: 宋体">的根目录Q这个目录下最重要的是</span>solr.xml<span style="font-family: 宋体">q个配置文gQ这个配|文件用于初始化容器中加载的各个</span>solr<span style="font-family: 宋体">核,如果没有提供</span>solr.xml<span style="font-family: 宋体">Q则会启用默认的配置信息Q?/span> </p> <div> <div>  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> String DEF_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +<br />          "<solr persistent=\"false\">\n" +<br />          "  <cores adminPath=\"/admin/cores\" defaultCoreName=\"" + DEFAULT_DEFAULT_CORE_NAME + "\">\n" +<br />          "    <core name=\""+ DEFAULT_DEFAULT_CORE_NAME + "\" shard=\"${shard:}\" instanceDir=\".\" />\n" +<br />          "  </cores>\n" +<br />          "</solr>";</div></div> <p style="text-indent: -18pt; margin: 0cm 0cm 0pt 39pt">  3Q?nbsp;<span style="font-family: 宋体">初始化过E的其中一步就是初始化</span>Zookeeper<span style="font-family: 宋体">服务器,你可以选择单机?/span>Zookeeper<span style="font-family: 宋体">服务器,也可以构?/span>Zookeeper<span style="font-family: 宋体">集群Q下面以集群Zq行代码分析?/span></p> <div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div> <div>    <span style="color: #0000ff">if</span> (zkRun != <span style="color: #0000ff">null</span>) {<br />      zkServer = <span style="color: #0000ff">new</span> SolrZkServer(zkRun, zookeeperHost, solrHome, hostPort);<br />      zkServer.parseConfig();<br />      zkServer.start();<br />      <br />      <span style="color: #008000">//</span><span style="color: #008000"> set client from server config if not already set</span><span style="color: #008000"><br /></span>      <span style="color: #0000ff">if</span> (zookeeperHost == <span style="color: #0000ff">null</span>) {<br />        zookeeperHost = zkServer.getClientString();<br />      }<br />}</div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div></div> <p><span>         SolrZkServer</span><span style="font-family: 宋体;">cd是伴?/span>solr<span style="font-family: 宋体;">启动的内嵌的</span>Zookeeper<span style="font-family: 宋体;">服务器,首先来看</span>parseConfig<span style="font-family: 宋体;">ҎQ它负责解析</span>zoo.cfg<span style="font-family: 宋体;">文gQ读?/span>Zookeeper<span style="font-family: 宋体;">启动时所需要的配置信息Q这些配|信息由</span>SolrZkServerProps<span style="font-family: 宋体;">c表C,</span></p> <p style="text-indent: 21pt;"><span style="font-family: 宋体;">首先讄</span>Zookeeper<span style="font-family: 宋体;">存储数据的目?/span></p> <div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div> <div>    <span style="color: #0000ff">if</span> (zkProps == <span style="color: #0000ff">null</span>) {<br />      zkProps = <span style="color: #0000ff">new</span> SolrZkServerProps();<br />      <span style="color: #008000">//</span><span style="color: #008000"> set default data dir<br />      </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: use something based on IP+port???  support ensemble all from same solr home?</span><span style="color: #008000"><br /></span>      zkProps.setDataDir(solrHome + '/' + "zoo_data");<br />      zkProps.zkRun = zkRun;<br />      zkProps.solrPort = solrPort;<br />}</div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div></div> <p style="text-indent: 21pt;"><span style="font-family: 宋体; color: black; font-size: 10pt;'Courier New';'Courier New';'Courier New';">然后d</span><span style="font-family: 'Courier New'; color: black; font-size: 10pt;">zoo.cfg</span><span style="font-family: 宋体; color: black; font-size: 10pt;'Courier New';'Courier New';'Courier New';">配置文g中的信息Qؓ启动</span><span style="font-family: 'Courier New'; color: black; font-size: 10pt;">zookeeper</span><span style="font-family: 宋体; color: black; font-size: 10pt;'Courier New';'Courier New';'Courier New';">服务器提供完整的配置信息Q?/span></p> <div> <div>      props = SolrZkServerProps.getProperties(solrHome + '/' + "zoo.cfg");<br />      SolrZkServerProps.injectServers(props, zkRun, zkHost);<br />      zkProps.parseProperties(props);</div></div> <p><span style="font-family: 'Courier New'; color: black; font-size: 10pt">    </span><span style="font-family: 宋体; color: black; font-size: 10pt">下面是一个示例配|文Ӟ</span></p> <div> <div>tickTime=2000<br />dataDir=/var/zookeeper/<br />clientPort=2181<br />initLimit=5<br />syncLimit=2<br />server.1=zoo1:2888:3888<br />server.2=zoo2:2888:3888<br />server.3=zoo3:2888:3888</div></div> <p style="text-indent: 21pt"><span style="font-family: 宋体; color: #333333">注意Q?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">server.x</span><span style="font-family: 宋体; color: #333333">q些行就指明?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">zookeeper</span><span style="font-family: 宋体; color: #333333">集群所包含的机器名Uͼ每台</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">Zookeeper</span><span style="font-family: 宋体; color: #333333">服务器会使用</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">3</span><span style="font-family: 宋体; color: #333333">个端口来q行工作Q其中第一个端口(端口</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">1</span><span style="font-family: 宋体; color: #333333">Q用来做q行期间</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">server</span><span style="font-family: 宋体; color: #333333">间的通信Q第二个端口Q端?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">2</span><span style="font-family: 宋体; color: #333333">Q用来做</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">leader election</span><span style="font-family: 宋体; color: #333333">Q另外还有一个端口(端口</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">0</span><span style="font-family: 宋体; color: #333333">Q负责接收客Lh。那么一台机器怎样定自己是谁呢?q是通过</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">dataDir</span><span style="font-family: 宋体; color: #333333">目录下的</span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">myid</span><span style="font-family: 宋体; color: #333333">文本文g定?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">myid</span><span style="font-family: 宋体; color: #333333">文g只包含一个数字,内容是所?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">Server</span><span style="font-family: 宋体; color: #333333">?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">ID</span><span style="font-family: 宋体; color: #333333">Q?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">QuorumPeerConfig.myid</span><span style="font-family: 宋体; color: #333333">?/span></p> <p style="text-indent: -18pt; margin: 0cm 0cm 0pt 39pt"><span style="font-family: 'Tahoma','sans-serif'; color: #333333">1Q?</span><span style="font-family: 宋体; color: #333333">准备好集所需要的配置信息后,可以启?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">Zookeeper</span><span style="font-family: 宋体; color: #333333">集群了。启动时是生成一?/span><span style="font-family: 'Tahoma','sans-serif'; color: #333333">Zookeeper</span><span style="font-family: 宋体; color: #333333">服务器线E,Ҏ配置信息来决定是单机q是集群模式Q如果是单机模式Q则生成</span>ZooKeeperServerMain<span style="font-family: 宋体">对象q启动,如果是集模式,则?/span>QuorumPeerMain<span style="font-family: 宋体">对象启动。最后将服务器线E设|ؓ</span>Daemon<span style="font-family: 宋体">模式Q就完成?/span>Zookeeper<span style="font-family: 宋体">服务器的启动工作了?/span></p> <div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div> <div>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> start() {<br />        zkThread = <span style="color: #0000ff">new</span> Thread() {<br />            @Override<br />            <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> run() {<br />                <span style="color: #0000ff">try</span> {<br />                    <span style="color: #0000ff">if</span> (zkProps.getServers().size() > 1) {<span style="color: #008000">//</span><span style="color: #008000">zk集群</span><span style="color: #008000"><br /></span>                        QuorumPeerMain zkServer = <span style="color: #0000ff">new</span> QuorumPeerMain();<br />                        zkServer.runFromConfig(zkProps);<br />                        <span style="color: #0000ff">if</span> (logger.isInfoEnabled()) {<br />                            logger.info("启动zk服务器集成?);<br />                        }<br />                    } <span style="color: #0000ff">else</span> {<span style="color: #008000">//</span><span style="color: #008000">单机zk</span><span style="color: #008000"><br /></span>                        ServerConfig sc = <span style="color: #0000ff">new</span> ServerConfig();<br />                        sc.readFrom(zkProps);<br />                        ZooKeeperServerMain zkServer = <span style="color: #0000ff">new</span> ZooKeeperServerMain();<br />                        zkServer.runFromConfig(sc);<br />                        <span style="color: #0000ff">if</span> (logger.isInfoEnabled()) {<br />                            logger.info("启动单机zk服务器成?);<br />                        }<br />                    }<br />                    logger.info("ZooKeeper Server exited.");<br />                } <span style="color: #0000ff">catch</span> (Throwable e) {<br />                    logger.error("ZooKeeper Server ERROR", e);<br />                    <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> SolrException(SolrException.ErrorCode.SERVER_ERROR, e);                    <br />                }<br />            }<br />        };<br />        <span style="color: #0000ff">if</span> (zkProps.getServers().size() > 1) {<br />            logger.info("STARTING EMBEDDED ENSEMBLE ZOOKEEPER SERVER at port " + zkProps.getClientPortAddress().getPort());<br />        } <span style="color: #0000ff">else</span> {<br />            logger.info("STARTING EMBEDDED STANDALONE ZOOKEEPER SERVER at port " + zkProps.getClientPortAddress().getPort());            <br />        }<br />        <br />        zkThread.setDaemon(<span style="color: #0000ff">true</span>);<br />        zkThread.start();<br />        <span style="color: #0000ff">try</span> {<br />            Thread.sleep(500); <span style="color: #008000">//</span><span style="color: #008000"> pause for ZooKeeper to start</span><span style="color: #008000"><br /></span>        } <span style="color: #0000ff">catch</span> (Exception e) {<br />            logger.error("STARTING ZOOKEEPER", e);<br />        }<br />    }</div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div></div> <p style="text-indent: 21pt"><span style="font-family: 宋体">Z验证集群是否启动成功Q可以?/span>Zookeeper<span style="font-family: 宋体">提供的命令行工具q行验证Q进?/span>bin<span style="font-family: 宋体">目录下,q行Q?/span></p> <div> <div>zkCli.cmd –server zookeeper服务器地址1:端口</div></div> <p><span style="font-family: 宋体">    q是q接到集中</span>1<span style="font-family: 宋体">?/span>Zookeeper<span style="font-family: 宋体">服务器,然后创徏一?/span>ZNode,<span style="font-family: 宋体">往其中加入一些数据,你再q接到集中其他的服务器上,查看数据是否一_卛_知道</span>Zookeeper<span style="font-family: 宋体">集群是否已经构徏成功?/span></p></div><img src ="http://www.aygfsteel.com/wangxinsh55/aggbug/382218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wangxinsh55/" target="_blank">SIMONE</a> 2012-07-04 18:40 <a href="http://www.aygfsteel.com/wangxinsh55/archive/2012/07/04/382218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">¡Ң</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">³ƶ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͽ</a>| <a href="http://" target="_blank">Ͼ</a>| <a href="http://" target="_blank">ʩ</a>| <a href="http://" target="_blank">̩</a>| <a href="http://" target="_blank">˳</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">¬</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">»</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͱ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>