Jetty(6.1.3)
Entitytag也是一种新的方法来进行鉴别,它比使用lastmodifieddate更加的强健和灵活。
ETag是一个字符串。
在Solr的索引更新以后,当前的ETag会随之改变。
Solr缓存
Solr为缓存使用了LRU算法,缓存存放在内存中,缓存和IndexSearcher关联在一起,维持了一个数据的快照(asnapshotviewofdata).在一个commit之后,新的indexsearcher打开,并会自动预热(auto-warmed).自动预热指的是之前搜索的缓存会被拷贝到新的searcher。
接着,预先在solrconfig.xml中定义的searcher会运行。
为那些需要排序的字段(field)加入一些典型的query到newSearcher和firstSearcher,这样,新的searcher就能为新的搜索提供服务了。
Solr1.4使用了FastLRUCache,它比LRUCache要更快,因为它无需单独的线程来移除无用的items。
通过Solr的statistics页面,你可以看到你的缓存有多大,并且可以根据实际情况对缓存的大小进行调整以适应最新的情况。
设计更好的Schema
你需要考虑是否indexed,是否stored等等,这些将决定于你应用程序的具体情况。
如果你存储很大的文本到你的索引中,你最好使用field的compressed选项配置对其进行压缩。
如果你不是总需要读取所有的fields,那么在solrconfig.xml中配置使用field延迟加载:
true
这会起到很好的作用。
注意:
如果你使用了compressed,那么你可能需要使用field延迟加载,同时还要降低解压缩的代价。
另外降低文本分析的数量将有效提高性能,因为文本分析会消耗大量的CPU时间,并且使得你的索引大幅增大。
索引策略
一种加速索引的方式是分批索引,这样将会显著加速性能。
但是,随着你的document增加,性能还是会开始下降。
根据经验,对于大的document,每批索引10个,而对于小的document,每批索引100个,并分批提交。
另外,使用多线程进行索引将会再次提高性能。
取消document唯一性检查(Disableuniquedocumentcheck)
默认情况下,索引的时候Solr会检查主键是否有重复的,以避免不同的document使用相同的主键。
如果你确认你的document不会有重复的主键,将参数allowDups=true加到url上可以取消检查,对于scv文档,使用overwrite=false。
Commit/optimize因子(factors)
对于大的索引以及频繁的更新,使用较大的mergeFactor,它决定了Lucene会在segments数量达到多少时将它们合并(merge)。
优化Faceting(分组查询)的性能
使用TermVectors
TermVectors是某field经文本分析之后的一系列terms。
它一般包括了term的频率,document的频率和在文本中的数值偏移量,启用它有可能会增强MoreLikeThis查询和Hignlight查询的性能。
但是启用ternvectors会增加索引的大小,并且可能根本不会在MoreLikeThis和Highlight查询结果中。
提升phrase查询的性能
在大索引的查询中,phrase查询的性能会很慢,因为,某个phrase可能会出现在很多的document中,一种解决办法是使用filter过滤掉诸如“the”这样没有意义的词语。
但是这样会使得搜索出现歧义,解决方案是使用Shingling,它使用类似n-gram的方法将搜索句子切分,如“Thequickbrownfoxjumpedoverthelazydog”将会变为"thequick","quickbrown",
"brownfox","foxjumped","jumpedover","overthe","thelazy","lazydog".粗糙的测试表明,这样至少可以提高2-3倍的性能。
使用多Solr服务器(Scalewide)
当你对单台Solr服务器的调优仍然无法满足性能需求的时候,接下来你应该考虑拆分查询请求到不同的机器上,具备横向扩展(Scalewide)是可扩展系统的最基本的特点,因此,solr也具备了该特点。
ScriptVSJavareplication
在Solr1.4之前,replication是通过使用Unix脚本进行的。
一般来说,这种方案还算不错,但是可能有一些复杂了,需要编写shell脚本,cronjobs和resyncdaemon。
从1.4开始,Solr实现了基于Java的复制策略,不用再编写复杂的shell脚本,并且运行得更快。
Replication的配置在solrconfig.xml之中,并且配置文件本身可以在master和slave服务器之间被复制。
Replication目前已经支持Unix和Windows系统并且已经集成到了Admininterface之中。
Admininterface目前可以控制复制---例如,强制开始replication或者终止失效(stalled)的复制。
复制是通过ReplicationHandler提供的RESTAPI进行的。
如果你在多个Solr服务器之间使用了同一个solrconfig.xml文件,那么你需要在启动的时候指定以下几个参数:
l -Dslave=disabled:
指定当前solr服务器是Master。
Master将负责推送索引文件到所有slave服务器。
你将会存储document到master上,而在slave服务器上进行查询。
l -Dmaster=disabled:
指定当前solr服务器是Slave。
Slave要么定期轮询Master服务器来更新索引,要么手动的通过Admininterface触发更新操作。
一组slave将会被负载均衡(可能是HAProxy之类)器管理着来对外提供搜索。
如果你想在同一机器上运行多个Solr服务器,那么你需要通过-Djetty.port=8984指定不同的端口,并且通过-Dsolr.data.dir=./solr/data8984指定不同的data目录。
配置Replication
配置replication很简单,在./examples/cores/mbreleases/solrconfig.xml中就有示例配置:
master}">
startup
commit
stopwords.txt
slave}">
http:
//localhost:
8983/solr/replication
00:
00:
60
注意${}将能够运行期进行配置,它将通过-Dmaster=disabled 或-Dslave=disabled决定这里的参数是master还是slave。
Master机器已经配置了在每次commit之后进行replication。
并且可通过confFiles属性以指定复制配置文件。
复制配置文件非常有用,因为你可以在运行期修改配置而无需重新部署。
在master上修改配置文件,replication到slave后,Slave将会知道配置文件被修改了,并reloadcore。
可以参考http:
//wiki.apache.org/solr/SolrReplication
Replication的实现
Master是感知不到Slave的存在的,Slave会周期性的轮询Master来查看当前的索引版本。
如果Slave发现有新的版本,那么Slave启动复制进程。
步骤如下:
1. Slave发出一个filelist命令来收集文件列表。
这个命令将返回一系列元数据(size,lastmodified,alias等等)
2. Slave查看它本地是否有这些文件,然后它会开始下载缺失的文件(使用命令filecontent)。
如果连接失败,则下载终止。
它将重试5次,如果仍然失败则放弃。
3. 文件被下载到了一个临时目录。
因此,下载中途出错不会影响到slave。
4. 一个commit命令被ReplicationHandler执行,然后新的索引被加载进来
索引一些文件到Master上
你可以用SSH运行两个session,一个开启Solr服务,另一个索引一些文件:
>>curlhttp:
//localhost:
8983/solr/mbreleases/update/csv-Ff.r_
attributes.split=true-Ff.r_event_country.split=true-Ff.r_event_
date.split=true-Ff.r_attributes.separator=''-Ff.r_event_country.
separator=''-Ff.r_event_date.separator=''-Fcommit=true-Fstream.
file=/root/examples/9/mb_releases.csv
上面的命令索引了一个csv文件。
你可以通过Admininterface监控这个操作。
配置Slave
之前已经索引了文件,并且通过复制已经到了slave上,接下来,需要使用SSH到slave机器上,配置masterUrl如下:
slave}">
http:
//ec2-67-202-19-pute-:
8983/solr/mbreleases/replication
00:
00:
60
你可以到Admininterface上查看当前的replication状况。
由于使用了多个Slave,所以我们没有一个固定的请求URl给客户的,因此,我们需要使用负载均衡,这里使用了HAProxy。
在master机器上,配置/etc/haproxy/haproxy.cfg,将你的salve机器的url放入:
listensolr-balancer0.0.0.0:
80
balanceroundrobin
optionforwardfor
serverslave1ec2-174-129-87-pute-:
8983
weight1maxconn512check
serverslave2ec2-67-202-15-pute-:
8983
weight1maxconn512check
solr-balancer处理器将会监听80端口,并将根据权重将请求重定向到每个Slave机器,运行
>>servicehaproxystart
来启动HAProxy。
当然,SolrJ也提供了API来进行负载均衡,LBHttpSolrServer需要客户端知道所有slave机器的地址,并且它没有HAProxy这样的强健,因为它在架构上实现得很简略。
可以参考:
http:
//wiki.apache.org/solr/LBHttpSolrServer
Sharding是一种当你的数据太多时很普遍的对单台数据库进行扩展的策略。
在Solr中,sharding有两种策略,一是将一个单一的Solrcore分成多个Solr服务器,二是将单核的Solr变成多核的。
Solr具备将单一的查询请求分发到多个Solrshards上,并聚集结果到一个单一的result里返回调用者。
当你的查询在单台服务器上执行太慢时你就需要组合多台solr服务器的能力来共同完成一个查询。
如果你的查询已经足够快了,而你只是想扩展以为更多用户服务,那么建议你使用全索引而使采用replication的方法。
使用Sharding并不是一个完全透明的操作。
关键的约束就是当索引一个document,你需要决定它应当在哪个Shards上。
Solr对于分布式索引并没有相关的逻辑支持。
那么当你搜索的时候你需要加上shards参数到url,以确定需要到哪些shards上收集结果。
这意味着客户端需要知道Solr的架构。
另外,每个document需要一个唯一的id,因为你是基于行将其拆分的,需要一个id来区分彼此。
分发documents到shards
一种比较好的办法是对id进行hash,在模分片的大小来决定应当分发到哪个shards上:
SHARDS=['http:
//ec2-174-129-178-110
.compute-:
8983/solr/mbreleases',
'http:
//ec2-75-101-213-59
.compute-:
8983/solr/mbreleases']
unique_id=document[:
id]
ifunique_id.hash%SHARDS.size==local_thread_id
#indextoshard
end
这样,在你的shards不变化的情况下,你的document将会很好的找到它的shards。
跨多个shards搜索(Searchingacrossshards)
这个功能是已经配置在queryrequesthandler里面的。
因此你无需做额外的配置,如果你想在两个shards上面进行查询,那么你只需要在url跟相关的参数即可:
>>http:
//[SHARD_1]:
8983/solr/select?
shards=ec2-174-129-178-110.
compute-:
8983/solr/mbreleases,ec2-75-101-213-pute-
:
8983/solr/mbreleases&indent=true&q=r_a_name:
Joplin
注意shards后的参数不能跟http这样的传输协议,并且你可以跟尽量多的shards,只要你不超过GETURL的最大字符数4000.
在使用Shards的时候,请务必注意以下内容:
l Shards仅仅支持以下组件(Component):
Query,faceting,Hignlighting,Stats和Debug
l 每个document必须有一个唯一的id。
Solr是根据这个来合并搜索结果document的。
l 如果多个shards返回了相同id的document,那么第一个会被选中,而余下的被忽略。
联合使用Replication和Shards(ScaleDeep)
如果你使用了前面的方法,仍然发现性能无法满足要求,那么是到了将两个联合起来组成更高层次的架构来达到你的需要的时候了。
你需要使用同样的方法配置一组Master,这样最终你将有一棵树一样的Masters和Slaves。
你甚至可以有一个专用的Solr服务器,它没有索引,只负责将查询分发的shards上,并在最后合并结果返回用户。
数据的更新将通过在Master机器上更新并replication到slave机器上实现。
前端需要相关的负载均衡支持,但是这样一来,Solr将能够处理极大的数据。
关于Solr的下一步scaling,在Solr的邮件列表里面已经讨论了很多次,一些调查研究显示,Hadoop能够提供强健可靠的文件系统。
另一个有趣的项目是ZooKeeper,它将能对分布式系统进行集中式的管理,对于将ZooKeeper集成进来已经有不少努力。