solr(一)配置文件详解与整合zookeeper集群

来源:互联网 发布:记工时的软件 编辑:程序博客网 时间:2024/06/05 23:58
一 . 概念 
 1) 全文检索 :  先对非结构化数据建立索引, 在对索引进行搜索的过程就是全文检索
 2) 方法 : 顺序索引(windows文件查找, linux的grep命令)
      索引 : 从非结构化数据中提取然后重新组织的信息
    (eg : 字典的字是非结构化数据, 拼音表和偏旁部首表就是索引)
 3) 顺序查找 : 速度慢, 顺序查找是文件包含了哪些字符串 , 是文件-> 字符串
      索引查找 : 有字符串找文件, 二者方向相反, 也成反向索引
 
 字符串1 --> 文档编号的列表1词典 | 倒排表
 字符串2 --> 文档编号的列表2(优势 : 一次创建索引, 多次使用)
 字符串3 --> 文档编号的列表3
 字符串4 --> 文档编号的列表4
 
二. 概念
   1. Document : solr的基本单元, 一个描述某一个对象的数据集 , 包括物体的组成成分,结构, 操作时间等
   2. Field : Document由field组成, field描述对象的属性
  
 三 . 配置文件
  1. solr.xml

        (1)单个core的配置 : 
      <solr><solrcloud><str name="host">${host:}</str><int name="hostPort">${jetty.port:8983}</int><str name="hostContext">${hostContext:solr}</str><int name="zkClientTimeout">${zkClientTimeout:30000}</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>   
          (2) 多个core的配置 
<solr persistent="false"><cores adminPath="/admin/cores" host="${host:}" hostPort="${jetty.port:8983}" hostContext="${hostContext:solr}"><core name="firstcore " instanceDir="core01" /><core name="secondcore" instanceDir="core02" /></cores></solr>

   2. solrconfig.xml : 

      1) 在每个collection下有一个, mutilconfig里的collection有一个, 用来配置requestHandler
      2) 数据库导入时 , 配置数据库的文件 dataimport
           a) <dataDir> : solr索引数据存放位置 
 <dataDir>${solr.data.dir:/home/lj/software/solrdata}</dataDir>
           b) <directoryFactory> : 配置工厂类, 以实现在dataDir中存放索引
<directoryFactory name="DirectoryFactory"  class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}">
          c) <schemaFactory> : 配置索引是用到的schema.xml
1. <schemaFactory class="ClassicIndexSchemaFactory"/>
默认为schma.xml
2. <schemaFactory class="ManagedIndexSchemaFactory">()
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
详解见"example里的solrconfig.xml"
(4) <indexConfig> : 配置lucene的index writer, 默认即可
(5) <updatehandler> : 配置如何更新索引
发送到solr中的数据不能立刻被查到, 这些数据还需经过commit的过程. 这个过程会有延迟, 并且在此过程中, 不能处理
新的"commit", 以免数据被覆盖
1. commit : 
2. soft commit : 数据存储且立刻被查到, 这种方式不会等到background merge完毕. 当服务器突然宕机, solr不会知道已经存储的数据放在哪里
3. auto commit : 

<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
</updateLog>
<autoCommit> 
  <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> 
  <openSearcher>false</openSearcher>  //会自动提交, 但不会立刻看到索引变化
</autoCommit>
<autoSoftCommit> 
<maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> 
</autoSoftCommit>
</updateHandler>
(6) 查询设置<query>
1. caches : 超过一定时间为改变的索引就会形成cache, 以便更快的查找
新index searcher也会在老searcher的caches基础上建立, 当新searcher建立完毕, 老searcher关闭
实现类 : 1) LRUCache
2) FastLRUCache
3) LFUCache
 
(1) filterCache 
<filterCache class="solr.FastLRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
...
   ... 更多见文档
2. requestDispatcher
配置http响应处理
<requestDispatcher handleSelect="false" >
<requestParsers enableRemoteStreaming="true" 
multipartUploadLimitInKB="2048000"
formdataUploadLimitInKB="2048"
addHttpRequestToContext="false"/>
<httpCaching never304="true" />
 </requestDispatcher>

3. requestHandler
http://10.1.198.56:8983/solr/iap_app_log_201501/select?q=ss (正确)  http请求不加#
http://10.1.198.56:8983/solr/#/iap_app_log_201501/select?q=ss (错误)
  2. schemal.xml : 
    1) fieldType : 
<1>  四大内容 : name, class , 
 TextField的字段类型需要analyzer类
 其他属性(sortMissingLast)
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="text_greek" class="solr.TextField">
<analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
</fieldType>
<2>solr的货币类型
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
currency.xml文件中定义了利率
2) 规定fields
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
3) 复制fields
<copyField source="cat" dest="text"/> 
   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
cat的内容回作为附加加载text值的后面, 存在text中
4) 动态fields
<dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
5) unique key : 
<uniqueKey>id</uniqueKey>
6) defaultSearchField : 不推荐
7) solrQueryParser : 
<solrQueryParser defaultOperator="OR"/> 不推荐, 默认or

四. 分析器
(一)分析其包括分词器和过滤器 , 分词器和过滤器组合形成分析器, 他们可以形成链式处理. 这种处理在建立索引, 分析查询语句时都使用
 分词器Tokenizer : 把field的数据分成词汇单元, 或者每个token
 过滤器filter : 过滤器把token stream中的每个词变形, 丢弃, 增加
 
(二) schema.xml配置分析器
当fieldType为"solr.TextField"时, 才配置分析器, 
      1. 配置org.apache.lucene.analysis.Analyzer的子类
<fieldtype name="nametext" class="solr.TextField">  
<analyzer class="org.apache.lucene.analysis.WhitespaceAnalyzer"/>  
</fieldtype>  
 2. 分别配置tokenizer和filter
<fieldtype name="text" class="solr.TextField">  
 <analyzer>  
<tokenizer class="solr.StandardTokenizerFactory"/>  
<filter class="solr.StandardFilterFactory"/>  
<filter class="solr.LowerCaseFilterFactory"/>  
<filter class="solr.StopFilterFactory"/>  
<filter class="solr.PorterStemFilterFactory"/>  
 </analyzer>  
</fieldtype>  

(三) Tokenizer详解
1. 工厂类StandardTokenizerFactory必须实现solr.analysis.TokenizerFactory接口, 在工厂类的create()方法中翻译分析器实例,实现solr和第三方分词器的结合
<fieldType name="managed_en" class="solr.TextField" positionIncrementGap="100">
 <analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.ManagedStopFilterFactory" managed="english" />
<filter class="solr.ManagedSynonymFilterFactory" managed="english" />
 </analyzer>
</fieldType>
2. solr实现的TokenizerFactory
1) <tokenizer class="solr.StandardTokenizerFactory"/>
   用空格和分隔符分割字符串, 再除去分隔符
eg "a b,c @sina.com" => "a""b""c""sina.com"
2) <tokenizer class="solr.KeywordTokenizerFactory"/>
不对输入进行分词
3) <tokenizer class="solr.LetterTokenizerFactory"/>
对所有符号进行分割
eg "i can't"->"i" "can" "t"
4)  solr.LowerCaseTokenizerFactory
用所有非字母符号分词, 讲分得的字母变为小写, 非字母去除
eg: "I LOVE "=> 'i' 'love' 
.
.
.
(四) Filter详解
filter会按照配置的顺序来对tokenizer产生的tokens进行处理
...
...
(五) CharFilterFactories组件
该组件在tokenizer之前处理字符串中的字符, 可以对字符增加, 修改,删除, 该组件也可以形成链式处理
<fieldType name="text_fa" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<charFilter class="solr.PersianCharFilterFactory"/>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.ArabicNormalizationFilterFactory"/>
<filter class="solr.PersianNormalizationFilterFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fa.txt" />
</analyzer>
</fieldType>
四. 导入数据到solr
  1. 从数据库导Data Import Handler :
1)  solrconfig.xml配置数据库连接xml  
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>

2) xml文件
<dataConfig>
<dataSource name="jdbc" driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@10.1.242.63:1521:AI4A" user="audit30devc"password="audit30#devc" />
<document>
<entity name="core的逻辑名(显示), 非真实目录" dataSource="jdbc" query="select T.*, from dual">
<field name="stdBeginTimeDate" column="STD_BEGIN_DATE" dateTimeFormat="yyyy-MM-dd HH:mm:ss" locale="en" />
</entity>
</document>
</dataConfig>
   
  2. csv文件
  3. json对象
  4. 从word/pdf导入 
       1) Solr Cell :  ExtractingRequestHandler 
  5.. 用solrj导入
  
 
 
 五. solrCloud
    (1) 每个分片都是索引集合的子集, 但是用http://localhost:8983/solr/collection1/select?*=*得出的是索引全集
    (2) 用bin\solr脚本启动, 默认开启2个shard(8983,7574),每个shard2个副本. 
 <1> 手动建立多节点分片
  (建立集群之前, 至少运行example单节点solr一次,解压必要的jar文件)
   (1) 开启第一个节点, 让该节点内置的zookeeper'监控集群
   (2) 开启其余节点, 并让其余节点指向第一个节点的zookeeper
1. 步骤
   (1) 复制example, 让其分成两个节点node1,node2 
cp -r example node1cp -r example node2
   (2) -DzkRun开启node1节点
cd node1java -DzkRun              // (开启节点内置zookeeper)     -DnumShards=2        // (索引分成2片,shard个数, 机器节点个数)     -Dbootstrap_confdir=./solr/collection1/conf       //(让内置zookeeper找到cluster的配置文件)     -Dcollection.configName=myconf                       // (为内置zookeeper的配置信息起别名)     -jar start.jar
   (3) 开启node2
 cd node2 java  -Djetty.port=7574       -DzkHost=localhost:9983 //(指出第一个节点的zookeeper位置,让node2向zookeeper报告任务, zookeeper端口必须比solr端口大1000)       -jar start.jar
    <2>为分片建立高可用
   (1)  基于以上node1,node2两个分片, 再建立两个新的节点
cp -r example node3cp -r example node4
   (2) 开启新的节点
cd node3 java -Djetty.port=8900 -DzkHost=localhost:9983 -jar start.jar
    [注] : a) 由于已经在开启node1的时候, -DnumShards=2指定了分片个数为2, 所以新建立的node会直接作为已存在分片的副本, 二不会成为新的副本
     b) 副本的添加顺序 和 leader节点额开启顺序一致,副本会自动挂载成辅助节点
cd node4 java -Djetty.port=7575 -DzkHost=localhost:9983 -jar start.jar
   [注] : a) shard的副本并不处理任务, 也不会控制数据流向正确的位置, 只是存储数据
    b) 只要每个shard有一个实例运行, 集群就可以运行
    c) 这种集群不能让node1挂掉, 否则zookeeper挂掉. 在某些情况下, zookeeper挂掉仍然能运行solr集群, 但不能再接受节点增加和节点切换
  <3>建立多实例zookeeper的solr集群(Zookeeper Ensemble)
在上面node1~4 的基础上搭建 ,
    1. 清除上面步骤的zookeeper数据
rm -r node*/solr/zoo_data
    2. 在启动start.jar时, 指定出所有的zookeeper集合
cd node1java  -DzkRun  -DnumShards=2        -Dbootstrap_confdir=./solr/collection1/conf    -Dcollection.configName=myconf      //  把solrconfig.xml和schema.xml发送到zookeeper中      -DzkHost=localhost:9983,localhost:8574,localhost:9900       // 这几个端口分别比每个节点的端口大1000      -jar start.jarcd node2java  -Djetty.port=7574      //第一个节点已提交了配置文件到zookeeper, 剩下的直接启动zookeeper即可      -DzkRun      -DnumShards=2      -DzkHost=localhost:9983,localhost:8574,localhost:9900      -jar start.jarcd node3 java -Djetty.port=8900      -DzkRun     -DnumShards=2     -DzkHost=localhost:9983,localhost:8574,localhost:9900 -jar start.jarcd node4        //最后一个节点不开启zookeeper,所以不用加上-DzkRunjava -Djetty.port=7575 -DzkHost=localhost:9983,localhost:8574,localhost:9900 -jar start.jar
 [注] : a) 启动的zookeeper集合个数必须大于等于节点个数的一半
  b) 启动节点时会报错, 应为zookeeper ensemble并未全部启动
  c) 这四个节点,只是java启动参数不同, 节点的文件相同

[概念]
  1. core : 集群中每个shard的本地index库就是core
  2. collection : 集群中,每个节点的core组成了collection
      core.properties文件的内容
#Written by CorePropertiesLocator#Tue Feb 03 23:38:40 PST 2015numShards=3 name=mycollection_shard1_replica1shard=shard1  //分片名collection=mycollection//用collection名识别一个集群coreNodeName=core_node2
  3. shard的 数量一旦初始化不能改变, shard是把一个core分割到多个server或者node上面的一种方式
  4. 请求会分发给所有shard的leader
  5. ZooKeeper提供shard副本中的故障转移和多个分片的负载均衡
       如果leader宕机了,replica节点中的某一个节点将会自动被选举成新的leader。在每一个节点启动之后,它都是自动分配给拥有replica最少的shard。
       当所有shard拥有一样数量的replica的时候,新的节点会被分配给shard id值最小的shard。
  6. 当一个document发送到一个节点时, 若节点时副, 则转发请求到对应的leader, 若是leader, 则看该请求是否是这个shard
 
六.  手动分割shard (Collection API)
   (1) 当需求改变,一个错误的shard数量参数, 会导致要重新创建新的core和重新索引所有的数据, 带来时间和空进上的麻烦。
   (2) Collection API : 现在允许通过它来把一个shard分开到两个块中。原来存在的shard还是会保持原状,
   (3) 所有分割操作实际上是创建了它的数据的两个副本作为新的shard
     译注:这里应该是把原来shard里面的数据作为一个副本分开到两个新的shard里面去
                 当你一切都准备好了之后,你可以把旧的shard给删除掉。
    1) 新增collection : http://192.168.2.134:8983/solr/admin/collections?action=CREATE&name=mycollection&numShards=3
    2) 删除collection : http://192.168.2.134:8983/solr/admin/collections?action=DELETE&name=mycollection
    3) reload : 当zookeeper配置文件改变时, 要reload一个collection
         http://192.168.2.134:8983/solr/admin/collections?action=RELOAD&name=mycollection
    4) shard二次分片 : 
     (1) zookeeper加入新节点, 形成副本
     (2) 手动分片, 分片后原来的shard1会分片成两片, 均摊索引
            http://192.168.2.134:8983/solr/admin/collections?action=SPLITSHARD&collection=collection1&shard=shard1
     (3) 分片后, 原分片还在, 要删除原分片

七. 指定分片上查询的分布式请求 : Distributed Requests
       1) 查询整个shard   --->   http://localhost:8983/solr/collection1/select?q=*:*
       2) 指定在某几个分片上查询--->http://localhost:8983/solr/collection1/select?q=*:*&shards=localhost:7574/solr,localhost:
       3) 在多个collection上查询 : 
           http://localhost:8983/solr/collection1/select?collection=collection1,collection2
CloudSolrServer获取shard集群信息
public class Test {    public static void main(String[] args) {        String zkHost = "192.168.2.134:9983";   //链接任意一个zookeeper即可, 路径不带http          CloudSolrServer server = new CloudSolrServer(zkHost);        server.setDefaultCollection("collection1"); //配置索引collection          server.connect();        System.out.println("The cloud Server has been connected !!!!");        ZkStateReader zkStateReader = server.getZkStateReader();        ClusterState cloudState  = zkStateReader.getClusterState(); //获取集群信息,返回shard的json对象          System.out.println(cloudState);        String sql = "name:*";        SolrQuery query = new SolrQuery();        query.setQuery(sql);        query.setStart(0);        query.setRows(100);     //不设置行数,只显示前10条          try {            QueryResponse rs = server.query(query, METHOD.POST);            SolrDocumentList li = rs.getResults();            for(SolrDocument doc : li){                System.out.println(doc.getFieldValue("name"));            }            System.out.println("一共"+li.getNumFound());        } catch (SolrServerException e) {  e.printStackTrace(); }    }}



 4) 新加入的replicate节点, 会自动同步leader节点的索引数据 

   <四>solr 与 hdfs
    solr支持在hdfs上读写索引
java -Dsolr.directoryFactory-HdfsDirectoryFactory
  -Dsolr.lock.type=hdfs
  -Dsolr.hdfs.home=hdfs://host:port/path
/*-Dsolr.data.dir=hdfs://host:port/path
  -Dsolr.updatelog=hdfs://host:port/path*/
  -jar start.jar
   
   设置-XX:MaxDirectMemorySize=20g
   
   
   
   
   
   
   
   
 
 
 
1 0
原创粉丝点击