solrcloud集群搭建

  1. 什么是SolrCloud
    1. 什么是SolrCloud

SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用SolrCloud来满足这些需求。

    1. SolrCloud结构

SolrCloud为了降低单机的处理压力,需要由多台服务器共同来完成索引和搜索任务。实现的思路是将索引数据进行Shard(分片)拆分,每个分片由多台的服务器共同完成,当一个索引或搜索请求过来时会分别从不同的Shard的服务器中操作索引。

solrcloud集群搭建

SolrCloud需要Solr基于Zookeeper部署,Zookeeper是一个集群管理软件,由于SolrCloud需要由多台服务器组成,由zookeeper来进行协调管理。

下图是一个SolrCloud应用的例子:

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

对上图进行图解,如下:

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

      1. 物理结构

三个Solr实例( 每个实例包括两个Core),组成一个SolrCloud。

      1. 逻辑结构

索引集合包括两个Shard(shard1和shard2),shard1和shard2分别由三个Core组成,其中一个Leader两个Replication,Leader是由zookeeper选举产生,zookeeper控制每个shard上三个Core的索引数据一致,解决高可用问题。

用户发起索引请求分别从shard1和shard2上获取,解决高并发问题。

        1. collection

Collection在SolrCloud集群中是一个逻辑意义上的完整的索引结构。它常常被划分为一个或多个Shard(分片),它们使用相同的配置信息。

比如:针对商品信息搜索可以创建一个collection。

collection=shard1+shard2+....+shardX

        1. Core

每个Core是Solr中一个独立运行单位,提供 索引和搜索服务。一个shard需要由一个Core或多个Core组成。由于collection由多个shard组成所以collection一般由多个core组成。

        1. Master或Slave

Master是master-slave结构中的主结点(通常说主服务器),Slave是master-slave结构中的从结点(通常说从服务器或备服务器)。同一个Shard下master和slave存储的数据是一致的,这是为了达到高可用目的。

        1. Shard

Collection的逻辑分片。每个Shard被化成一个或者多个replication,通过选举确定哪个是Leader。

  1. SolrCloud搭建

SolrCloud结构图如下:

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

    1. 环境准备

CentOS-6.5-i386-bin-DVD1.iso

jdk-7u72-linux-i586.tar.gz

apache-tomcat-7.0.57.tar.gz

zookeeper-3.4.6.tar.gz

solr-4.10.3.tgz

服务器7台:

zookeeper三台:192.168.0.5,192.168.0.6,192.168.0.7

Solr四台:192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.4

    1. 环境安装
    1. CentOs 6.5安装

    1. jdk7安装

    1. zookeeper集群安装
      1. 解压zookeeper 安装包

tar -zxvf zookeeper-3.4.6.tar.gz

将zookeeper-3.4.6拷贝到/usr/local下并将目录 名改为zookeeper

至此zookeeper的安装目录为/usr/local/zookeeper

      1. 进入zookeeper文件夹,创建data 和logs

创建目录并赋于写权限

指定zookeeper的数据存放目录和日志目录

      1. 拷贝zookeeper配制文件zoo_sample.cfg

拷贝zookeeper配制文件zoo_sample.cfg并重命名zoo.cfg

cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper /conf/zoo.cfg

      1. 修改zoo.cfg

加入 dataDir=/usr/local/zookeeper/data

dataLogDir=/ usr/local/zookeeper/logss

server.1=192.168.0.5:2888:3888

server.2=192.168.0.6:2888:3888

server.3=192.168.0.7:2888:3888

zoo.cfg配制完后如下:

# The number of milliseconds of each tick

tickTime=2000

# The number of ticks that the initial

# synchronization phase can take

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

# do not use /tmp for storage, /tmp here is just

# example sakes.

dataDir=/usr/local/zookeeper/data

# the port at which the clients will connect

clientPort=2181

# the maximum number of client connections.

# increase this if you need to handle more clients

#maxClientCnxns=60

#

# Be sure to read the maintenance section of the

# administrator guide before turning on autopurge.

#

# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance

#

# The number of snapshots to retain in dataDir

#autopurge.snapRetainCount=3

# Purge task interval in hours

# Set to "0" to disable auto purge feature

#autopurge.purgeInterval=1

#dataLogDir=/usr/local/zookeeper/logs

server.1=192.168.0.5:2888:3888

server.2=192.168.0.6:2888:3888

server.3=192.168.0.7:2888:3888

      1. 进入data文件夹 建立对应的myid文件

例如server.1为192.168.0.5则 data文件夹下的myid文件内容为1

echo "1" >> myid

server.2为192.168.0.6则 data文件夹下的myid文件内容为2

依此类推

      1. 拷贝zookeeper文件夹到其他机器(192.168.0.6和192.168.0.7)
      2. 开启zookeeper的端口

/sbin/iptables -I INPUT -p tcp --dport 2181 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 2888 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 3888 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT --这里开启tomcat 8080端口

/etc/rc.d/init.d/iptables save #将更改进行保存

/etc/init.d/iptables restart #重启防火墙以便改动生效

      1. 启动三台服务器的zookeeper

进入/usr/local/zookeeper /bin

./zkServer.sh start

查看集群状态

./zkServer.sh status

刚启动可能会有错误,集群中其他节点一并起来后就正常了

    1. tomcat安装

将apache-tomcat-7.0.57.tar.gz拷贝到/usr/local下并解压

cd /usr/local

tar -zxvf apache-tomcat-7.0.57.tar.gz

    1. solr单机部署
      1. 解压solr.4.10.3.tgz

在其中一台服务器上解压solr.4.10.3.tgz,将solr.4.10.3.tgz拷贝到/usr/local下,解压缩:

tar -zxvf solr-4.10.3.tgz

压缩后在/usr/local下有 solr-4.10.3目录 。

      1. solrhome

在/home下创建solr作为solrhome 并赋于读写权限

      1. 部署solr.war

参考solr单机部署方法。

启动tomcat 访问 http://192.168.0.1:8080/solr 如图,至此单机版solr配制完成

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

    1. solrCloud部署
      1. 启动zookeeper

solrCloud部署依赖zookeeper,需要先启动每一台zookeeper服务器。

      1. zookeeper管理配置文件

由于zookeeper统一管理solr的配置文件(主要是schema.xml、solrconfig.xml), solrCloud各各节点使用zookeeper管理的配置文件。

将上边部署的solr单机的conf拷贝到/home/solr下。

执行下边的命令将/home/solr/conf下的配置文件上传到zookeeper(此命令为单条命令,虽然很长o(╯□╰)o):

sh /usr/local/solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh -zkhost 192.168.0.5:2181,192.168.0.6:2181,192.168.0.7:2181 -cmd upconfig -confdir /usr/local/solr-4.10.3/example/solr/collection1/conf -confname myconf

登陆zookeeper服务器查询配置文件:

cd /usr/local/zookeeper/bin/

./zkCli.sh

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

      1. 修改SolrCloud监控端口为8080:

修改每个solr的/home/solr/solrhome/solrconfig.xml文件。

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

      1. 每一台solr和zookeeper关联

修改每一台solr的tomcat 的 bin目录下catalina.sh文件中加入DzkHost指定zookeeper服务器地址:

JAVA_OPTS="-DzkHost=192.168.0.5:2181,192.168.0.6:2181,192.168.0.7:2181"

(可以使用vim的查找功能查找到JAVA_OPTS的定义的位置,然后添加)

      1. 启动所有的solr服务

启动每一台solr的tomcat服务。

      1. 访问solrcloud

访问任意一台solr,左侧菜单出现Cloud:

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

      1. SolrCloud集群配置

上图中的collection1集群只有一片,可以通过下边的方法配置新的集群。

创建新集群collection2,将集群分为两片,每片两个副本。

http://192.168.0.1:8080/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

删除集群命令;

http://192.168.0.1:8080/solr/admin/collections?action=DELETE&name=collection1

执行后原来的collection1删除,如下:

uploading.4e448015正在上传…重新上传取消正在上传…重新上传取消

更多的命令请参数官方文档:apache-solr-ref-guide-4.10.pdf

      1. 启动solrCloud注意

启动solrCloud需要先启动solrCloud依赖的所有zookeeper服务器,再启动每台solr服务器。

    1. SolrCloud测试

创建索引:

测试1:在一台solr上创建索引,从其它solr服务上可以查询到。

测试2:一次创建100个文档甚至更多,通过观察每个solr的core下边都有索引文档,说明索引文档是分片存储。

查询索引:

从任意一台Solr上查询索引,返回一个完整的结果,说明查询请求从不同的分片上获取数据,最终返回集群上所有匹配的结果。

    1. solrJ访问solrCloud

public class SolrCloudTest {

// zookeeper地址

private static String zkHostString = "192.168.101.7:2181,192.168.101.8:2181,192.168.101.9:2181";

// collection默认名称,比如我的solr服务器上的collection是collection2_shard1_replica1,就是去掉“_shard1_replica1”的名称

private static String defaultCollection = "collection2";

// 客户端连接超时时间

private static int zkClientTimeout = 3000;

// zookeeper连接超时时间

private static int zkConnectTimeout = 3000;

// cloudSolrServer实际

private CloudSolrServer cloudSolrServer;

// 测试方法之前构造 CloudSolrServer

@Before

public void init() {

cloudSolrServer = new CloudSolrServer(zkHostString);

cloudSolrServer.setDefaultCollection(defaultCollection);

cloudSolrServer.setZkClientTimeout(zkClientTimeout);

cloudSolrServer.setZkConnectTimeout(zkConnectTimeout);

cloudSolrServer.connect();

}

// 向solrCloud上创建索引

@Test

public void testCreateIndexToSolrCloud() throws SolrServerException,

IOException {

SolrInputDocument document = new SolrInputDocument();

document.addField("id", "100001");

document.addField("title", "李四");

cloudSolrServer.add(document);

cloudSolrServer.commit();

}

// 搜索索引

@Test

public void testSearchIndexFromSolrCloud() throws Exception {

SolrQuery query = new SolrQuery();

query.setQuery("*:*");

try {

QueryResponse response = cloudSolrServer.query(query);

SolrDocumentList docs = response.getResults();

System.out.println("文档个数:" + docs.getNumFound());

System.out.println("查询时间:" + response.getQTime());

for (SolrDocument doc : docs) {

ArrayList title = (ArrayList) doc.getFieldValue("title");

String id = (String) doc.getFieldValue("id");

System.out.println("id: " + id);

System.out.println("title: " + title);

System.out.println();

}

} catch (SolrServerException e) {

e.printStackTrace();

} catch (Exception e) {

System.out.println("Unknowned Exception!!!!");

e.printStackTrace();

}

}

// 删除索引

@Test

public void testDeleteIndexFromSolrCloud() throws SolrServerException, IOException {

// 根据id删除

UpdateResponse response = cloudSolrServer.deleteById("zhangsan");

// 根据多个id删除

// cloudSolrServer.deleteById(ids);

// 自动查询条件删除

// cloudSolrServer.deleteByQuery("product_keywords:教程");

// 提交

cloudSolrServer.commit();

}

}

SolrCloud 是基于 Solr 和 Zookeeper 的分布式搜索方案,是正在开发中的 Solr4.0 的核心组 件之一,它的主要思想是使用 Zookeeper 作为集群的配置信息中心。
它有几个特色功能:①集中式的配置信息 ②自动容错 ③近实时搜索 ④查询时自动负载均 衡。

下面看看 wiki 的文档:
1、SolrCloud SolrCloud 是指 Solr 中一套新的潜在的分发能力。这种能力能够通过参数让你建立起一个高 可用、 容错的 Solr 服务集群。当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud(solr 云)。
看看下面“启动”部分内容,快速的学会怎样启动一个集群。后面有 3 个快速简单的例子, 它们展现怎样启动一个逐步越来越复杂的集群。检出例子之后,需要翻阅后面的部分了解 更加细节的信息。
2、关于 SolrCores 和 Collections 的一点儿东西 对于单独运行的 Solr 实例,它有个东西叫 SolrCore(Solr.xml 中配置的),它是本质上独立的 索引块。如果你打算多个索引块,你就创建多个 SolrCores。当同时部署 SolrCloud 的时, 独立的索引块可以跨越多个 Solr 实例。这意味着一个单独的索引块能由不同服务器设备上 多个 SolrCore 的索引块组成。我们把组成一个逻辑索引块的所有 SolrCores 叫做一个独立 索引块儿(collection)。一个独立索引块是本质上一个独立的跨越多个 SolrCore 索引块的索 引块,同时索引块尽可能随着多余的设备进行缩放。如果你想把你的两个 SolrCore Solr 建 立成 SolrCloud,你将有 2 个独立索引块,每个有多个独立里的 SolrCores 组成。
3、启动 下载 Solr4-Beta 或更高版本。
如果你还没了解,通过简单的 Solr 指南让自己熟悉 Solr。注意:在通过指南了解云特点前, 重设所有的配置和移除指南的文档.复制带有预先存在的 Solr 索引的例子目录将导致文档计 数关闭 Solr 内嵌使用了 Zookeeper 作为集群配置和协调运作的仓储。协调考虑作为一个包 含所有 Solr 服务信息的分布式文件系统。
如果你想用一个其他的而不是 8983 作为 Solr 端口,去看下面’ Parameter Reference’部分下 的关于 solr.xml 注解
例 A:简单的 2 个 shard 集群

这个例子简单的创建了一个代表一个独立索引块的两个不同的 shards 的两个 solr 服务组成
的集群。从我们将需要两个 solr 服务器,简单的复制例子目录副本作为第二个服务器时, 要确保没有任何索引存在。
1 2 rm -r example/solr/collection1/data/* cp -r example example2
下面的命令启动了一个 solr 服务同时引导了一个新的 solr 集群
1 2 3
cd example java -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DzkRun -DnumShards=2 -jar start.jar
•-DzkRun 该参数将促使一个内嵌的 zookeeper 服务作为 Solr 服务的部分运行起来。 •-Dbootstrap_confdir=./solr/collection1/conf 当我们还没有 zookeeper 配置时,这个参数导致 本地路径./solr/conf 作为“myconf”配置被加载.“myconf”来自下面的“collection.configName” 参数定义。 •-Dcollection.configName=myconf 设置用于新集合的配置名。省略这个参数将导致配置名字 为默认的“configuration1” •-DnumShards=2 我们打算将索引分割到逻辑分区的个数。
浏览 http://localhost:8983/solr/#/~cloud 地址,看看集群的状态。你从 zookeeper 浏览程序能 看到 Solr 配置文件被加载成”myconf”,同时一个新的叫做”collection1”的文档集合被创 建.collection1 下是碎片列表,这些碎片组成了那完整的集合。
现在我们想要启动我们的第二个服务器;因为我们没明确设置碎片 id,它将自动被设置成 shard2,启动第二个服务器,指向集群
1 2
cd example2 java -Djetty.port=7574 -DzkHost=localhost:9983 -jar start.jar
•-Djetty.port=7574 只是一种用于让 Jetty servlet 容器使用不同端口的方法 •-DzkHost=localhost:9983 指向全体包含集群状态的 Zookeeper 服务.这个例子中,我们运行 的是一个内嵌在第一个 solr 服务器中的独立的 Zookeeper 服务.默认情况下,一个内嵌的 Zookeeper 服务运行在 9983 端口上。
如果你刷新浏览器,你现在在 collection1 下应该看到两个 shard1 和 shard2。
接下来,索引一些文档。如果你想要快速完成一些,像 java 你能够使用 CloudSolrServer solrj 的实现和简单的用 Zookeeper 地址初始化它就可以了.或者也可以随便选择某个 solr 实 例添加文档,这些文档自动的被导向属于他们的地方。
1 2 3 4
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
现在,发起一个获得覆盖整个集合的分布式搜索服务搜索到的任何一个服务的结果的请求:
1 http://localhost:8983/solr/collection1/select?q=*:*
如果在任一个点你希望重新加载或尝试不同的配置,你能通过关闭服务器后简单的删除 solr/zoo_data 目录方式删除所有 zookeeper 的云状态。
例 B:简单的支持副本的两个碎片集群

有先前的例子,这个例子通过再创建 shard1 和 shard2 副本很容易创建起来。额外的 shard 副本用于高可用性和容错性,或用于提高集群的检索能能力。
首先,通过前一个例子, 我们已经有两个碎片和一些文档索引在里面了。然后简单的复制 那两个服务:
1 2
cp -r example exampleB cp -r example2 example2B
然后在不同的端口下启动这两个新的服务,每个都在各自的视窗下执行
1 2 3 4
cd exampleB java -Djetty.port=8900 -DzkHost=localhost:9983 -jar start.jar cd example2B java -Djetty.port=7500 -DzkHost=localhost:9983 -jar start.jar
刷新 zookeeper 浏览页面,核实 4 个 solr 节点已经启动,并且每个 shard 有两个副本,因为 我们已经告诉 Solr 我们想要 2 个逻辑碎片,启动的实例 3 和 4 自动的被负值为两个 shards 的副 本。
现在,向任何一个服务器发送请求来查询这个集群
1 http://localhost:7500/solr/collection1/select?q=*:*
多次发送这个请求,来研究 solr 服务的日志。你应该能够发现 Solr 实现跨副本的负载均衡 请求,用不同的服务满足每一个请求。 浏览器发送请求的服务器里有一个顶层请求的日志 描述,也会有被合并起来生成完成响应的子请求的日志描述。
为了证明故障切换的可用性,在任何一个服务器(除了运行 Zookeeper 的服务器)运行窗 口下按下CTRL-C。一旦那个服务实例停止运行,就向剩余运行的服务器的任何一个发送 另一个查询请求,你应该仍然看到完整的结果。
SolrCloud 能够持续提供完整查询服务直到最后一个维护每一个碎片的服务器当机.你能通 过明确地关闭各个实例和查询结果来证明这种高可用性。如果你关掉维护某一个碎片的所 有服务器,请求其他服务器时将会返回 503 错误结果。要想从依然运行的碎片服务中返回 可用的正确文档,需要添加 shards.tolerant=true 查询参数。
SolrCloud 用多主服务+监控者服务实现。这意味着某写节点或副本扮演一种特殊角色。你 不需要担忧你关掉的是主服务或是集群监控,如果你关掉它们中的一个,故障切换功能将 自动选出新的主服务或新的监控服务,新的服务将无缝接管各自的工作。任何 Solr 实例都 能被升级为这些角色中的某个角色。
例 C:支持副本和完整 zookeeper 服务的两个碎片集群

例 B 的问题是可以 有足够多的服务器保证任何一个损坏的服务器的信息幸存下来,但确只 有一个包含集群状态的 zookeeper 服务器。如果那台 zookeeper 服务器损坏,分布式查询将 仍然工作在上次 zookeeper 保存的集群状态下,可能没有机会改变集群的状态了。
在 a zookeeper ensemble(zookeeper 集群)中运行多个 zookeeper 服务器保证 zookeeper 服务的 高可用性。每个 zookeeper 服务器需要知道集群中其他服务器,且这些服务器中的一个主 服务器需要提供服务。例如: 3 台组成的 zookeeper 集群允许任一个故障,而后通过剩余 2 个协商一个主服务继续提供服务。5 台的需要允许一次 2 个服务器故障。
对于用于生产服务时,推荐运行一个额外的 zookeeper 集群而不是运行内嵌在 Solr 里面的 zookeeper服务。在这里你能阅读更多关于建立 zookeeper 集群的知识。对于这个例子,为 了简单点我们将用内嵌的 zookeeper 服务。
首先停止 4 个服务器并清理 zookeeper 数据
1 rm -r example*/solr/zoo_data
我们将分别在 8983,7574,8900,7500 端口运行服务。默认的方式是在主机端口+1000 运 行内嵌的 zookeeper 服务,所以如果我们用前 3 个服务器运行内嵌 zookeeper,地址分别是 localhost:9983,localhost:8574,localhost:9900。
为了方便,我们上传第一个服务器 solr 配置到集群。你将注意到第一个服务器阻塞了,直 到你启动了第二个服务器。这是因为 zookeeper 需要达到足够的服务器数目才允许操作。
1 2
cd example java -Dbootstrap_confdir=./solr/collection1/conf
3 4 5 6 7 8
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
现在我们已经运行起由 3 个内嵌 zookeeper 服务组成的集群,尽管某个服务丢失依然保持 工作。通过 CTRL+C 杀掉例 B 的服务器然后刷新浏览器看 zookeeper 状态可以断定 zookeeper 服务仍然工作。注意:当运行在多个 host 上时,在每个需要设置对应的 hostname,-DzkRun=hostname:port,-DzkHosts 使用准确的 host 名字和端口,默认的 localhost 将不能工作。
4、ZooKeeper 为了容错和高可用多个 zookeeper 服务器一起运行,这种模式叫做 an ensemble。对于生产 环境,推荐额外运行 zookeeper ensemble 来代替 solr 内嵌的 zookeeper 服务。关于下载和运 行 ensemble的更多信息访问 Apache ZooKeeper 。 更特殊的是,试着启动和管理 zookeeper。 它的运行实际上非常简单。你能容银让 Solr 运行 Zookeeper,但是记住一个 zookeeper 集群 不容易进行动态修改。除非将来支持动态修改,否则最好在回滚重启时进行修改。与 Solr 分开处理通常是最可取的。
当 Solr 运行内嵌 zookeeper 服务时,默认使用 solr 端口+1000 作为客户端口,另外,solr 端 口+1 作为 zookeeper 服务端口,solr 端口+2 作为主服务选举端口。所以第一个例子中, Solr 运行在 8983端口,内嵌 zookeeper 使用 9983 作为客户端端口,9984 和 9985 作为服务 端口。
鉴于确保 Zookeeper 搭建起来是非常快速的,要记住几点:Solr 不强烈要求使用 Zookeeper, 很多情况优化可能不是必须的。另外,当添加更多的 Zookeeper 节点对读数据性能会有帮 助,但也轻微的降低了写的性能。再有,当集群处于稳定运行时,solr 与 Zookeeper 没有太 多的交互。如果你需要优化 zookeeper,这里有几个有益的要点:
1.ZooKeeper在专用的机器上运行效果最好。ZooKeeper 提供的是一种及时服务,专用设备 有助于确保及时服务的响应。当然,专用机器并不是必须的。 2.ZooKeeper在事务日志和快照在不同的硬盘驱动器上工作效果最好 3.如果配置支持 solr 的 Zookeeper,各自使用独立的硬盘驱动器有助于性能。
5、通过集合 api 管理集合 你可以通过集合 API 管理集合。在这个 API 壳下,一般使用 CoreAdmin API 异步管理每台 服务器上的 SolrCores,对于如果你自己处理使独立的 CoreAdmin API 通过替换 action 参数 就能调用每个服务器来说,这无疑是一个必不可少好东西。
①创建接口
1 http://localhost:8983/solr/admin/collections?action=CREATE&name=mycollection&numShards=3&replicationFactor=4
相关参数:

name:将被创建的集合的名字 numShards:集合创建时需要创建逻辑碎片的个数 replicationFactor:每个文档副本数。replicationFactor(复制因子)为 3 意思是每个逻辑碎片将有 3 份副本。注:Solr4.0 中,replicationFactor 是 additional * 副本数 ,而不是副本总数 maxShardsPerNode:一个创建操作将展开创建 numShards*replicationFactor 碎片副本遍布在你的 Solr 节点上,公平 分布,同一个碎片的两个副本不会在同一个 Solr 节点上。如果创建操作完成 时 Solr 损坏,该操作不会创建出新集合的任何部分。该参数用来防止在同一 个 Solr 节点创建太多副本,默认参数 1.如果它的值与整体集合中 numShards*replicationFactor 副本数分布到正常活跃的 Solr 节点的数不 符,将不能创建任何东西 createNodeSet:如果不提供该参数,创建操作将创建碎片副本展开分布到所 有活跃的 Solr 节点上。提供该参数改变用于创建碎片副本的节点集合。参数 值的格式是:"<node-name1>,<node-name2>,...,<node-nameN>", 例如: createNodeSet=localhost:8983_solr,localhost:8984_solr,localhos t:8985_solr collection.configName:用于新集合的配置文件的名称。如果不提供该参数 将使用集合名称作为配置文件的名称。
Solr4.2 相关参数: name:将被创建的集合别名的名字 collections:逗号分隔的一个或多个集合别名的列表
②删除接口
1 http://localhost:8983/solr/admin/collections?action=DELETE&name=mycollection
相关参数:
1 <strong>name</strong>:将被删除的集合的名字
③重新加载接口
1 http://localhost:8983/solr/admin/collections?action=RELOAD&name=mycollection
相关参数: name:将被重载的集合的名字
④分割碎片接口
1 http://localhost:8983/solr/admin/collections?action=SPLITSHARD&collection=&lt;collection_name&gt;&shard=shardId
Solr4.3 相关参数: collection:集合的名字 shard:将被分割的碎片 ID
这个命令不能用于使用自定义哈希的集群,因为这样的集群没有一个明确的哈希范围。 它 只用于具有 plain 或 compositeid 路由的集群。
该命令将分割给定的碎片索引对应的那个碎片成两个新碎片。通过将碎片范围划分成两个 相等的分区和根据新碎片范围分割出它在父碎片(被分的碎片)中的文档。新碎片将被命名 为 appending_0 和_1。例如:shard=shard1 被分割,新的碎片将被命名为 shard1_0 和 shard1_1。一旦新碎片被创建,它们就被激活同时父碎片(被分的碎片)被暂停因此将没有新 的请求到父碎片(被分的碎片)。
该特征达到了无缝分割和无故障时间的要求。原来的碎片数据不会被删除。使用新 API 命 令重载碎片用户自己决定。
该特性发布始于 Solr4.3,由于 4.3 发布版本发现了一些 bugs,所以要使用该特性推荐等待 4.3.1。
6、集合别名 别名允许你创建独立的指向一个或多个真是集合的虚拟集合,你能够在运行时修改别名。
①创建别名
1 http://localhost:8983/solr/admin/collections?action=CREATEALIAS&name=alias&collections=collection1
创建或修改别名。用于发送修改的别名应该只映射一个独立的集合。读的别名能映射一个 或多个集合。
②移除存在的别名
1 http://localhost:8983/solr/admin/collections?action=DELETEALIAS&name=alias
移除存在的别名
7、经 CoreAdmin 创建 cores 经过 CoreAdmin 可以创建新的 Solrcores 和使新的 Solrcores 与一个集合关联,创建时附加 云相关参数
•collection 这个 core 所属的集合的名字。默认 core 的名字 •shard 这个 core 代表的碎片的 id(可选-通常自动设置一个碎片 id) •numShards 集合碎片个数。该参数只在集合第一个 core 创建时有用 •collection.<param>=<value> 集合创建时设置属性值,用 collection.configName=<configname> 指明新集合的配置文件
1
curl 'http://localhost:8983/solr/admin/cores?action=CREATE&name=mycore&collection=collection1&shard=shard2
8、分布式请求 查询一个集合的所有碎片(注意:那个集合已经隐含在 URL 中了)
1 http://localhost:8983/solr/collection1/select?
查询一个兼容集合的所有碎片,明确详述如下:
1 http://localhost:8983/solr/collection1/select?collection=collection1_recent
查询多个兼容集合的所有碎片
1 http://localhost:8983/solr/collection1/select?collection=collection1_NY,collection1_NJ,collection1_CT
查询集合的某些碎片。例子中,用户已经按日期对索引进行分割了,每月创建一个新的碎 片
1 http://localhost:8983/solr/collection1/select?shards=shard_200812,shard_200912,shard_201001
明确指明以想要查询碎片的地址
1 http://localhost:8983/solr/collection1/select?shards=localhost:8983/solr,localhost:7574/solr
明确指明以想要查询碎片的地址,同时为负载均衡和故障切换给出可选的地址
1 http://localhost:8983/solr/collection1/select?shards=localhost:8983/solr|localhost:8900/solr,localhost:7574/solr|localhost:7500/solr
9、必须的配置 所有必须的配置已经安装在 Solr 的例子中。下面是如果你正在迁移旧的配置文件你需要添 加什么,或不应该删除什么
10、schema.xml 字段_version_是必须定义的
1
<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
11、solrconfig.xml 必要有一个更新日志的定义,这个应该被定义在 updateHandler 标签中
1 2 3 4
<!-- Enables a transaction log, currently used for real-time get."dir" - the target directory for transaction logs, defaults to thesolr data directory. --> <updateLog> <str name="dir">${solr.data.dir:}</str> </updateLog>
必须有一个复制处理调用的定义
1
<requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
必须有一个获取实际时间处理的调用的定义
1 2 3 4 5
<requestHandler name="/get" class="solr.RealTimeGetHandler"> <lst name="defaults"> <str name="omitHeader">true</str> </lst> </requestHandler>
必须有管理句柄的定义
1 <requestHandler name="/admin/" class="solr.admin.AdminHandlers"/>
DistributedUpdateProcessor 是默认更新链的部分也会被自动注入自定义更新链。
1 2 3 4 5 6
<updateRequestProcessorChain name="sample"> <processor class="solr.LogUpdateProcessorFactory" /> <processor class="solr.DistributedUpdateProcessorFactory"/> <processor class="my.package.UpdateFactory"/> <processor class="solr.RunUpdateProcessorFactory" /> </updateRequestProcessorChain>
如果不想让它自动注入到你的链中(说明你想使用 SolrCloud 功能,但想自己分发修改)那么 在你的链 中指明下面的更新处理工厂: NoOpDistributingUpdateProcessorFactory
12、solr.xml 必须保留 admin path 作为默认 core
1 <cores adminPath="/admin/cores" />
13、可变集群 当你在一个集合中启动 SolrCore 时通过 numShards 参数可以控制集群的规模。 这个参数一 般自动赋给关联每个实例的碎片。启动 numShards 个实例后所有的 SolrCores 都被均匀的加 入每个碎片作为副本。
向集合添加 SolrCores 保证其启动是很简单的,你随时都可以进行这样的操作。新的 SolrCore 在激活前会把它的数据同步到碎片中的副本上。
如果你要在几台机器上启动集群,不仅添加副本需要花时间扩展成集群也需要时间,那么, 你可以选择通过每部机器负责几个碎片的方式启动(使用多 SolrCores),然后通过对碎片启 动副本的形式迁移碎片到新的设备上,最终移除原来设备上的碎片。
Solr4.3 具备新的 API 接口, SPLITSHARD,分割已存在的碎片成两份新的碎片,相关介 绍前面讲过。
14、近实时搜索 如果你希望启用近实时搜索,你可能需要修改放在ZooKeeper中的 solrconfig.xml文件,添 加启动软件自动提交配置,或者通过向集群发送软提交。详见看近实时搜索。
15、参数参考介绍 A.集群参数
numShards
默认值
1
文档被散列存储到所有碎片的数量。每个碎片有一个主碎片(领导者),每
个主碎片有 N 个副本
B.Solr 云实例参数 参数在 solr.xml 中设置,实例的运行与系统环境变量也有关。重要事项:hostPort 是每个 Solr 实例运行的端口,zookeeper 通过该端口通知集群的状态(剩余等),默认值是 8983。 solr.xml 例子用的是 jetty.port 环境变量,所以如果你不想用 8983,那么你启动 Solr前设置 jetty.port 变量,或修改 solr.xml 文件。
host
默认值 找
到的第一
个本地地
址 如果自动找到的地址是错的,你可以通过这个参数修改
hostPort 默认值 这个参数是Solr使用的,默认使用的是jettry的配置文件
jettry的
系统配置
host
默认值
solr
Solr 部署成 web 应用时的上下文路径。(注:在 Solr4.0 中,强制要
求 hostContext 不能包含”/”或”_”字符。Solr4.1 开始,没有这个
限制了,并且建议以”/”开头。运行 jetty 例子时,hostContext 既是
jetty 容器的 servlet 上下文地址也是 SolrCloud 上下文地址,例:
DhostContext=/solr)
C.云实例中 Zookeeper 参数
zkRun
默认值
localhost:solrPort+1000
配置该参数让 Solr 运行起内嵌的 Zookeeper
服务。参数设置了 Zookeeper 所在的服务器
地址。这个值会出现在 zkHost 参数中,我们
能够知道都有哪些 zk 服务器。简单模式可以
使用默认值;注意:这个值必须是 zkHost 中
的一个;另外,多服务器版的不能使用默认的
localhost。
zkHost 默认值 没有
ZooKeeper host 地址——你的ZooKeeper
集群一般节点地址使用逗号分割
zkClientTimeout 默认值 15000 session 没有过期前提下,不和ZooKeeper
交互的最长间隔
zkClientTimeout 参数在 solr.xml 设置,也可以通过系统参数设置。
D.云核参数
shard shard 的ID,默认基于 numShards自动分配 允许你指定SolrCores里的shard的 Id
碎片 id 可以在每个 core 元素的属性中配置
16、把配置文件给 ZooKeeper A.配置启动引导参数
第一次启动 Solr,有两种使用系统参数加载初始化 Zookeeper 配置文件的方法。记住,只 用于第一次启动或覆盖配置文件时。每次启动都要带着系统参数,系统参数会覆盖配置文 件中名字相同的值。
1.看 solr.xml 文件,找到每个 SolrCore 加载的 conf 目录。 ‘config set’ (配置集)的名字就是 SolrCore的集合的名字,集合使用与它名字相同的配置集合。
bootstrap_conf
无默
认值
如果启动时携带参数 -Dbootstrap_conf=true,每个 SolrCore 将把
自己的配置文件加载关联到它对应的集合上。

2.通过给的配置文件名字从指定目录下加载配置集。尽管没有指定集合到配置集的关联, 如果只有一个配置集,集合将自动链接到这个配置集。
bootstrap_confdir 无默认值
如果你通过 -bootstrap_confdir=<目录≶ 启动,
指定的配置目录文件将会被提交到 ZooKeeper,
设置配置名可以用下面的参数:
collection.configName
collection.configName 默认值 通过bootstrap_confdir设置配置集的名称
configuration1
B.命令行工具 CLI 工具也可以配置 Zookeeper。 它与上面两种方法一样。 它提供一些命令,能够配置集 到集合关联,创建 Zookeeper 路径或移除,还能从 zookeeper 下载配置文件到本地。
1 2 3 4 5 6 7 8 9
usage: ZkCLI -c,--collection <arg> for linkconfig: name of the collection -cmd <arg> cmd to run: bootstrap, upconfig, downconfig,linkconfig, makepath, clear -d,--confdir <arg> for upconfig: a directory of configuration files -h,--help bring up this help page -n,--confname <arg> for upconfig, linkconfig: name of the config set -r,--runzk <arg> run zk internally by passing the solr run port -only for clusters on one machine (tests, dev) -s,--solrhome <arg> for bootstrap, runzk: solrhome location -z,--zkhost <arg> ZooKeeper host address
C.例子
1 2 3 4 5 6
# try uploading a conf dir java -classpath example/solr-webapp/WEB-INF/lib/* org.apache.solr.cloud.ZkCLI -cmd upconfig -zkhost 127.0.0.1:9983 -confdir example/solr/collection1/conf -confname conf1 # try linking a collection to a conf set java -classpath example/solr-webapp/WEB-INF/lib/* org.apache.solr.cloud.ZkCLI -cmd linkconfig -zkhost 127.0.0.1:9983 collection collection1 -confname conf1 # try bootstrapping all the conf dirs in solr.xml java -classpath example/solr-webapp/WEB-INF/lib/* org.apache.solr.cloud.ZkCLI -cmd bootstrap -zkhost 127.0.0.1:9983 solrhome example/solr
D.脚本 如果你不想使用 jettry容器,example/cloud-scripts 目录下有系统脚本文件,它帮你处理了 classpath 和 class name,命令变成为:
1
sh zkcli.sh -cmd linkconfig -zkhost 127.0.0.1:9983 -collection collection1 -confname conf1
17、ZooKeeper chroot 如果其他应用已经在用 Zookeeper,你想保持原应用的管理方式,又或者有多个分开的 solrcloud 集群共用一个 zookeeper,你可以用 zookeeper 的‘chroot’选项,来自 Zookeeper Session。 An optional "chroot" suffix may also be appended to the connection string. This will run the client commands while interpreting all paths relative to this root (similar to the unix chroot command). If used the example would look like: "127.0.0.1:4545/app/a" or "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" where the client would be rooted at "/app/a" and all paths would be relative to this root - ie getting/setting/etc... "/foo/bar" would result in operations being run on "/app/a/foo/bar" (from the server perspective).
要使用这个特点,zkHost 参数用上”chroot”后缀,而后简单启动 solr
1 java -DzkHost=localhost:9983/foo/bar -jar start.jar
或者
1 java -DzkHost=zoo1:9983,zoo2:9983,zoo3:9983/foo/bar -jar start.jar
提示:Solr4.0启动时你需要预先创建 ZooKeeper路径,Solr4.1以后再使用 eitherbootstrap_conf 或 boostrap_confdir 的路径是自动初始化的了。
18、已知的局限性 很少 Solr 搜索框架不支持分布式搜索的。有些情况下,一个框架无法支持分布式,不过, 那只是时间和努力的问题。不支持标准分布式搜索的搜索框架,它的 SolrCloud 同样不支 持。通过 distrib=false控制是否使用分布式。
组群特点只能是在同一个存储碎片上的组群。必须自定义碎片特征才能使用组群特点。
如果要更新支持 SolrCloud 的 Solr4.0 到 4.1,注意 name_node 参数的定义方式已经改变了。 这导致一种情况发生,由于 name_node 用 ip 地址代替了服务器的名字,使 SolrCloud 无法 感知到这个 name_node。你可以通过 solr.xml 配置 ip 到服务器名的关联解决问题。
19、术语
Collection: A single search index.
Shard:
A logical section of a single collection (also called Slice). Sometimes
people will talk about “Shard” in a physical sense (a manifestation of a
logical shard)
Replica:
A physical manifestation of a logical Shard, implemented as a single
Lucene index on a SolrCore
Leader:
One Replica of every Shard will be designated as a Leader to coordinate
indexing for that Shard
SolrCore:
Encapsulates a single physical index. One or more make up logical shards
(or slices) which make up a collection.
Node:
A single instance of Solr. A single Solr instance can have multiple
SolrCores that can be part of any number of collections.
Cluster: All of the nodes you are using to host SolrCores.
英文原文地址
您可能喜欢:

Solr索引数据同步(ReplicationHandler)功能搭建问题

Solr 开发过程中遇到的一下资料、问题整理(资料)

Solr实现 并集式、多值、复杂 过滤查询(filterQuery)

Solr 对比 Lucene 的优势

Solr4.0(SolrCloud) & ElasticSearch(ES) 比较(二)

  1. 什么是SolrCloud

SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用SolrCloud来满足这些需求。

SolrCloud是基于Solr和Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。

它有几个特色功能:

1)集中式的配置信息

2)自动容错

3)近实时搜索

4)查询时自动负载均衡

zookeeper是个什么玩意?

顾名思义zookeeper就是动物园管理员,他是用来管hadoop(大象)、Hive(蜜蜂)、pig(小猪)的管理员, Apache Hbase和 Apache Solr 的分布式集群都用到了zookeeper;Zookeeper:是一个分布式的、开源的程序协调服务,是hadoop项目下的一个子项目。

  1. 集群的搭建
    1. 开发环境

CentOS-6.4-i386-bin-DVD1.iso

jdk-7u72-linux-i586.tar.gz

apache-tomcat-7.0.47.tar.gz

zookeeper-3.4.6.tar.gz

solr-4.10.3.tgz

    1. Solr集群的结构

uploading.4e448015正在上传…重新上传取消

    1. 环境的安装
      1. 第一步:安装CentOS6.4。
      2. 第二步:安装java虚拟机。
      3. 第三步:安装zookeeper。

Zookeeper保证是奇数节点。最少三个节点。伪分布式的集群环境,在同一个linux下运行集群环境。

  1. 解压zookeeper。

tar -zxf zookeeper-3.4.6.tar.gz

  1. 在/usr/local下创建一个solrcloud目录

mkdir /usr/local/solrcloud

  1. 把zookeeper在solrcloud文件夹下复制三份。

uploading.4e448015正在上传…重新上传取消

  1. 配置zookeeper
    1. 在zookeeper1文件夹下创建一个data目录,在data目录下创建一个名为myid的文件,内容就是“1”。
    2. 创建配置文件。

在conf文件夹下有一个zoo_sample.cfg文件,把复制一份命名为zoo.cfg

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

# do not use /tmp for storage, /tmp here is just

# example sakes.

dataDir=/usr/local/solrcloud/zookeeper1/data

# the port at which the clients will connect

clientPort=2181

# the maximum number of client connections.

# increase this if you need to handle more clients

#maxClientCnxns=60

#

# Be sure to read the maintenance section of the

# administrator guide before turning on autopurge.

#

# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance

#

# The number of snapshots to retain in dataDir

#autopurge.snapRetainCount=3

# Purge task interval in hours

# Set to "0" to disable auto purge feature

#autopurge.purgeInterval=1

server.1=192.168.25.150:2881:3881

server.2=192.168.25.150:2882:3882

server.3=192.168.25.150:2883:3883

    1. 依次配置好zookeeper2、zookeeper3,创建一个data目录创建一个myid文件,内容对应编号。修改配置文件。

[root@bogon solrcloud]# cd zookeeper2

[root@bogon zookeeper2]# mkdir data

[root@bogon zookeeper2]# echo 2 >> data/myid

[root@bogon zookeeper2]# cd conf

[root@bogon conf]# cp zoo_sample.cfg zoo.cfg

[root@bogon conf]# vim zoo.cfg

Zookeeper2:

# The number of milliseconds of each tick

tickTime=2000

# The number of ticks that the initial

# synchronization phase can take

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

# do not use /tmp for storage, /tmp here is just

# example sakes.

dataDir=/usr/local/solrcloud/zookeeper2/data

# the port at which the clients will connect

clientPort=2182

# the maximum number of client connections.

# increase this if you need to handle more clients

#maxClientCnxns=60

#

# Be sure to read the maintenance section of the

# administrator guide before turning on autopurge.

#

# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance

#

# The number of snapshots to retain in dataDir

#autopurge.snapRetainCount=3

# Purge task interval in hours

# Set to "0" to disable auto purge feature

#autopurge.purgeInterval=1

server.1=192.168.25.150:2881:3881

server.2=192.168.25.150:2882:3882

server.3=192.168.25.150:2883:3883

  1. 启动zookeeper

/usr/local/solrcloud/zookeeper1/bin/zkServer.sh start

/usr/local/solrcloud/zookeeper2/bin/zkServer.sh start

/usr/local/solrcloud/zookeeper3/bin/zkServer.sh start

  1. 查看zookeeper的状态

/usr/local/solrcloud/zookeeper1/bin/zkServer.sh status

      1. 第四步:安装tomcat
  1. 解压tomcat
  2. 把tomcat在solrcloud目录下复制四份。
  3. 修改tomcat的端口包装端口不冲突。
      1. 第五步:配置solr服务
  1. 解压solr-4.10.3.tgz.tgz
  2. 把单机版安装的solr工程上传至服务器。
  3. 把example目录下的solr文件夹复制到solrcloud目录下复制四份,创建四个solrhome。

uploading.4e448015正在上传…重新上传取消

  1. 指定solrhome的位置

修改solr工程的web.xml文件。

      1. 第六步:集群环境搭建
  1. 修改solrhome下的solr.xml

uploading.4e448015正在上传…重新上传取消

  1. 使用zookeeper统一管理配置文件。需要把solrhome下的collection1/的conf文件夹上传至zookeeper。

执行下边的命令将/home/solr/conf下的配置文件上传到zookeeper(此命令为单条命令,虽然很长o(╯□╰)o)。此命令在solr-4.10.3/example/scripts/cloud-scripts/目录下:

./zkcli.sh -zkhost 192.168.25.150:2181,192.168.25.150:2182,192.168.25.150:2183 -cmd upconfig -confdir /usr/local/solrcloud/solrhome1/collection1/conf -confname myconf

  1. 告诉solr服务zookeeper集群的位置。

修改每一台solr的tomcat 的 bin目录下catalina.sh文件中加入DzkHost指定zookeeper服务器地址:

JAVA_OPTS="-DzkHost=192.168.25.150:2181,192.168.25.150:2182,192.168.25.150:2183"

(可以使用vim的查找功能查找到JAVA_OPTS的定义的位置,然后添加)

  1. 启动所有tomcat

uploading.4e448015正在上传…重新上传取消

  1. 集群管理
    1. 创建有两片的collection

http://192.168.25.150:8080/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2

uploading.4e448015正在上传…重新上传取消

    1. 删除collection

http://192.168.25.150:8080/solr/admin/collections?action=DELETE&name=collection1

uploading.4e448015正在上传…重新上传取消

uploading.4e448015正在上传…重新上传取消

uploading.4e448015正在上传…重新上传取消

    1. 配置dataimport插件
  1. 需要在每个节点都配置一下,把dataimport插件依赖的jar包添加到每个节点的collection文件夹的lib下。
  2. 修改solrconfig.xml把solrconfig.xml上传至zookeeper。

使用单机版配置,只需要把单机版的collection1/conf目录上传至zookeeper就可以了。

./zkcli.sh -zkhost 192.168.25.150:2181,192.168.25.150:2182,192.168.25.150:2183 -cmd upconfig -confdir /root/solrhome/collection1/conf -confname myconf

  1. 重启tomcat集群。
  1. 集群环境下SolrJ的使用
    1. 步骤:

第一步:创建一java工程

第二步:导入jar包。包括solrJ的jar包solrJ依赖的jar包。Example/lib/ext下的日志相关的jar包。

第三步:集群环境使用CloudSolrServer创建一连接。指定zookeeper的地址列表。还需要指定要连接的collection。

第四步:创建一个查询。

第五步:执行查询。跟单机版一样的。

    1. 代码实现

@Test

public void testCloud() throws Exception {

//创建一个连接

String zkHost = "192.168.25.150:2181,192.168.25.150:2182,192.168.25.150:2183";

//参数:zookeeper服务器的地址列表。

CloudSolrServer server = new CloudSolrServer(zkHost);

//指定默认连接的collection

server.setDefaultCollection("collection2");

//创建一查询对象

SolrQuery solrQuery = new SolrQuery();

solrQuery.setQuery("*:*");

//执行查询

QueryResponse queryResponse = server.query(solrQuery);

SolrDocumentList solrDocumentList = queryResponse.getResults();

System.out.println("查询结果总数量:" + solrDocumentList.getNumFound());

for (SolrDocument solrDocument : solrDocumentList) {

System.out.println(solrDocument.get("id"));

System.out.println(solrDocument.get("product_name"));

System.out.println(solrDocument.get("product_price"));

System.out.println(solrDocument.get("product_picture"));

}

}

  1. 综合案例

Solr搜索在电商网站中的应用。电商搜索。

    1. 需求

使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序。

    1. 开发中的必须的文档
  1. 数据库的表结构文档。
  2. 页面原型。

最好的是html。

  1. 业务流程图。
    1. 原型分析

uploading.4e448015正在上传…重新上传取消

Spring容器

业务流程

Service层

根据表现层传递过来的参数查询商品列表

Dao层

访问solr集群查询商品列表。

使用SolrJ实现

Solr集群

Tomcat

Solr服务

调用solr服务

索引库

Mysql数据库

使用dataimport插件导入

当展示商品详细信息时需要查询数据库。

商品查询不需要数据库

表现层

Jsp+Controller

Springmvc框架

uploading.4e448015正在上传…重新上传取消
    1. Dao
      1. 功能:

service层调用dao层查询商品列表。使用solrJ技术实现。接收一个SolrQuery对象,直接根据SolrQuery对象查询索引库,返回一个商品列表。

      1. 参数:

SolrQuery

      1. 返回值:

包含商品列表,包含查询结果的总数量。ResultModel

      1. 商品的pojo:

包含商品的id、商品的名称、商品的价格、商品的图片、商品分类。

public class ProductModel {

// 商品编号

private String pid;

// 商品名称

private String name;

// 商品分类名称

private String catalog_name;

// 价格

private float price;

// 图片名称

private String picture;

}

      1. 返回值的pojo:

包含商品列表和商品查询结果总数量。

public class ResultModel {

// 商品列表

private List<ProductModel> productList;

// 商品总数

private Long recordCount;

// 总页数

private int pageCount;

// 当前页

private int curPage;

}

      1. 接口的方法:

ResultModel queryProduct(SolrQuery solrQuery) throws Exception;

    1. Service
      1. 功能

由controller调用,传递过来查询的参数。主查询条件、根据商品的分类过滤、商品价格区间过滤、商品价格排序、分页条件。根据查询条件拼装一个SolrQuery对象,调用dao查询商品列表。根据查询结果的总数量计算总页数。

      1. 参数

查询条件:String queryString

商品的分类过滤,需要分类名称:String catalog_name

价格区间,0-10,11-20,21-30,30-*:String price

排序条件,只是根据价格排序,只需要一个排序方式0:升序1:降序:String sort

分页条件:start【(page-1)*rows】,rows自定义:Integer page

      1. 返回值:

包含商品列表, 包含总页数。

ResultModel

      1. 方法定义

ResultModel queryProduct(String queryString, String catalog_name, String price, String sort, Integer page) throws Exception;

    1. Controller
      1. 功能

接收页面传递过来的查询条件,调用service方法查询商品列表。把商品列表传递给jsp页面。需要参数回显。

      1. 参数

查询条件:String queryString

商品的分类过滤,需要分类名称:String catalog_name

价格区间,0-10,11-20,21-30,30-*:String price

排序条件,只是根据价格排序,只需要一个排序方式0:升序1:降序:String sort

分页条件:start【(page-1)*rows】,rows自定义:Integer page

Model:传递参数使用。

      1. 返回值

String:逻辑视图,就sp页面的名字。可能是一部分。

      1. 方法定义

Public String queryProduct(String queryString, String catalog_name, String price, String sort, Integer page, Model model) throws Exception;

    1. Jsp

查看参考资料。

uploading.4e448015正在上传…重新上传取消

    1. 代码实现
      1. 实现步骤

第一步:创建一个web工程

第二步:导入jar包。Springmvc+spring+solrJ的jar包

第三步:开发dao

第四步:开发service

第五步:开发controller。

      1. Dao

@Repository

public class ProductDaoImpl implements ProductDao {

@Autowired

private SolrServer solrServer;

@Override

public ResultModel queryProduct(SolrQuery solrQuery) throws Exception {

//根据查询条件查询索引库

QueryResponse response = solrServer.query(solrQuery);

//取查询结果

SolrDocumentList solrDocumentList = response.getResults();

//商品列表

List<ProductModel> productList = new ArrayList<>();

//遍历列表

for (SolrDocument solrDocument : solrDocumentList) {

//取商品信息

ProductModel model = new ProductModel();

model.setPid((String) solrDocument.get("id"));

//取高亮显示

Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");

String productName = "";

if (null != list && list.size() > 0) {

productName = list.get(0);

} else {

productName = (String) solrDocument.get("product_name");

}

model.setName(productName);

model.setPrice((float) solrDocument.get("product_price"));

model.setPicture((String) solrDocument.get("product_picture"));

model.setCatalog_name((String) solrDocument.get("product_catalog_name"));

//添加到商品列表

productList.add(model);

}

//添加到返回值对象中

ResultModel resultModel = new ResultModel();

resultModel.setProductList(productList);

//查询结果的总数量

resultModel.setRecordCount(solrDocumentList.getNumFound());

return resultModel;

}

}

      1. Service

@Service

public class ProductServiceImpl implements ProductService {

@Autowired

private ProductDao productDao;

@Override

public ResultModel queryProduct(String queryString, String catalog_name,

String price, String sort, Integer page) throws Exception {

SolrQuery solrQuery = new SolrQuery();

//拼装查询条件

//主查询条件

if (null != queryString && !"".equals(queryString)) {

solrQuery.setQuery(queryString);

} else {

solrQuery.setQuery("*:*");

}

//根据商品分类过滤

if (null != catalog_name && !"".equals(catalog_name)) {

solrQuery.addFilterQuery("product_catalog_name:" + catalog_name);

}

//价格区间过滤

if (null != price && !"".equals(price)) {

String[] strings = price.split("-");

solrQuery.addFilterQuery("product_price:["+strings[0]+" TO "+strings[1]+"]");

}

//排序条件

if ("1".equals(sort)) {

solrQuery.setSort("product_price", ORDER.desc);

} else {

solrQuery.setSort("product_price", ORDER.asc);

}

//分页条件

if (null == page) page = 1;

//计算分页

int start = (page - 1) * Global.PAGE_SIZE;

solrQuery.setStart(start);

solrQuery.setRows(Global.PAGE_SIZE);

//设置默认搜索域

solrQuery.set("df", "product_keywords");

//设置高亮

solrQuery.setHighlight(true);

//高亮显示的域

solrQuery.addHighlightField("product_name");

//高亮显示的前缀

solrQuery.setHighlightSimplePre("<span style=\"color:red\">");

//高亮后缀

solrQuery.setHighlightSimplePost("</span>");

//执行查询

ResultModel resultModel = productDao.queryProduct(solrQuery);

//计算总页数

Long recordCount = resultModel.getRecordCount();

int pageCount = (int) (recordCount / Global.PAGE_SIZE);

if (recordCount % Global.PAGE_SIZE > 0) {

pageCount++;

}

resultModel.setPageCount(pageCount);

resultModel.setCurPage(page);

return resultModel;

}

}

      1. Controller

@Controller

public class ProductController {

@Autowired

private ProductService productService;

@RequestMapping("/list")

public String queryProduct(String queryString, String catalog_name,

String price, String sort, Integer page, Model model)

throws Exception {

//接收参数,调用service查询商品列表

ResultModel resultModel = productService.queryProduct(queryString, catalog_name, price, sort, page);

//把resultModel传递给页面

model.addAttribute("result", resultModel);

//参数回显

model.addAttribute("queryString", queryString);

model.addAttribute("catalog_name", catalog_name);

model.addAttribute("price", price);

model.addAttribute("sort", sort);

model.addAttribute("page", page);

//返回jsp页面

return "product_list";

}

}

      1. Web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

<display-name>SolrCloudJD</display-name>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

<!-- 前端控制器 -->

<servlet>

<servlet-name>springmvc</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:springmvc.xml</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>springmvc</servlet-name>

<url-pattern>*.action</url-pattern>

</servlet-mapping>

<!-- post乱码过滤器 -->

<filter>

<filter-name>Character Encoding</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>Character Encoding</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

</web-app>

      1. Springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

<!-- 配置扫描包 -->

<context:component-scan base-package="cn.itcast.jd"/>

<!-- 配置注解驱动 -->

<mvc:annotation-driven/>

<!-- jsp视图解析器 -->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >

<!-- 前缀 -->

<property name="prefix" value="/WEB-INF/jsp/"></property>

<!-- 后缀 -->

<property name="suffix" value=".jsp"></property>

</bean>

<!-- 单机版的SolrServer -->

<!-- <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">

<constructor-arg value="http://localhost:8080/solr/"></constructor-arg>

</bean> -->

<!-- 集群环境SolrServer -->

<bean class="org.apache.solr.client.solrj.impl.CloudSolrServer">

<constructor-arg index="0" value="192.168.25.150:2181,192.168.25.150:2182,192.168.25.150:2183"/>

<property name="defaultCollection" value="collection2"/>

</bean>

</beans>

    1. SolrCloud结构

SolrCloud为了降低单机的处理压力,需要由多台服务器共同来完成索引和搜索任务。实现的思路是将索引数据进行Shard(分片)拆分,每个分片由多台的服务器共同完成,当一个索引或搜索请求过来时会分别从不同的Shard的服务器中操作索引。

SolrCloud需要Solr基于Zookeeper部署,Zookeeper是一个集群管理软件,由于SolrCloud需要由多台服务器组成,由zookeeper来进行协调管理。

下图是一个SolrCloud应用的例子:

uploading.4e448015正在上传…重新上传取消

对上图进行图解,如下:

uploading.4e448015正在上传…重新上传取消

      1. 物理结构

三个Solr实例( 每个实例包括两个Core),组成一个SolrCloud。

      1. 逻辑结构

索引集合包括两个Shard(shard1和shard2),shard1和shard2分别由三个Core组成,其中一个Leader两个Replication,Leader是由zookeeper选举产生,zookeeper控制每个shard上三个Core的索引数据一致,解决高可用问题。

用户发起索引请求分别从shard1和shard2上获取,解决高并发问题。

        1. collection

Collection在SolrCloud集群中是一个逻辑意义上的完整的索引结构。它常常被划分为一个或多个Shard(分片),它们使用相同的配置信息。

比如:针对商品信息搜索可以创建一个collection。

collection=shard1+shard2+....+shardX

        1. Core

每个Core是Solr中一个独立运行单位,提供 索引和搜索服务。一个shard需要由一个Core或多个Core组成。由于collection由多个shard组成所以collection一般由多个core组成。

        1. Master或Slave

Master是master-slave结构中的主结点(通常说主服务器),Slave是master-slave结构中的从结点(通常说从服务器或备服务器)。同一个Shard下master和slave存储的数据是一致的,这是为了达到高可用目的。

        1. Shard

Collection的逻辑分片。每个Shard被化成一个或者多个replication,通过选举确定哪个是Leader。

  1. SolrCloud搭建

SolrCloud结构图如下:

uploading.4e448015正在上传…重新上传取消

参考:“solrcloud搭建.docx”文档

    1. 环境准备

CentOS-6.5-i386-bin-DVD1.iso

jdk-7u72-linux-i586.tar.gz

apache-tomcat-7.0.57.tar.gz

zookeeper-3.4.6.tar.gz

solr-4.10.3.tgz

服务器7台:

zookeeper三台:192.168.0.5,192.168.0.6,192.168.0.7

Solr四台:192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.4

    1. 环境安装
    1. CentOs 6.5安装

    1. jdk7安装

    1. zookeeper集群安装
      1. 解压zookeeper 安装包

tar -zxvf zookeeper-3.4.6.tar.gz

将zookeeper-3.4.6拷贝到/usr/local下并将目录 名改为zookeeper

至此zookeeper的安装目录为/usr/local/zookeeper

      1. 进入zookeeper文件夹,创建data 和logs

创建目录并赋于写权限

指定zookeeper的数据存放目录和日志目录

      1. 拷贝zookeeper配制文件zoo_sample.cfg

拷贝zookeeper配制文件zoo_sample.cfg并重命名zoo.cfg

cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper /conf/zoo.cfg

      1. 修改zoo.cfg

加入 dataDir=/usr/local/zookeeper/data

dataLogDir=/ usr/local/zookeeper/logs

server.1=192.168.0.5:2888:3888

server.2=192.168.0.6:2888:3888

server.3=192.168.0.7:2888:3888

zoo.cfg配制完后如下:

# The number of milliseconds of each tick

tickTime=2000

# The number of ticks that the initial

# synchronization phase can take

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

# do not use /tmp for storage, /tmp here is just

# example sakes.

dataDir=/usr/local/zookeeper/data

# the port at which the clients will connect

clientPort=2181

# the maximum number of client connections.

# increase this if you need to handle more clients

#maxClientCnxns=60

#

# Be sure to read the maintenance section of the

# administrator guide before turning on autopurge.

#

# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance

#

# The number of snapshots to retain in dataDir

#autopurge.snapRetainCount=3

# Purge task interval in hours

# Set to "0" to disable auto purge feature

#autopurge.purgeInterval=1

#dataLogDir=/usr/local/zookeeper/logs

server.1=192.168.0.5:2888:3888

server.2=192.168.0.6:2888:3888

server.3=192.168.0.7:2888:3888

      1. 进入data文件夹 建立对应的myid文件

例如server.1为192.168.0.5则 data文件夹下的myid文件内容为1

server.2为192.168.0.6则 data文件夹下的myid文件内容为2

依此类推

      1. 拷贝zookeeper文件夹到其他机器(192.168.0.6和192.168.0.7)
      2. 开启zookeeper的端口

/sbin/iptables -I INPUT -p tcp --dport 2181 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 2888 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 3888 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT --这里开启tomcat 8080端口

/etc/rc.d/init.d/iptables save #将更改进行保存

/etc/init.d/iptables restart #重启防火墙以便改动生效

      1. 启动三台服务器的zookeeper

进入/usr/local/zookeeper /bin

./zkServer.sh start

查看集群状态

./zkServer.sh status

刚启动可能会有错误,集群中其他节点一并起来后就正常了

    1. tomcat安装

将apache-tomcat-7.0.57.tar.gz拷贝到/usr/local下并解压

cd /usr/local

tar -zxvf apache-tomcat-7.0.57.tar.gz

    1. solr单机部署
      1. 解压solr.4.10.3.tgz

在其中一台服务器上解压solr.4.10.3.tgz,将solr.4.10.3.tgz拷贝到/usr/local下,解压缩:

tar -zxvf solr-4.10.3.tgz

压缩后在/usr/local下有 solr-4.10.3目录 。

      1. solrhome

在/home下创建solr作为solrhome 并赋于读写权限

      1. 部署solr.war

参考solr单机部署方法。

启动tomcat 访问 http://192.168.0.1:8080/solr 如图,至此单机版solr配制完成

uploading.4e448015正在上传…重新上传取消

    1. solrCloud部署
      1. 启动zookeeper

solrCloud部署依赖zookeeper,需要启动每一台zookeeper服务器。

      1. zookeeper管理配置文件

由于zookeeper统一管理solr的配置文件(主要是schema.xml、solrconfig.xml), solrCloud各各节点使用zookeeper管理的配置文件。

将上边部署的solr单机的conf拷贝到/home/solr下。

执行下边的命令将/home/solr/conf下的配置文件上传到zookeeper:

sh /solr/solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh -zkhost 192.168.200.149:2181,192.168.200.150:2181,192.168.200.151:2181 -cmd upconfig -confdir /solr/solr-4.10.3/example/solr/collection1/conf -confname myconf -solrhome /solr/solr-4.10.3/example/solr

登陆zookeeper服务器查询配置文件:

cd /solr/zookeeper/bin/

./zkCli.sh

uploading.4e448015正在上传…重新上传取消

      1. 修改SolrCloud监控端口为8080:

修改每个solr的/solr/solr-4.10.3/example/solr/solr.xml文件。

uploading.4e448015正在上传…重新上传取消

      1. 每一台solr和zookeeper关联

修改每一台solr的tomcat 的 bin目录下catalina.sh文件中加入DzkHost指定zookeeper服务器地址:

JAVA_OPTS="-DzkHost=192.168.0.5:2181,192.168.0.6:2181,192.168.0.7:2181"

      1. 启动所有的solr服务

启动每一台solr的tomcat服务。

      1. 访问solrcloud

访问任意一台solr,左侧菜单出现Cloud:

uploading.4e448015正在上传…重新上传取消

      1. SolrCloud集群配置

上图中的collection1集群只有一片,可以通过下边的方法配置新的集群。

创建新集群collection2,将集群分为两片,每片两个副本。

http://192.168.200.149:8080/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2

uploading.4e448015正在上传…重新上传取消

删除集群命令;

http://192.168.200.149:8080/solr/admin/collections?action=DELETE&name=collection1

执行后原来的collection1删除,如下:

uploading.4e448015正在上传…重新上传取消

更多的命令请参数官方文档:apache-solr-ref-guide-4.10.pdf

另一种配置方法:如下

${solr_home}/collenction1/core.properties

numShards=2

name=collection1

shard=shard1

coreNodeName=core_node1

以上参数说明

numShards=2 //分片数量

name=collection1 //core名称

shard=shard1 //所属分片

coreNodeName=core_node1 //结点名称

    1. SolrCloud测试

创建索引:

测试1:在一台solr上创建索引,从其它solr服务上可以查询到。

测试2:一次创建100个文档甚至更多,通过观察每个solr的core下边都有索引文档,说明索引文档是分片存储。

查询索引:

从任意一台Solr上查询索引,返回一个完整的结果,说明查询请求从不同的分片上获取数据,最终返回集群上所有匹配的结果。

    1. solrJ访问solrCloud

public class SolrCloudTest {

// zookeeper地址

private static String zkHostString = "192.168.101.7:2181,192.168.101.8:2181,192.168.101.9:2181";

// collection默认名称,比如我的solr服务器上的collection是collection2_shard1_replica1,就是去掉“_shard1_replica1”的名称

private static String defaultCollection = "collection2";

// 客户端连接超时时间

private static int zkClientTimeout = 3000;

// zookeeper连接超时时间

private static int zkConnectTimeout = 3000;

// cloudSolrServer实际

private CloudSolrServer cloudSolrServer;

// 测试方法之前构造 CloudSolrServer

@Before

public void init() {

cloudSolrServer = new CloudSolrServer(zkHostString);

cloudSolrServer.setDefaultCollection(defaultCollection);

cloudSolrServer.setZkClientTimeout(zkClientTimeout);

cloudSolrServer.setZkConnectTimeout(zkConnectTimeout);

cloudSolrServer.connect();

}

// 向solrCloud上创建索引

@Test

public void testCreateIndexToSolrCloud() throws SolrServerException,

IOException {

SolrInputDocument document = new SolrInputDocument();

document.addField("id", "100001");

document.addField("title", "李四");

cloudSolrServer.add(document);

cloudSolrServer.commit();

}

// 搜索索引

@Test

public void testSearchIndexFromSolrCloud() throws Exception {

SolrQuery query = new SolrQuery();

query.setQuery("*:*");

try {

QueryResponse response = cloudSolrServer.query(query);

SolrDocumentList docs = response.getResults();

System.out.println("文档个数:" + docs.getNumFound());

System.out.println("查询时间:" + response.getQTime());

for (SolrDocument doc : docs) {

ArrayList title = (ArrayList) doc.getFieldValue("title");

String id = (String) doc.getFieldValue("id");

System.out.println("id: " + id);

System.out.println("title: " + title);

System.out.println();

}

} catch (SolrServerException e) {

e.printStackTrace();

} catch (Exception e) {

System.out.println("Unknowned Exception!!!!");

e.printStackTrace();

}

}

// 删除索引

@Test

public void testDeleteIndexFromSolrCloud() throws SolrServerException, IOException {

// 根据id删除

UpdateResponse response = cloudSolrServer.deleteById("zhangsan");

// 根据多个id删除

// cloudSolrServer.deleteById(ids);

// 自动查询条件删除

// cloudSolrServer.deleteByQuery("product_keywords:教程");

// 提交

cloudSolrServer.commit();

}

}

以上内容由“WiFi之家网”整理收藏!。

原创文章,作者:192.168.1.1,如若转载,请注明出处:https://www.224m.com/232158.html

(0)
192.168.1.1192.168.1.1
上一篇 2022年11月9日 09:50
下一篇 2022年11月9日 09:50

相关推荐