ES常见问题汇总

请问es怎样zk来监听?

大家可以先参考一下文章中的“图9 异地双集群互备架构图”
http://7xpvay.com1.z0.glb.clouddn.com/09936bd0-c0ec-11e6-8b71-f520a7c97e7c

能详细说下es集群监控这块吗?比如怎么获取健康值和节点状态,发生异常后第一时间自动告警给相关人员。

借助ZK监控ES集群一般由2部分组成:
1. ES集群健康监控服务:一般为一个WebService,此服务在启动之初,利用ES客户端集群管理API判定每个ES集群是否正常,将正常服务的ES集群在ZK中创建一个与其相对应的指定Path,即完成ES集群服务注册;然后由运维帮忙设定一个针对该WebService的心跳检测,例如每隔3秒使用ClusterStatsResponse探测一下所监控的每个ES集群的健康状况(绿:健康、黄:有潜在风险、红:异常,例如索引丢失、服务不存在),根据服务返回结果标识,一旦发现异常即可报警。
2. 搜索服务/索引更新服务: 在系统启动之初,便开始监听来自ZK中代表该服务所用相关ES集群的特定Path,根据监听消息:Add或Delete,自动Add或Delete代表相关ES集群的客户端连接,从而可以保证在异地ES集群之一发生故障时,该集群对应客户端已经删除,而另一个热备ES集群还可以继续使用,而不影响现有线上搜索服务。

可否多讲讲ES在日志分析方面的实施案例?

ES在日志分析方面主要借助其比较强大的ELK组合,其典型应用实例可以参考这篇文章:http://www.importnew.com/20464.html ,该文章介绍了ELK工作基本原理,最后以收集log4j日志为例介绍。

随着Beats发布及应用,现在ELKB组合更受欢迎,大家可以参考这篇文章:http://www.ibm.com/developerworks/cn/opensource/os-cn-elk-filebeat/index.html ,对为什么引入Beats以及Beats不同类型做了更详细的介绍。

ES的多个集群能否做到平滑切换,比如我希望在每天重建索引的时候一个ES集群先重建然后再重建另外一个

ES多个集群想做到平滑切换,就要保证多个集群相同索引的数据一致性,多集群数据一致性保证:一般通过索引写入API的封装,比如,向2个ES集群的相同索引插入一条数据或一批数据,这时可使用JDK8提供的CompletableFuture异步请求,异步并发写到2个集群,以提高效率。

关于ES 的发布,现在偶尔会修改ES 的配置,这样每次都必须修改每个节点,有时候办法可以通过统一部署来解决修改配置问题吗?

ES集群搭建之初,一般全局性配置JVM对内存、脚本功能是否开启、默认Shard数量和Replica数量等在配置文件统一配置好即可。ES一个特色在于,对于索引Mapping的动态配置,可以借助脚本,动态调整. 例如常用的创建、修改、删除索引。

对于分词这块,你们是如何维护的?词库如何动态添加或发现新词?

ES插件对中文分词支持比较好,比如 IK、mmseg、nsj等,如果想实时更新专有词库,目前可以考虑2种开源方案:
1. IK: 监听一个远程http访问的词库,定时默认每10秒根据其lastmodifytime是否更新来重新加载词库,实现词库近实时更新;
2. ANSJ: 通过借助Redis的pub-sub机制,实现新词添加或旧词删除。

我们目前在用solr实现全文检索,每天大概几十t的数据量吧,但在实时检索上达不到,一般需要一天的时间才能把前天的数据都导入到solr中?如果采用es的话,能做到实时检索吗?看文章里es的导入速度更慢。另外,如果迁移的话,代价会很高吗?

1). 每天数据量几十T属于比较大的数据,全部写入一个索引中,索引会比较大,这时即使换成ES,实时检索效果也不见得有效果。因此存入索引时,是不是可以考虑做些优化,建议如下3点:
1. 这些数据在存入ES时是不是可以考虑精简,只把涉及查询的字段存入索引;
2. 存入ES的索引在mapping设置时,不要设置store属性为true,因为所有字段默认都会在_source中存在,再设置store属性为true,相当于存了2份数据;
3. 一天数据量达到这几个级别,为提高效率,是不是可以考虑索引按小时存放,减小单个索引的数据量; 查询时,根据时间跨度,异步并发从多个小时段内的小索引查找再merge到一起。

2) ES和Solr底层都是基于Lucene,其现有索引数据理论上是兼容的,对于迁移,把Solr中索引字段都变更到ES的mapping设置好,理论说代价不会太大,这个需要具体做下实验。ES和Solr比较,个人认为:感觉ES使用更简单,上手更快,ES集群搭建比SolrCloud集群搭建要简单很多,其官方提供的ES-client使用也非常全面。

文中说当数据量变大时,加多一些索引。那么有没有这个数据量和索引什么配对比例性能最优, 或者说不同索引不同分片几种方案的对比得出最优方案,这方面有什么具体指标? 当遇到搜索性能瓶颈时,分析解决思路树,比如遇到查询慢了是该加索引,大索引,做多分片?

索引拆分,这个需要根据具体业务来定,文中提到的方案,是因为一般新闻查询都有时效性要求,对于一些从来不会检索到的内容,如果还维持在一个大索引库里,就会造成这个大索库非常臃肿,查询效率低下,因此需要一个只保留满足业务需求最大时间跨度的新闻即可,而且需要滚动更新,每天将超时doc移植到过时索引库,以提高效率。

遇到慢查询:是该加索引,大索引,做多分片?这个问题 还要看总体数据量和查询业务需求,以及当前性能瓶颈,这个目前没有普适指标要求。不过一般而言,索引分片不易过多,也不易过少,一般单个shard索引数据量达到100G以上,就可以考虑是不是索引分层。

最新ES5.0会大大减少索引占用空间、提高查询性能,这个值得实验下。

上面说了不用springmvc,用了jetty。后端RPC最后选了哪个?之后跟zk,mq等等组件一起构建时候,你们的项目用了Spring cloud吗?

之所以不选择springmvc而实用Jetty实现 webservice,在于其更加轻量,简单易用。
后端RPC,一般使用thrift或其结合netty的优化升级版nifty。

SpringCloud是一个比较强大的开发工具,也相对比较重量级,有一定学习成本。SpringCloud结合SpringData大有一统天下之势,做了大量封装,让使用相关组件相对简单。
具体应用中,是否选用SpringCloud、SpringData、SpringMVC要靠所在开发团队技术偏好,毕竟现在时团队并肩作战。
对于创业企业,要求短平快,一般尽量使用轻量级技术框架快速解决问题。

可否多讲讲es内部的一些实现,感觉偏运维多,希望多一些面向开发的。比如并发情况下跨多个索引进行查询性能调优。

ES对于开发而言,使用比较多的功能模块一般集中在: TransportClient(ES连接客户端)、suggestion(建议)、aggregation(聚合)、QueryBuilders(查询构造)、SearchRequestBuilder(查询请求构造器)和ClusterAdminClient(集群管理),此外有关ES的字段类型以及索引实时更新原理(文中已经提到)。

并发情况下跨多个索引查询性能优化,建议如下:
1. 一次跨索引检索请求,转化为应对多个索引的异步并发请求,可以参考前述提到的JDK8提供的CompletableFuture,这样对于多个索引请求,返回结果依赖于耗时最长的那个索引检索耗时。
2. 对于比较复杂的查询请求,QPS比较高时,可以使用GuanvaCache本地缓存(限时限个数)相同条件的检索结果,为减少ES集群压力。 其中查询条件一般比较多,这里我们可以考虑使用MD5值对每次查询条件加密,以缩小GuavaCache中缓存key的大小。

高可用性那部分,俩个ES集群怎么确保数据的一致性。

多个集群相同索引的数据一致性:一般通过索引写入API的封装,比如,向2个ES集群的相同索引插入一条数据或一批数据,这时可可以在该次请求中:使用JDK8提供的CompletableFuture异步请求异步并发写到2个集群,以提高效率。

同时还需要在索引中增加一个“addTime”的时间戳,最好是形如:“20161228180629” 这样的形式,一旦有某个集群故障,回头弥补数据时,还可以从服务正常集群中,根据故障缺失时间段查找到相关doc,再补上。

目前我们正在做拼音搜索,是在建立索引的时候,用ik和mecl分词器同时建立中文和拼音的2个字段。请问你们这个方案可行否?还有你们做拼音搜索的时候是怎么解决的?

拼音搜索,一般考虑全拼和简拼,这里汉字转拼音,可以考虑使用pinyin4j的api,也可以考虑使用es的拼音插件https://github.com/medcl/elasticsearch-analysis-pinyin。

ES存储多对多的关系,在两类实体都可能被查询的情况下,怎么设计比较合理?比如说针对用户的标签系统。既可能会根据标签查用户,也可能会根据用户查标签,同时,可能还会根据打标签的时间来筛选标签。

ES支持关联查询,但其效率较低,尤其是针对大数据集,生产环境下实用还需要再完善。
对于这类关联实体查询,可以考虑像关系数据库设计那样,每个索引增加一个类似于外健的字段。
比如你这里提到的用户标签系统: 设置2个独立的索引,标签索引(其中含有打标时间)和 用户标签索引(userId,tagId),就可以满足根据标签查用户,也可能会根据用户查标签。
对于根据打标签的时间来筛选标签: 这个需要根据打标时间再标签索引库首先筛选出满足要求的标签ID集合,再使用该tagId集合再像用户标签索引库过滤相关用户等。

如果一个ES集群中有多个索引,是否有办法调节每个索引所占的资源。比如说。一个ES集群中,包含一个重要业务的索引,同时也包含了一个用于BI的索引。能否有办法限定BI的索引占用的资源比例

据我个人了解,目前还没有办法调节每个索引所占的资源。
ES集群虽然可以包含多个索引,但一般不建议集群中含有过多索引,尤其是资源竞争比较强烈的不同业务类型的索引。
可以按垂直业务拆分,为每个独立的垂直业务设立一个独立集群。

请问现在做多语言分词,有什么好的推荐插件,比如韩语或者泰语。另外汉语基础词库是否用IK自带的搜索词库就可以了,或者有什么更优的推荐吗?

对于中文分词,IK确实效果不错,尤其是结合前述说的ES-IK插件支持实时更新专有词词库。 多语言,尤其是小语种这块,了解不多。平时主要集中在中文和英语。对于中文分词,IK确实效果不错,尤其是结合前述说的ES-IK插件支持实时更新专有词词库。

词库更新后 以前建的索引是不是要重新建?如果要,请问有什么注意事项?

词库更新后,新词是不会对原有索引有效果的,新加入索引会有效果。如果重建索引,注意词库更新的时间,以及最好不要影响用户使用。

重建索引,为避免影响用户使用体验,可以考虑 文中提到的 异地双主集群模式, 在客户端指定用户访问哪个es集群。这样,2个ES 集群,一个重建,一个正常使用;然后轮循操作,直到2个集群都完成索引重建

类似于关系库的联合查询,在es中是如何实现的?

ES通过mapping来指定文档的nested-parent关系,实现关联,具体查询时指定has_child、has_parent父子查询:

对于搜索结果的评分如何设计更加科学,能举例说明么?

lucene默认评分或后加的 bm25 相关性评分 都是基于 tf/idf,
更加科学合理的评分: 一般都利用ES简单查询处候选集,然后结合具体业务,使用特定的数学模型,计算相关性平分

ES有成熟的离线建索引在线load的解决方案么?

一般实时索引更新,都是结合MQ完成;元数据生成方 将生成的最新doc原数据信息发到指定的mq
mq消费端 异步对所接受的数据实时插入索引;对于并发比较高的写,一般mq消费端,定时每隔1、2秒集中写一次数据;

我们用es有段时间了,经常会在异常关闭之后导致分片不可以,有什么建议?另外,单节点最大写入能做到多少?

一般索引太大时,写入效率会大大受影响。
所以文中曾提到 对于数据量比较大的索引考虑 索引拆分问题

个性化搜索一般是怎样的做法,比如用户搜 酒店,可能根据用户的画像拿到一些偏好,比如星级啊什么的,改写query的方式做个性化吗

这个问题 是搜索和推荐的结合, 实际上搜索和推荐界限很模糊;
这里建议:首先利用用户标签集合,从酒店标签 索引中 查询处 酒店候选集,
对候选集,在使用一定数学模型综合排序,然后取topN 返回;
关键看你们设计的数据结构我出版的书中,最后一章是一个完整的 用户画像 实时更新实例,可以参考一下

如何优化es实时索引的性能?

现在所谓的实时索引准确讲只能叫近实时索引更新,
SolrCloud和ES, 都是借助 内存存索引soft commit 和 硬盘索引hard commit相结合方式;一般默认每秒索引刷新一次
实际中,考虑到集群压力问题,会设定大于1秒;实时性本身也跟索引规模有关;就是之前说的片shard,索引拆分等,到一定阶段,都需要综合考虑

在建立索引的过程中,如何减轻Elasticsearch在merge大的segments时对CPU资源的消耗?

一般设定merge临届条件 要根据服务器负载情况 设定一个宽松的范围,避免影响前端搜索性能

es倒序索引的优势是什么?

搜索引擎从诞生至今,其速度优势就在于倒排索引,
和传统关系DB相比较,其优势在于,要查找的关键词,事先已经知道存在于那些doc中

公司使用 Sphinx和solr,目前查和排序有问题,现在想合并索引,请问一下有哪种较好的可行方案,Sphinx数据是从几十张表更新索引的,solr 是从一张大表更新索引

ES dfs查询的原理: 向索引查找返回50个doc, ES 集群收到请求后,会同时向各个shard 请求,每个shard返回top50, 然后再对所取回的各个shard 的top50合并,统一排序,最后得到的top50才是最终结果;
你们目前Sphinx索引来自几个表的数据,Solr来自一个大索引 是不是也可以考虑 采用类似模式;
如果 将2者合并到一起 可能你们会有很多额外开销,是不是可以考虑将2者得到的满足要起的结果,再次排序返回呢?