《Solr in Action》读书笔记

4.3.1 新建搜索器

在 Solr 中,任何时候只能存在一个处于活跃粗体文本状态的搜索器,所有搜索请求处理器中的查询组件都会向这个处于活跃状态的搜索器发起查询请求

处于活跃状态的搜索器拥有底层 Lucene 索引快照的只读视图,如果将一份文档添加到 Solr 中,它在当前搜索器的搜索结果中是不可见的,所以为了让新文档能够出现在搜索结果当中,需要关闭当前的搜索器,打开一个新的搜索器

提交操作会创建新的搜索器,以确保更新后的文档和索引可以被搜索器检索到,所有基于当前搜索器中索引视图的缓存对象都将失效

4.3.2 新搜索器预热

Solr的两种预热机制 :

  1. 利用旧缓存自动预热新缓存
  2. 执行缓存预热查询

    在 solrconfig.xml 中定义缓存查询语句

<listener event="newSearcher" class="solr.QuerySenderListener">
  <arr name="queries">
    <lst><str name="q">solr</str><str name="sort">price asc</str></lst>
    <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst>
  </arr>
</listener>

第一个搜索器

在 Solr 的初始化过程中或重新加载完一个内核之后会预热第一个搜索器

在 solrconfig.xml 中为第一个搜索器配置预热查询语句

<listener event="firstSearcher" class="solr.QuerySenderListener">
  <arr name="queries">
    <lst>
      <str name="q">static firstSearcher warming in solrconfig.xml</str>
    </lst>
  </arr>
</listener>

useColdSearcher

<useColdSearcher> 适用于一个搜索请求已经被提交,但是目前 Solr 中没有定义搜索器的情形

如果 <useColdSearcher> 的值为 false,那么 Solr 将会一直处于阻塞状态,直到正在预热的搜索器执行完所有的预热查询

maxWarmingSearchers

在新搜索器预热完成之前发出新的提交,那么在当前搜索器预热完成之前,另一个搜索器的预热又开始了。如果搜索器的预热时间很长,那么这种情况就会经常发生,如果并发预热的搜索器过多会耗尽服务器的内存和 CPU 资源

<maxWarmingSearchers> 可以控制并发预热的搜索器的最大数目,一旦达到阀值,新的提交将会失败。Solr 中该元素的默认值为 2

4.4.1 缓存原理

缓存大小

Solr 能够将所有缓存的对象都保存在内存中,不会溢出到硬盘上

最近最久未使用(Least Recently Used, LRU) 根据缓存对象最后一次被请求的时间来决定缓存对象被回收的次序

Solr 默认的缓存算法

最近最少使用(Least Frequently Used, LFU) 根据缓存对象被请求频率的高低决定缓存对象被回收的次序

Solr 过滤器缓存使用的算法

如果没有根据垃圾回收的实际情况对缓存大小进行合适的调整,就可能导致服务器因垃圾回收而长时间暂停服务

缓存命中率与缓存回收

缓存命中率 指应用程序的缓存命中的用户请求数量占所有用户请求数量的比例

缓存回收数 指有多少缓存对象根据缓存置换算法被回收了

如果缓存回收数很大,则表明应用程序的缓存对象数量的最大值设置的太小

自动预热新的缓存

自动预热 指 Solr 利用即将关闭的旧搜索器中的部分缓存内容构建新搜索器的缓存

每一个自动预热的缓存都支持 autowarmCount 属性,表示自动预热的旧缓存对象的最大数目或百分比

4.4.2 过滤器缓存

自动预热过滤器缓存

缓存中的每一个对象都有一个键,对于过滤缓存来说,这个键就是过滤查询语句

预热新的缓存时,一部分键从旧的缓存中抽取出来,向新的搜索器提交查询,形成新的过滤器

要利用新搜索器自动预热过滤器缓存,就需要 Solr 重新执行过滤查询

7.8.1 按字段排序

对于相同得分的文档,根据搜索索引的 Lucene 内部文档编号以升序方式进行排序。
如果没有相关度得分,则按 Lucene 内部文档编号进行排序

对缺失值排序

与查询相匹配但不包含该排序字段的文档 <fieldType name = "string" class="solr.StrField" sortMissingLast = "true" sortMissingFirst = "true" 如果 sortMissingLast = true,则不管排序方向如何,不包含该字段的所有文档都会显示在搜索结果排序列表的末尾。sortMissingFirst = true 则相反。

12.3.1 内存和固态硬盘

在大部分操作系统中,当文档加载到内存,它将一直保存在内存中,直到系统要求回收这部分内存以作他用。保存内存中最近加载的文件直到所有可用内存都已消耗完毕(或者被缓存的文档最近不经常被访问,需要被释放以加载新的文档)。

12.3.3 索引切换

增量索引

增量索引原则 : 总是将修改添加到新文档中,而不添加到之前已写的文件中。

在许多更新请求被提交之后,Solr 中存在许多索引块,需要将它们合并成新的索引块。合并过程并不会修改旧的索引块,而是创建新的索引块,使旧的索引块失效。当旧的索引块文件不再被 Solr 引用的时候,它们会被删除以释放磁盘空间。

12.9.3 从请求处理器和 Mbeans 获取统计信息

处理器的 Solr 性能统计请求 : /solr/core1/admin/mbeans?stats=true&wt=json

12.9.9 加载测试

SolrMeter

13.1.1 在云模式下启动 Solr

每个索引分割称为分片,每个分片包含应用大约 1 / 分片数量 的文档

SolrCloud 下的分布式查询

一个文档仅能存在于唯一的分片中。每个分片占用独有的散列分区,散列函数会试图在分片之间将各个文档进行均匀分配,所以集群中每个分片的大小大致相同

13.1.2 SolrCloud 架构的驱动因素

可扩展性

复制增加了索引能同时执行查询的数量,分布式查询会被发送到每个分片的一个副本上

高可用性

SolrCloud 的一个关键的设计原则是 : 集群里的每个节点都能创建索引和执行查询

硬件方面提升 Solr 节点的容错性 : 对磁盘阵列进行 RAID 配置

一致性

Solr 确定一次写操作是否成功时,只会考虑处于激活状态和处于恢复过程中的副本,不会考虑离线副本也需要更新的问题

目前 SolrCloud 对于弱一致性是零容错,即写操作在分片的所有副本上都必须执行成功

13.4.2 分布式搜索的局限性

  1. 倒排文档频次(idf)仅基于本地索引中的词频

    https://issues.apache.org/jira/browse/SOLR-1632 好像已经被 fixed