CDH中SOLR配置IK中文分词器的方法(血泪教训,关于IK jar的存放位置)

网上关于SOLR配置IK中文分词的文章有很多,以下是我的测试步骤:

测试于:Solr 4.5.1, IK Analyzer 2012FF_hf1, Jdk 1.6.0_45, Tomcat 6.0.37 | CentOS 5.7

配置步骤:

从googlecode上下载针对solr4的ik版本IK Analyzer 2012FF_hf1.zip(https://code.google.com/p/ik-analyzer/downloads/list)
解压后将IKAnalyzer2012FF_u1.jar上传到solr lib中,如:
/opt/tomcat/webapps/solr/WEB-INF/lib
在core的schema中加入ik分词类型,如下代码需要放在<types>…</types>中,推荐放在最后
<!– ik analyzer Chinese –>
<fieldType name=”text_ik” class=”solr.TextField”>
<analyzer class=”org.wltea.analyzer.lucene.IKAnalyzer”/>
</fieldType>
在core的schema中应用我们新定义的类型,如:
<field name=”id” type=”string” indexed=”true” stored=”true” required=”true” />
<field name=”title” type=”text_ik” indexed=”true” stored=”true” termVectors=”true”/>
<field name=”content” type=”text_ik” indexed=”false” stored=”true”/>
<field name=”create_time” type=”date” indexed=”true” stored=”true”/>
<field name=”update_time” type=”date” indexed=”true” stored=”true”/>
重启tomcat

但是在CDH下面,确定solr的lib位置成了一个问题。

开始以为是在/var/lib/solr/tomcat-deployment/webapps/solr/WEB-INF/lib下面,把IK jar包放进去重启solr服务发现提示没有找到IK的类!

再次查看上面的目录发现重启前传入的IK jar包居然不见了~

可能的原因应该是启动时该目录被清空然后从其他lib目录传入了jar。(可能 应该 的说法好不严谨啊。。。)

然后再次find 了一下上上述目录中的jar包,发现以下目录均存在:

/var/lib/solr/tomcat-deployment/webapps/solr/WEB-INF/lib/lucene-core.jar
/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/solr/webapps/solr/WEB-INF/lib/lucene-core.jar
/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/hbase-solr/lib/lucene-core.jar
/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/search/lib/lucene-core.jar
/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/search/lib/search-crunch/lucene-core.jar
/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/kite/lib/lucene-core.jar

难道是从/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/solr/webapps/solr/WEB-INF/lib这个目录copy jar包的?

把IK jar包传到/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/solr/webapps/solr/WEB-INF/lib目录下面,再次重启solr服务,发现/var/lib/solr/tomcat-deployment/webapps/solr/WEB-INF/lib下面果然有IK的jar包了。

so,正确的jar包目录应该是/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/lib/solr/webapps/solr/WEB-INF/lib。

Lily Hbase Indexer在solr中为hbase的rowkey建立索引字段

在hbase录入数据的同时将数据索引到solr是一个很不错的主意。Lily Hbase Indexer就可以这么做。

但是在设计处理流程时发现如何将hbase的rowkey索引为hbase的字段,在网上资料没搜索到。

机智的“我”去搜索morphline的相关资料,果然发现了一些端倪。

资料地址在 https://github.com/NGDATA/hbase-indexer/wiki/Indexer-configuration  .

在这篇讲解morphline indexer配置的文章中,涉及到一个属性  unique-key-field。

原文如下:

unique-key-field

This attribute specifies the name of the document identifier field used in Solr.
The default value for this field is "id".

翻译过来就是:此属性用以指定solr中文档标识字段的名字。默认是“id”。

仔细想想,这说的难道不就是 solr字段配置文件 schema.xml中uniqueKey 嘛。。

so,在配置morphline-mapper.xml文件时,如果要把rowkey放入索引的结果中,要在schema.xml中配置一个专门的字段或者是直接使用uniqueKey。

如果使用uniqueKey作为接收rowkey的字段名,记得在上传hbase数据时不要再带入uniqueKey了。只传入其他正常的列就好了。

morphline-mapper.xml模板:

<?xml version=”1.0″?>
<indexer table=”indextest” mapping-type=”column” mapper=”com.ngdata.hbaseindexer.morphline.MorphlineResultToSolrMapper” unique-key-field=”id”>
<param name=”morphlineFile” value=”morphlines.conf”/>
</indexer>

后面附上资料全文,意思很直白,就不翻译了。

Global indexer attributes

The following is a list of attributes that can be set on the top-level <indexer> element in an indexer configuration.

table

The table attribute specifies the name of the HBase table to be indexed by the indexer. It is the only mandatory attribute in the indexer element.

mapping-type

The mapping-type attribute has two possible values: row, or column. This attribute specifies whether row-based or column-based indexing is to be performed.

Row-based indexing treats all data within a single HBase row as input for a single document in Solr. This is the kind of indexing that would be used for an HBase table that contains a separate entity in each row, e.g. a table containing users.

Column-based indexing treats each HBase cell as input for a single document in Solr. This approach could be used for example in a messaging platform where a single user’s messages are all stored in a single row, with each message being stored in a separate cell.

The default mapping-type value is row.

read-row

The read-row attribute has two possible values: dynamic, or never.

This attribute is only important when using row-based indexing. It specifies whether or not the indexer should re-read data from HBase in order to perform indexing.

When set to “dynamic”, the indexer will read the necessary data from a row if a partial update to the row is performed in HBase. In dynamic mode, the row will not be re-read if all data needed to perform indexing is included in the row update.

If this attribute is set to never, a row will never be re-read by the indexer.

The default setting is “dynamic”.

mapper

The mapper attribute allows the user to specify a custom mapper class that will create a Solr document from a HBase Result object. The mapper class must implement the

com.ngdata.hbaseindexer.parse.ResultToSolrMapper

interface.

By default, the built-in

com.ngdata.hbaseindexer.parse.DefaultResultToSolrMapper

is used.

unique-key-formatter

The unique-key-formatter attribute specifies the name of the class used to format HBase row keys (as well as column families and column qualifiers) as text. A textual representation of these pieces of information is needed for indexing in Solr, as all data in Solr is textual, but row keys, column families, and column qualifiers are byte arrays.

A unique-key-formatter class must implement the

com.ngdata.hbaseindexer.uniquekey.UniqueKeyFormatter

interface.

The default value of this attribute is com.ngdata.hbaseindexer.uniquekey.StringUniqueKeyFormatter. The StringUniqueKey formatter simply treats row keys and other byte arrays as strings.

If your row keys, column families, or qualifiers can’t simply be used as strings, consider using the com.ngdata.hbaseindexer.uniquekey.HexUniqueKeyFormatter.

unique-key-field

This attribute specifies the name of the document identifier field used in Solr.

The default value for this field is “id”.

row-field

The row-field attribute specifies the name of the Solr field to be used for storing an HBase row key.

This field is only important when doing column-based indexing. In order for the indexer to be able to delete all documents for a single row from the index, it needs to be able to find all documents for the row in Solr. When this attribute is populated in the indexer definition, it’s value is used as the name of a field in Solr to store the encoded row key.

By default, this attribute is empty, meaning that the row key is not stored in Solr. The consequence of this is that deleting a complete row or complete column family in HBase will not delete the indexed documents in Solr.

column-family-field

The column-family-field specifies the name of the Solr field to be used for storing the HBase column family name.

See the description of the row-field attribute for more information.

By default, this attribute is empty, so the column-family name is not saved in Solr.

table-name-field

The table-name-field specifies the name of the Solr field to be used for storing the name of the HBase table where a record is stored.

By default, this attribute is empty, so the name of the HBase table is not stored unless this setting is explicitly set in the indexer config.

Elements within the indexer definition

There are three types of elements that can be used within an indexer configuration: <field>, <extract>, and <param>.

<field>

The field element defines a single field to be indexed in Solr, as well as where its contents are to be taken from and interpreted from HBase. There are typically one or more fields listed in an indexer configuration — one for each Solr field to be stored.

The field attribute has four attributes, listed below.

name

The name attribute specifies the name of a Solr field in which to store data. A field with a matching name should be defined in the Solr schema.

The name attribute is mandatory.

value

The value attribute specifies the data to be used from HBase for populating the field in Solr. It takes the form of a column family name and qualifier, separated by a colon.

The qualifier portion can end in an asterisk, which is interpreted as a wildcard. In this case, all matching column-family and qualifier expressions will be used.

The following are examples of valid value attributes:

  • mycolumnfamily:myqualifier
  • mycolumnfamily:my*
  • mycolumnfamily:*

source

The source attribute determines what portion of an HBase KeyValue will be used as indexing content.

It has two possible values: value and qualifier.

When value is specified (which is the case by default), then the cell value is used as input for indexing.

When qualifier is specified, then the column qualifier is used as input for indexing.

type

The type attribute defines the datatype of the content in HBase.

Because all data is stored in HBase as byte arrays, but all content in Solr is indexed as text, a method for converting from byte arrays to the actual datatype is needed.

The value of this field can be one of any of the datatypes supported by the HBase Bytesclass: int, long, string, boolean, float, double, short, or bigdecimal.

If the Bytes-based representation has not been used for storing data in HBase, the name of a custom class can be specified for this attribute. The custom class must implement the

com.ngdata.hbaseindexer.parse.ByteArrayValueMapper

interface.

<param>

The <param> element defines a key-value pair that will be supplied to custom classes that implement the

com.ngdata.hbaseindexer.Configurable

interface.

<param> elements can also be nested in a <field> element.

The element has two attributes: name and value. Both are mandatory.

Example configuration

The example configuration below demonstrates all elements and attributes that can be used to configure an indexer.


&lt;!--
   Do row-based indexing on table "table1", never re-reading updated content.
   Store the unique document id in Solr field called "custom-id".
   Additionally store the row key in a Solr field called "custom-row", and store the
   column family in a Solr field called "custom-family".

   Perform conversion of byte array keys using the class "com.mycompany.MyKeyFormatter".
--&gt;
&lt;indexer
    table="table1"
    mapping-type="row"
    read-row="never"
    unique-key-field="custom-id"
    row-field="custom-row"
    column-family-field="custom-family"
    table-name-field="custom-table"
    unique-key-formatter="com.mycompany.MyKeyFormatter"
    &gt;

  &lt;!-- A float-based field taken from any qualifier in the column family "colfam" --&gt;
  &lt;field name="field1" value="colfam:*" source="qualifier" type="float"/&gt;

  &lt;param name="globalKeyA" value="globalValueA"/&gt;
  &lt;param name="globalKeyB" value="globalValueB"/&gt;

&lt;/indexer&gt;

 

 

CDH中Lily HBase Indexer(Key-value Store Indexer)的配置使用

CDH版本: 4.5.7

前段时间在学习Solr的知识。做了一个测试系统,精确查询使用HBase来做,模糊查询使用Solr。

Hbase的数据录入直接采用原生API,效率还不错。但是当向Solr录入数据建立索引时时常会发生异常。

所以学习了一下Lily Hbase Indexer来为Hbase的数据在solr建立索引。

 

1.在 HBase 列系列上启用复制

确保已启用群集范围内的 HBase 复制。使用 HBase shell 定义列系列复制设置。

对于每个现有表,在需要通过发出格式命令进行索引的每个列系列上设置 REPLICATION_SCOPE

$ hbase shell
hbase shell> disable 'record'
hbase shell> alter 'record', {NAME => 'data', REPLICATION_SCOPE => 1}
hbase shell> enable 'record'

对于每个新表,在需要通过发出格式命令进行索引的每个列系列上设置 REPLICATION_SCOPE

$ hbase shell hbase shell> create 'record', {NAME => 'data', REPLICATION_SCOPE => 1}

2.创建相应的 SolrCloud 集合

用于 HBase 索引的 SolrCloud 集合必须具有可容纳 HBase 列系列的类型和要进行索引处理的限定符的 Solr 架构。使用以下表单命令创建 SolrCloud 集合:

<1>生产实体配置文件:
    $ solrctl instancedir --generate /etc/solr/conf/record
<2>编辑Collection的Schema.xml文件,根据自己的需求确定。
    $ edit /etc/solr/conf/record/conf/schema.xml 
<3>上传实体配置文件至zookeeper
    $ solrctl instancedir --create record /etc/solr/conf/record
<4>使用实体配置文件建立collection
    $ solrctl collection --create record

3.创建 Lily HBase Indexer 配置

$ vi /etc/solr/conf/morphline-hbase-mapper.xml

<?xml version="1.0"?>
<indexer table="record" mapper="com.ngdata.hbaseindexer.morphline.MorphlineResultToSolrMapper">

   <!-- The relative or absolute path on the local file system to the morphline configuration file. -->
   <!-- Use relative path "morphlines.conf" for morphlines managed by Cloudera Manager -->
   <param name="morphlineFile" value="/etc/hbase-solr/conf/morphlines.conf"/>

   <!-- The optional morphlineId identifies a morphline if there are multiple morphlines in morphlines.conf -->
   <!-- <param name="morphlineId" value="morphline1"/> -->

</indexer>

4.创建 Morphline 配置文件.

在CDH 管理界面进入Key-Value Store Indexer面板->配置->服务范围->Morphlines->Morphlines文件。
$ vi /etc/hbase-solr/conf/morphlines.conf

morphlines : [
  {
    id : morphline1
    importCommands : ["org.kitesdk.morphline.**", "com.ngdata.**"]

    commands : [                    
      {
        extractHBaseCells {
          mappings : [
            {
              inputColumn : "data:title"
              outputField : "title"
              type : string 
              source : value
            }

            {
              inputColumn : "data:subject"
              outputField : "subject"
             type : "byte[]"
             source : value
            }
          ]
        }
      }

      #for avro use with type : "byte[]" in extractHBaseCells mapping above
      #{ readAvroContainer {} } 
      #{ 
      #  extractAvroPaths {
      #    paths : { 
      #      data : /user_name      
      #    }
      #  }
      #}

      { logTrace { format : "output record: {}", args : ["@{}"] } }
    ]
  }
]

id:表示当前morphlines文件的ID名称。

importCommands:需要引入的命令包地址。

extractHBaseCells:该命令用来读取HBase列数据并写入到SolrInputDocument对象中,该命令必须包含零个或者多个mappings命令对象。

mappings:用来指定HBase列限定符的字段映射。

inputColumn:需要写入到solr中的HBase列字段。值包含列族和列限定符,并用‘ : ’分开。其中列限定符也可以使用通配符‘*’来表示,譬如可以使用data:*表示读取只要列族为data的所有hbase列数据,也可以通过data:my*来表示读取列族为data列限定符已my开头的字段值。

outputField:用来表示morphline读取的记录需要输出的数据字段名称,该名称必须和solr中的schema.xml文件的字段名称保持一致,否则写入不正确。

type:用来定义读取HBase数据的数据类型,我们知道HBase中的数据都是以byte[]的形式保存,但是所有的内容在Solr中索引为text形式,所以需要一个方法来把byte[]类型转换为实际的数据类型。type参数的值就是用来做这件事情的。现在支持的数据类型有:byte[](原封不动的拷贝hbase中的byte[]数据),int,long,string,boolean,float,double,short和bigdecimal。当然你也可以指定自定的数据类型,只需要实现com.ngdata.hbaseindexer.parse.ByteArrayValueMapper接口即可。

source:用来指定HBase的KeyValue那一部分作为索引输入数据,可选的有‘value’和’qualifier’,当为value的时候表示使用HBase的列值作为索引输入,当为qualifier的时候表示使用HBase的列限定符作为索引输入。

5.注册Lily HBase Indexer配置文件到Lily HBase Indexer Service服务中

当前面的所有步骤完成之后,我们需要把Lily HBase Indexer的配置文件注册到Zookeeper中,使用如下命令:

hbase-indexer add-indexer -n recordIndexer -c /etc/solr/conf/morphline-hbase-mapper.xml –connection-param  solr.zk=xhadoop1:2181,xhadoop2:2181,xhadoop3:2181,xhadoop4:2181,xhadoop5:2181/solr  –connection-param solr.collection=record –zookeeper xhadoop1:2181,xhadoop2:2181,xhadoop3:2181,xhadoop4:21281,xhadoop5:2181

当前面5条全部按序完成后,就可以测试hbase数据输入Solr索引数据了。

6.HBase写入数据

向HBase中配置的索引表写入数据,如下:

put ‘record’,’row6′,’data:title’,’Good Luck!My love’
当写入数据后,稍过几秒我们可以在相对于的solr中查询到该插入的数据,表明配置已经成功。

{ “responseHeader“: { “status“: 0, “QTime“: 14, “params“: { “q“: “title:Good”, “_“: “1447069417938”, “wt“: “json” } }, “response“: { “numFound“: 1, “start“: 0, “maxScore“: 0.15342641, “docs“: [ { “id“: “row6”, “title“: [ “Good Luck!My love” ], “_version_“: 1517358513903370200 } ] } }

Zookeeper的Quorum机制-谈谈怎样解决脑裂(split-brain)

在使用zookeeper的过程中,我们经常会看到这样一些说法:

1.zookeeper cluster的节点数目必须是奇数。

2.zookeeper 集群中必须超过半数节点(Majority)可用,整个集群才能对外可用。

这个说法在大多数情况下是正确的。

实际上ZooKeeper提供了几种方式来认定整个集群是否可用,Majority只是其中的一种。

(http://zookeeper.apache.org/doc/r3.3.5/zookeeperInternals.html)

1. Majority Quorums

2. Weight

3. Hierarchy of groups

所谓整个集群是否可用,隐含的一个意思就是整个集群还能够选举出一个”Leader”。

ZooKeeper默认设置的是采用Majority Qunroms的方式来支持Leader选举。在ZooKeeper中Quorums有2个作用:

1. 集群中最少的节点数用来选举Leader保证集群可用

2. 通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据

采用Quoroms投票的方式来选举Leader主要是为了解决“Split-Brain”问题( http://linux-ha.org/wiki/Split_Brain)。

Split-Brain问题说的是1个集群如果发生了网络故障,很可能出现1个集群分成了两部分,而这两个部分都不知道对方是否存活,不知道到底是网络问题还是直接机器down了,所以这两部分都要选举1个Leader,而一旦两部分都选出了Leader, 并且网络又恢复了,那么就会出现两个Brain的情况,整个集群的行为不一致了。

所以集群要防止出现Split-Brain的问题出现,Quoroms是一种方式,即只有集群中超过半数节点投票才能选举出Leader。

这样的方式可以确保leader的唯一性,要么选出唯一的一个leader,要么选举失败.

ZooKeeper默认采用了这种方式。更广义地解决Split-Brain的问题,一般有3种方式:

1.  Quorums

2. 采用Redundant communications,冗余通信的方式,集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。

3. Fencing, 共享资源的方式,比如能看到共享资源就表示在集群中,能够获得共享资源的锁的就是Leader,看不到共享资源的,就不在集群中

理解了Quorums就不难理解为什么集群中的节点数一般配置为奇数。节点数配置成奇数的集群的容忍度更高。

比如3个节点的集群,Quorums = 2, 也就是说集群可以容忍1个节点失效,这时候还能选举出1个lead,集群还可用

比如4个节点的集群,它的Quorums = 3,Quorums要超过3,相当于集群的容忍度还是1,如果2个节点失效,那么整个集群还是无效的

所以4个节点的集群的容忍度 = 3个节点的集群的容忍度,但是4个节点的集群多了1个节点,相当于浪费了资源。

更极端的例子是100个节点的集群,如果网络问题导致分为两个部分,50个节点和50个节点,这样整个集群还是不可用的,因为按照Quorums的方式必须51个节点才能保证选出1个Leader。这时候可以采用Weight加权的方式,有些节点的权值高,有些节点的权值低,最后计算权值,只要权值过半,也能选出1个Leader

solr设置schema.xml以支持中文数据上传

1.在设置solr的schema.xml中field时,如果想要索引或存储中文数据,需要将该field的type设为class为solr.StrField的fieldType.

比如想要username存储中文数据,那么设置如下:

<field name=”username” type=”string” indexed=”true” stored=”false”/>

<fieldType name=”string” class=”solr.StrField” sortMissingLast=”true” />

2.当solr文档中有中文数据时,有时候查询的时候会发现无法查到这些数据,可以尝试的解决方法是调整tomcat的编码方式。

方法:

修改tomcat配置目录conf下的server.xml。

原配置:

<Connector port=”8787″ protocol=”HTTP/1.1″
connectionTimeout=”20000″
redirectPort=”8443″ />

修改后配置:

<Connector port=”8787″ protocol=”HTTP/1.1″
connectionTimeout=”20000″
URIEncoding=”UTF-8″
redirectPort=”8443″ />

即添加了URIEncoding=”UTF-8″。

附:solr内置字段类型

字段类型在org.apache.solr.schema包下

Class 描述
BCDIntField 二进制整形字段
BCDLongField 二进制长整形字段
BCDStrField 二进制字符型字段
BinaryField 二进制数据
BoolField 包含true或者false,值的第一个字符如果是1、t、T均表示true,其他为false
ByteField 一个字节数据
DateField 一个精确到毫秒的时间值
DoubleField
ExternalFileField 从硬盘读取文件作为该字段的值
FloatField
IntField
Location 方位搜索用到,存经纬度值
LongField
Point N维点搜索,在蓝图或者CAD图中使用
RandomSortField 不包含值,当查询时按这种类型的字段排序时会产生随机排序。使用该特性时需要是一个动态字段
ShortField
StrField UTF-8编码的字符串或Unicode
TextField 文本类型,一般包含多个单词或汉字
UUIDField 唯一识别码,单传入的值是“NEW”时,Solr将为其创建1个UUID值

solrCloud4.10.4+zookeeper3.3.6在Centos上的安装及使用

Apache SolrCloud安装

SolrCloud通过ZooKeeper集群来进行协调,使一个索引进行分片,各个分片可以分布在不同的物理节点上,多个物理分片组成一个完成的索引Collection。SolrCloud自动支持Solr Replication,可以同时对分片进行复制,冗余存储。下面,我们基于Solr4.10.4版本进行安装配置SolrCloud集群。

1. 安装环境

我使用的安装程序各版本如下:

  • Solr:  solr-4.10.4
  • Tomcat: apache-tomcat-7.0.62
  • ZooKeeper: zookeeper-3.3.6

各个目录说明:

  • 所有的程序安装在/usr/solrcloud/目录下,你可以依照你的实际情况下修改安装目录。
  • ZooKeeper的数据目录在:/usr/solrcloud/data
  • solrhome(collection的数据存储位置)设置在:/usr/solrcloud/solr-home
  • solrconf(collection的配置文件位置)设置在:/usr/solrcloud/solr-conf

2. 规划SolrCloud

  • 单一SolrCloud数据集合:mycollection
  • ZooKeeper集群:3台
  • SolrCloud实例:3节点
  • 索引分片:3
  • 复制因子:2

手动将3个索引分片(Shard)的复本(Replica)分布在2个SolrCloud节点上

三个节点:

  • 192.168.1.111
  • 192.168.1.112
  • 192.168.56.113

3. 安装ZooKeeper集群

由于需要用到ZooKeeper来存储集群的collection 信息以及collection的配置文件,所以先安装好ZooKeeper集群。

首先,在第一个节点上将zookeeper-3.3.6.tar.gz解压到/usr/solrcloud/目录:

$ tar zxvf zookeeper-3.3.6.tar.gz -C /usr/solrcloud/

创建zookeeper配置文件zookeeper-3.3.6/conf/zoo.cfg,内容如下:

tickTime=2000 
initLimit=10
syncLimit=5 
dataDir=/usr/solrcloud/data 
clientPort=2281 
server.1=192.168.1.111:2988:3988
server.2=192.168.1.112:2988:3988
server.3=192.168.1.113:2988:3988

zookeeper的数据目录指定在

/usr/solrcloud/data,你也可以使用其他目录,通过下面命令进行创建该目录:
$ mkdir /usr/solrcloud/data -p

然后,初始化myid,三个节点编号依次为1,2,3,在其余节点上分别执行命令(注意修改编号)。

$ echo "1" >/usr/solrcloud/data/myid

然后,在第二个和第三个节点上依次重复上面的操作。这样第一个节点中myid内容为1,第二个节点为2,第三个节点为3。

最后,启动ZooKeeper集群,在每个节点上分别启动ZooKeeper服务:

$ /usr/solrcloud/zookeeper-3.3.6/bin/zkServer.sh start

可以查看ZooKeeper集群的状态,保证集群启动没有问题:

[root@192.168.56.121 opt]# sh zookeeper-3.3.6/bin/zkServer.sh status 
JMX enabled by default
Using config: /usr/solrcloud/zookeeper-3.3.6/bin/../conf/zoo.cfg
Mode: follower
注意:当第一台机器启动zookeeper的时候运行status命令会显示错误,可能的原因是其它的机器还未启动zookeeper。

4. 安装Solr

solr的安装分为几个步骤,执行以下命令:

在执行如下操作之前建立三个文件

(1)/usr/solrcloud/solr-home

(2)/usr/solrcloud/solr-libs

(3)/usr/solrcloud/solr-conf

命令如下:

mkdir -p /usr/solrcloud/solr-home

mkdir -p /usr/solrcloud/solr-libs

mkdir -p /usr/solrcloud/solr-conf

然后进行如下操作:

1.解压缩apache-tomcat-7.0.62.tar.gz到/usr/solrcloud/tomcat 目录中      

tar xzvf  apache-tomcat-7.0.62.tar.gz & mv  apache-tomcat-7.0.62 tomcat.

2.解压缩solr-4.10.4.zip到/usr/solrcloud/solrsrc

unzip solr-4.10.4.zip -d /usr/solrcloud/solrsrc.

3.首先把solr-4.10.4/example/webapps/solr.war解压缩,然后复制到tomcat的webapps下面

$ cp solr-4.10.4/example/webapps/solr.war tomcat/webapps/

4.把solr-4.10.4/example/lib/ext/下所有jar文件copy到tomcat/webapps/solr/WEB-INF/lib/下   

$ cp solr-4.10.4/example/lib/ext/*tomcat/webapps/solr/WEB-INF/lib/

5.把solr-4.10.4/example/resources/log4j.properties 复制 tomcat/lib/ 下   

$ cp solr-4.10.4/example/resources/log4j.properties tomcat/lib/

6.把solr-4.10.4/example/solr/solr.xml复制到/usr/solrcloud/solr-home中    

$ cp solr-4.10.4/example/solr/solr.xml /usr/solrcloud/solr-home

7.在/usr/solrcloud/solr-conf下面建立一个core目录,例如mycollection

mkdir -p /usr/solrcloud/solr-conf/mycollection

8.复制solr-4.10.4/example/solr/collection1/conf 到/usr/solrcloud/solr-conf/mycollection/conf     

$ cp solr-4.10.4/example/solr/collection1/conf /usr/solrcloud/solr-conf/mycollection/conf

9.修改tomcat的启动端口为8787

vi tomcat/conf/server.xml

把所有的8080修改为8787

10.修改/usr/solrcloud/solr-home/solr.xml的 hostPort 节点的端口号为tomcat的端口号  

<int name=”hostPort”>${jetty.port:8787}</int>

在其他节点上重复以上操作完成所有节点的solr的安装。

11.启动tomcat,当solr.war解压后关闭tomcat
tomcat/bin/startup.sh
tomcat/bin/shutdown.sh
12.复制tomcat/webapps/solr/WEB-INF/lib/下所有的文件到/usr/solrcloud/solr-libs
cp tomcat/webapps/solr/WEB-INF/lib/* /usr/solrcloud/solr-libs

5. Tomcat配置与启动

首先说一下如何自动创建Collection及初始Shard,不需要通过zookeeper手动上传配置文件并关联collection。

1、在第一个节点修改tomcat启动参数

JAVA_OPTS='-Djetty.port=8787 -Dsolr.solr.home=/usr/solrcloud/solr-home -DzkHost=192.168.1.111:2281,192.168.1.112:2281,192.1.113:2281 -DnumShards=3 -Dbootstrap_confdir=/usr/solrcloud/solr-conf/mycollection/conf -Dcollection.configName=myconf'

然后启动tomcat。这个步骤上传了集群的相关配置信息(/home/solrcloud/solr-config/mycollectin/conf)到ZooKeeper中去,所以启动下一个节点时不用再指定配置文件了。

!!!下面的操作可以不做,只是为了演示下自动创建collection时配置文件是怎样让其它机器所知悉的。

在zookeeper的bin目录下运行zkCli.sh,会自动监听本地的2181端口,但由于我们改变了zookeeper的默认client端口,所以需要用-server来指定本地端口。

$ /usr/solrcloud/zookeeper-3.3.6/bin/zkCli.sh -server 127.0.0.1:2281

接着运行 ls /configs可以看到已经传到zookeeper的collection的配置文件。

[zk: 127.0.0.1:2281(CONNECTED) 1] ls /configs
[t1_conf, myconf]

[zk: 127.0.0.1:2281(CONNECTED) 2] ls /collections
[t3, t2, t1, mycollection]

这样zookeeper就拥有了collection名称,配置文件以及该配置的名称,其它机器就可以从zookeeper中获取到该配置信息了。

 

2、在第二个和第三个节点修改tomcat启动参数

JAVA_OPTS='-Djetty.port=8787 -Dsolr.solr.home=/usr/solrcloud/solr-home -DzkHost=192.168.1.111:2281,192.168.1.112:2281,192.1.113:2281 -DnumShards=3'

然后启动tomcat。

这样就会创建3个shard分别分布在三个节点上,如果你再增加一个节点,这节点会附加到一个shard上成为一个replica,而不会创建新的shard。

6. 建立core跟share的一些命令

curl 'http://192.168.1.111:8787/solr/admin/collections?action=CREATE&name=mycollection&numShards=3&replicationFactor=1'

上面链接中的几个参数的含义,说明如下:

  • name 待创建Collection的名称
  • numShards 分片的数量
  • replicationFactor 复制副本的数量

可以通过Web管理页面,访问http://192.168.1.111:8787/solr/#/~cloud,查看SolrCloud集群的分片信息。

7.手动创建Replication

下面对已经创建的初始分片进行复制。 shard1已经在192.168.1.113上,我们复制分片到192.168.1.111和192.168.1.112上,执行如下命令:

$ curl 'http://192.168.56.111:8787/solr/admin/cores?action=CREATE&collection=mycollection&name=mycollection_shard1_replica_2&shard=shard1' 
$ curl 'http://192.168.56.112:8787/solr/admin/cores?action=CREATE&collection=mycollection&name=mycollection_shard1_replica_3&shard=shard1'

最后的结果是,192.168.1.113上的shard1,在192.168.1.111节点上有1个副本,名称为mycollection_shard1_replica_2,在192.168.1.112节点上有一个副本,名称为mycollection_shard1_replica_3。也可以通过查看192.168.1.111和192.168.1.112上的目录变化.

你还可以对shard2和shard3添加副本。

8.如何手动创建Collection及初始 Shard?

1.首先上传solrhome配置

java -classpath .:/usr/solrcloud/solr-libs/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.1.111:2281,192.168.1.112:2281,192.168.1.113:2281 -cmd bootstrap -solrhome /usr/solrcloud/solr-home
2.上传自定义的collection配置信息

java -classpath .:/usr/solrcloud/solr-libs/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.1.111:2281,192.168.1.112:2281,192.168.1.113:2281 -cmd upconfig -confdir /usr/solrcloud/solr-conf/t1_collection/conf -confname t1_conf

这条命令是把/usr/solrcloud/solr-conf/t1_collection/conf上传到zookeeper的configs里面,并且以t1_conf命名。
3.java -classpath .:/usr/solrcloud/solr-libs/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.1.111:2281,192.168.1.112:2281,192.168.1.113:2281 -cmd linkconfig -collection t1 -confname t1_conf

这条命令把collection t1与配置t1_conf绑定。

4.curl “http://192.168.1.111/solr/admin/collections?action=CREATE&name=t2_collection&numShards=3&replicationFactor=2&maxShardsPerNode=2&collection.configName=t1_conf”

当在zookeeper里面上传了若干collection配置之后,可以在创建collection时通过collection.configName来指定collection的配置。这也解决了多个不同配置的core共存的问题。

 

solrCloud常用命令记录

/admin/collections?action=CREATE: create a collection
/admin/collections?action=RELOAD: reload a collection
/admin/collections?action=SPLITSHARD: split a shard into two new shards
/admin/collections?action=CREATESHARD: create a new shard
/admin/collections?action=DELETESHARD: delete an inactive shard
/admin/collections?action=CREATEALIAS: create or modify an alias for a collection
/admin/collections?action=DELETEALIAS: delete an alias for a collection
/admin/collections?action=DELETE: delete a collection
/admin/collections?action=DELETEREPLICA: delete a replica of a shard
/admin/collections?action=ADDREPLICA: add a replica of a shard
/admin/collections?action=CLUSTERPROP: Add/edit/delete a cluster-wide property
/admin/collections?action=MIGRATE: Migrate documents to another collection
/admin/collections?action=ADDROLE: Add a specific role to a node in the cluster
/admin/collections?action=REMOVEROLE: Remove an assigned role
/admin/collections?action=OVERSEERSTATUS: Get status and statistics of the overseer
/admin/collections?action=CLUSTERSTATUS: Get cluster status
/admin/collections?action=REQUESTSTATUS: Get the status of a previous asynchronous request
/admin/collections?action=LIST: List all collections

solrCloud探索之概念解析

solrCloud是基于solr与zookeeper的的分布式搜索方案。它的中心思想是使用zookeeper作为集群的配置信息中心.

solrCloud具有如下特点:

  • 集中式的配置信息
  • 自动容错
  • 近实时搜索
  • 查询时自动负载均衡

而现在要说的是涉及自动容错的自动负载均衡的几个名词解析。

1.shard与Replica

英文中shard是碎片的意思.在solrCloud中它代表collection的某个分片.

shard是collection的逻辑分片,实际上承载shard的是分布在每个solr物理节点上的replica.

  • shard的作用是什么?

答:逻辑上通过创建多个shard,collection被均匀分布到不同的节点,通过子查询的方式实现了查询时负载均衡功能,提高了查询效率,能够有效减轻服务器的查询压力。

replica英文中是复制品的意思,在solrCloud中它代表shard的物理复制品.

真实环境下,shard是以Replica的形式存储在solrCloud节点机器上的。

  • replica的作用是什么?

答: 顾名思义,复制品当然可以有多份。在solrCloud的世界,shard可以被复制多份存储在不同的节点上。

shard与replica的关系就像是鬼故事里面鬼魂与肉身的关系.

replica不仅是shard的物理载体,它还能实现solrCloud的自动容错功能。

每个shard的多个replica要选举出一个leader.

选举replica leader的作用在于当建立索引时,文档会首先传给leader,然后由leader负责将文档路由给同shard的所有replica实现数据的同步。

  • collection的逻辑图示

solr2

在创建collection时可以通过设置numShards来指定shard的数目.

 

下图是实际操作的效果示例(solr节点地址因为隐私问题被覆盖):

比如创建一个名字为test05_collection的collection,分为4片,每片复制2份.

action=CREATE&name=test05_collection&numShards=4&replicationFactor=2&maxShardsPerNode=3

  • collection逻辑实例

 

 

solr1

 

在上图可以看到,collection被分为了4部分,每个部分被复制成2份放到了solrCloud的2台不同的节点上。

redhat6.3一键安装L2TP脚本

Tips:
1.灵活设置自己的公网IP
tmpip=`ifconfig |grep ‘inet’ | grep -Evi ‘(inet6|127.0.0.1)’ | awk ‘{print $2}’ | cut -d: -f2 | head -1`
这行代码是检测网卡IP的,使用head或tail合理选择自己的公网IP
2.如果是SSH非root登录的系统,首先要 su root,然后进入/root或者注释掉程序开头对root身份的认证.
3.最后ipsec verify的结果如果出现下述情况:
<1>Two or more interfaces found, checking IP forwarding [FAILED]
那么请运行如下命令:
cat /proc/sys/net/ipv4/ip_forward
如果结果是1,请忽略这个FAILED.

<2>Checking for IPsec support in kernel [FAILED]
SAref kernel support [N/A]
Checking that pluto is running [FAILED]

如果出现上述情况,请执行下述命令:

ipsec setup start

再次执行ipsec verify查看.

 

——————————CODE BEGIN————————————–

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#===============================================================================================
# SYSTEM REQUIRED: CentOS 6 (32bit/64bit)
# DESCRIPTION: Auto install L2TP for CentOS 6
# Author: Teddysun <i@teddysun.com>
#===============================================================================================

if [[ “$USER” != ‘root’ ]]; then
echo “Sorry, you need to run this as root”
echo $USER
exit 1
fi

if [[ ! -e /dev/net/tun ]]; then
echo “TUN/TAP is not available”
exit 1
fi

clear
echo “”
echo “#############################################################”
echo “# Auto install L2TP for CentOS 6/RedHat 6 #”
echo “# System Required: CentOS/RedHat(32bit/64bit) #”
echo “# Intro: ~~~ #”
echo “# Author: ~~~ #”
echo “#############################################################”
echo “”

tmpip=`ifconfig |grep ‘inet’ | grep -Evi ‘(inet6|127.0.0.1)’ | awk ‘{print $2}’ | cut -d: -f2 | head -1`
if [[ “$tmpip” = “” ]]; then
tmpip=$(curl -4 icanhazip.com)
fi

echo “Please input IP-Range:”
read -p “(Default Range: 10.1.2):” iprange
if [ “$iprange” = “” ]; then
iprange=”10.1.2″
fi

echo “Please input PSK:”
read -p “(Default PSK: vpn):” mypsk
if [ “$mypsk” = “” ]; then
mypsk=”vpn”
fi

clear
get_char(){
SAVEDSTTY=`stty -g`
stty -echo
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
echo “”
echo “ServerIP:”
echo “$tmpip”
echo “”
echo “Server Local IP:”
echo “$iprange.1”
echo “”
echo “Client Remote IP Range:”
echo “$iprange.2-$iprange.254”
echo “”
echo “PSK:”
echo “$mypsk”
echo “”
echo “Press any key to start…or Press Ctrl+c to cancel”
char=`get_char`
clear

mknod /dev/random c 1 9
# Install some necessary tools
yum install -y ppp iptables make gcc gmp-devel xmlto bison flex libpcap-devel lsof vim-enhanced
#
cur_dir=`pwd`
mkdir -p $cur_dir/l2tp
cd $cur_dir/l2tp
# Download openswan-2.6.38.tar.gz
if [ -s openswan-2.6.38.tar.gz ]; then
echo “openswan-2.6.38.tar.gz [found]”
else
echo “openswan-2.6.38.tar.gz not found!!!download now……”
if ! wget http://lamp.teddysun.com/files/openswan-2.6.38.tar.gz;then
echo “Failed to download openswan-2.6.38.tar.gz, please download it to $cur_dir directory manually and retry.”
exit 1
fi
fi
# Download rp-l2tp-0.4.tar.gz
if [ -s rp-l2tp-0.4.tar.gz ]; then
echo “rp-l2tp-0.4.tar.gz [found]”
else
echo “rp-l2tp-0.4.tar.gz not found!!!download now……”
if ! wget http://lamp.teddysun.com/files/rp-l2tp-0.4.tar.gz;then
echo “Failed to download rp-l2tp-0.4.tar.gz, please download it to $cur_dir directory manually and retry.”
exit 1
fi
fi
# Download xl2tpd-1.2.4.tar.gz
if [ -s xl2tpd-1.2.4.tar.gz ]; then
echo “xl2tpd-1.2.4.tar.gz [found]”
else
echo “xl2tpd-1.2.4.tar.gz not found!!!download now……”
if ! wget http://lamp.teddysun.com/files/xl2tpd-1.2.4.tar.gz;then
echo “Failed to download xl2tpd-1.2.4.tar.gz, please download it to $cur_dir directory manually and retry.”
exit 1
fi
fi

# untar all files
rm -rf $cur_dir/l2tp/untar
mkdir -p $cur_dir/l2tp/untar
echo “======untar all files,please wait a moment=====”
tar -zxf openswan-2.6.38.tar.gz -C $cur_dir/l2tp/untar
tar -zxf rp-l2tp-0.4.tar.gz -C $cur_dir/l2tp/untar
tar -zxf xl2tpd-1.2.4.tar.gz -C $cur_dir/l2tp/untar
echo “=====untar all files completed!=====”
# Install openswan-2.6.38
cd $cur_dir/l2tp/untar/openswan-2.6.38
make programs install

# Configuation ipsec
rm -rf /etc/ipsec.conf
touch /etc/ipsec.conf
cat >>/etc/ipsec.conf<>/etc/ipsec.secrets< $each/accept_redirects
echo 0 > $each/send_redirects
done

# Install rp-l2tp-0.4
cd $cur_dir/l2tp/untar/rp-l2tp-0.4
./configure
make
cp handlers/l2tp-control /usr/local/sbin/
mkdir -p /var/run/xl2tpd/
ln -s /usr/local/sbin/l2tp-control /var/run/xl2tpd/l2tp-control
# Install xl2tpd-1.2.4.tar.gz
cd $cur_dir/l2tp/untar/xl2tpd-1.2.4
make install
mkdir -p /etc/xl2tpd
rm -rf /etc/xl2tpd/xl2tpd.conf
touch /etc/xl2tpd/xl2tpd.conf
cat >>/etc/xl2tpd/xl2tpd.conf<>/etc/ppp/options.xl2tpd<> /etc/ppp/chap-secrets

touch /usr/bin/l2tpset
echo “#/bin/bash” >>/usr/bin/l2tpset
echo “for each in /proc/sys/net/ipv4/conf/*” >>/usr/bin/l2tpset
echo “do” >>/usr/bin/l2tpset
echo “echo 0 > \$each/accept_redirects” >>/usr/bin/l2tpset
echo “echo 0 > \$each/send_redirects” >>/usr/bin/l2tpset
echo “done” >>/usr/bin/l2tpset
chmod +x /usr/bin/l2tpset
iptables –table nat –append POSTROUTING –jump MASQUERADE
l2tpset
xl2tpd
cat >>/etc/rc.local< #
#############################################################
if there are no [FAILED] above, then you can connect to your
L2TP VPN Server with the default user/password below:

ServerIP:$tmpip
username:vpn
password:${pass}
PSK:$mypsk

exit 0

HBase中zookeeper与用户表的关系

image0030

HBase中有两张特殊的表 -ROOT- .META.

.META.记录用户表的Region信息,且.META.表可以被split
-ROOT-记录.META.的Region信息,用来记录.META表被分到了哪些RegionServer上
zookeeper记录了-ROOT-的位置.

Client访问用户数据之前需要首先访问zookeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过client端会做cache缓存.