1、重启集群后,出现了unassigned shards
集群的shard数量较多,在节点重启后,由于recovery并发限制,shard分配次数超限,集群就不会在分配shard了,从而出现unassigned shards; 可以使用api对shard进行重新分配:POST _cluster/reroute?retry_failed=true
2、使用ES过程中,出现bulk reject, 查看日志看到bulk queue满了
可以通过GET _cat/thread_pool/bulk?s=queue:desc&v查看正在拒绝或者历史拒绝的个数;一般默认bulk queue大小是1024, 造成bulk reject的大多数原因大概有两种:
- shard容量多大,建议每个shard容量控制在20G-50G,shard数量不能过多,也不能过少
- shard分布不均,可通过调整index.routing.allocation.total_shards_per_node参数来解决
3、磁盘写满后,清理了一部分数据,此时无法向ES中写入数据
磁盘写满后,ES会把集群的block级别改为read_only_allow_delete, 此时需要修改该参数,通过调用PUT _cluster/settings {cluster. blocks.read_only_allow_delete:”false”}解决,如果出现index level级别的block贼需要修改对应索引的配置
4、使用logstash收集日志时,如何把logstash默认添加的@timestamp字段替换为日志中的时间?
1 | filter { |
5、使用logstash收集日志时,如何修改logstash默认添加的@timestamp字段的时区为东八区?
1 | filter { |
6、调用_forcemerge API发现并没有减少segment的数量?
_forcemerge API执行merge是有条件的,当索引数据量比较大时,经过了一定时间的merge之后,每个segement都会比较大,如果此时indexing的速率较低,merge操作期望可以merge的segment数量比较大,而实际上候选的segment数量没有那么大时,就不会触发merge操作
7、聚合查询越来越慢
需要确认进行聚合的字段唯一值是否比较多,唯一值较多的情况下聚合查询构建Global Ordinals会比较慢,如果索引没有持续写入,构建好的Global Ordinals就会进行缓存,之后的查询就可以使用缓存中的Global Ordinals;但是如果索引在持续写入,每当底层的segment发生变化时(有新数据写入导致产生新的Segment、Segment Merge),就需要重新构建Global Ordinals,随着数据量的增大聚合字段的唯一值越来越多,构建Global Ordinals越来越慢,所以对持续写入的索引,聚合查询会越来越慢。从业务角度进行优化的方案可以参考:https://cloud.tencent.com/developer/article/1421924
8、在kibana上创建index pattern卡主了,一直转圈圈,无法创建
首先确认下.kibana的索引是否被设置为只读了,当集群出现过磁盘写满时,ES会自动把索引设置block级别设置为readonly_allow_delete, 如果被设置为只读,需要修改block级别PUT .kibana/_settings {“index.blocks.read_only_allow_delete”:false}
9、通过logstash向ES写入日志报错:”type”=>”illegal_state_exception”, “reason”=>”Can’t get text on a START_OBJECT
原因是es对字段解析错误,类型是字符串(keyword或者text)的字段接收到的值为对象(如json对象),出现这种情况,可以在logstash 配置文件中使用json_encode filter plugin对原来是对象的字段转换为字符串。
10、查询dsl中使用了min_score参数用来限定返回文档的得分,为什么多次执行hit的文档数量不一致?
主分片和副本分片的差异导致的,底层segment可能不一致,特别是在有文档被删除的情况下主分片和副本分片的segment中标记删除的文档的数量可能会不一致(比如主分片进行了merge, 副本分片没有进行merge),导致最终主分片和副本分片上文档的得分不同,影响了最终的查询结果;可以在查询时指定preference=_primary指定只查询主分片解决,或者自定义preference解决
11、completion suggester自动补全功能,在添加seggest inputs时指定了多个词,为什么查询时options只返回一项?
1 | 创建索引并添加doc: |
completion suggester返回的options是文档级别的,查询命中后就会提前终止,所以只能返回第一个匹配到的值;解决方法是bat, bar两个词分别放在两个doc中
12、2核4G 3节点的集群,在保证集群性能稳定的情况下,最多可以支持多少shard?
每个节点上可以存储的分片数量与可用的堆内存大小成正比关系,分片数量越多,分片的元数据占用的内存越多,一般情况下,1GB的堆内存对应分片数量不超过20
13、ES报这个错误是什么原因
报错:”caused_by”=>{“type”=>”max_bytes_length_exceeded_exception”, “reason”=>”max_bytes_length_exceeded_exception: bytes can be at most 32766 in length; got 33023”}?
原因是索引中有字段为keyword类型,但是写入时的该字段的数据长度超过了keyword类型的最大长度32766个字节,可以把该字段的类型设置为text解决。
14、使用filebeat收集日志写入ES中,报错如下:
报错:”Bulk item insert failed (i=0, status=500): {“type”:”string_index_out_of_bounds_exception”,”reason”:”String index out of range: 0”}”
当filebeat的output.elasticsearch.index配置项有取自上游event中的某个字段,而某个event中该字段不存在时,想ES写入数据会报错。索引的名称如果要从event中的某个字段获取,需要确保该字段一定会存在。
15、ES的_refresh和_flush操作的区别是什么
refresh调用了lucene DirectoryReader的 openIfChanged()方法,相当于重新打开了indexReader, 使得写入的数据都可以被搜索到;flush操作调用了luecene IndexWriter的commit()方法,把仍在在文件系统缓存中的segment写入到磁盘中,实现了数据的真正持久化,flush同时还会触发refresh操作。
16、在ES的script query中,使用doc[‘my_field’].value和 params[‘_source’][‘my_field’],两种方式有什么不同?
使用doc[]的方式会把字段的所有terms都加载进内存并且会被缓存,因此比较消耗内存,同时doc[]的方式只支持单值字段;使用_source的方式terms不会被缓存,相比doc[]的方式较慢。
17、ES的删除操作不是真正的删除,那通过什么方式可以获取到准确的文档数量?
通过_cat/count API获取集群中所有文档数量,不包含已删除的文档;通过{index}/_stats API获取索引中的文档数量,结果中docs.count值为除了标记删除文档之外的总的文档数,docs.deleted为标记删除的文档数。
18、ES的_search API,当不指定索引时是会向集群中所有的索引发起查询请求吗?
是默认行为,最好通过指定索引名称或者对多个索引设置别名后进行查询,可以减少不必要的开销;5.6版本以后增加了分片预过滤功能,当要查询的分片数量超过128并且查询可能会被重写为MatchNoneQuery时,会进行过滤,过滤掉不需要的shard,_search API的返回结果中的_shards.skipped表示了过滤掉了多少shard。
19、如果使用scroll批量获取查询结果,ES执行该查询时还会使用node query cache或者shard request cache吗?
scroll请求不会用到cache,因为使用cache在查询请求执行过程中会修改search context,会破坏掉scroll的context。
20、如何实现字符串的前后通配符匹配,比如输入bc,想查询出abc, abcd, bcd, 但是不能查询出abdc?
使用query_string查询:
1 | { |
21、使用query_string查询指定的整型字段,查询的值为正数时正常,值为负数时抛异常,如“status:-1”时会报错
需要把负号转义(“status:-1”)或者对负数加引号, 否则会认为负号是一个操作符而解析失败。
22、在kibana中要对long型的字段进行聚合,但是提示不支持
如果索引是按天创建的,并且一个index pattern下包含多个索引,检查下索引的mapping,是否之前的索引中字段类型是否是字符串类型,如果不同索引中该字段的类型不一致,则不能对该字段进行聚合。https://github.com/elastic/kibana/issues/3451
23、通过bulk api向es写数据时,报错如下:
报错:failed to execute bulk item (index) BulkShardRequest …source[n/a, actual length: [4.5kb], max length: 2kb]}], 是字段超过了最大长度2kb的限制吗?
日志中打出的max length不是字段的最大长度的意思,而是超过了2kb就不把具体的doc信息在日志中打出,bulk失败的信息需要查看日志中后面的异常信息,一般是字段解析失败或者是bulk队列满导致的。
24、索引中有一个字符串型的字段,需要在kibana中这个字段求平均值并且展示出来,该怎么实现呢?
参考https://www.elastic.co/guide/en/kibana/current/scripted-fields.html, 使用script fields。
25、filebeat 7.x版本,在配置文件中定义了index名称,为什么写入到es中仍然生成的是filebeat-*之类的索引?
通过配置setup.ilm.enabled: false解决。索引生命周期管理ilm功能默认开启,开启的情况下索引名称只能为filebeat-*, 通过setup.ilm.enabled: false进行关闭;如果要使用自定义的索引名称,同时又需要启用ilm,可以修改filebeat的模板。
26、使用filebeat+es+kibana收集容器中的nginx日志,但是发现kibana中的message是一整段,字段都放在一起了,这个该怎么处理?
两种解决办法:
- nginx日志配置为json格式, filebeat配置文件中指定解析json格式的日志json.keys_under_root: true
- 仍然使用默认的nginx日志格式,在es中自定义ingest pipeline解析每个字段,filebeat配置文件中指定使用定义好的pipeline
27、ES的fielddata和docvalues有什么区别呢?
fielddata是在堆内存的,docvalues是在堆外内存的;docvalues默认对所有not_analyzed字段开启(index时生成),如果要对analyzed字段进行聚合,就要使用fielddata了(使用时把所有的数据全都加载进内存);如果不需要对analyzed字段进行聚合,就可以降低堆内存,Elasticsearch(更快的 GC)和 Lucene(更多的内存用于缓存)的性能越好
28、ES的ik-analyzer分词插件默认会把英文大写字母转换为小写,但是业务查询时是对大小写敏感的,怎么可以做到使用ik-analyzer分词插件的同时禁止把大写字母转换为小写?
可以基于ik_smart分词类型自定义analyzer, 同时配置参数 “enable_lowercase”: false:
1 | { |
29、业务日志按文件大小滚动(最大100MB,滚动后压缩),使用filbeat收集日志时,发现在日志滚动较快的情况下filebeat没有释放掉已经被删除掉的日志文件,导致磁盘使用率较高,这个怎么解决?
可以通过配置close_timeout参数释放掉已经删除文件的文件句柄。
30、使用filebeat 5.6.4收集nginx日志文件(按天滚动,滚动后压缩),发现filebeat data目录下registry文件越来越大,并没有清理掉很早日志文件的state信息,这个怎么解决?
通过配置ignore_older和clean_inactive两个参数,清理掉registry中无用的文件state信息。
31、es集群是yellow,分片完成度不是100%的问题
过多的复本数配置会延长分片完成时间,可以根据业务情况考虑减少复本数,以下仅供参考:
1 | curl -XPUT localhost:9200/.kibana/_settings -H “Content-Type:application/json” -d {“index.number_of_replicas”:0} |