嚴選 | Elasticsearch中文社區201901錯題本

題記

馬雲演講中曾經提到:很多時候少聽成功專家的話。所有的創業者多花點時間學習別人是怎麼失敗的,因爲成功的原因有千千萬萬,失敗的原因就一兩個點

創業需要關注別人的失敗,而開發實戰,別人的錯誤經驗、別人的問題也非常有價值。

開發最懊悔的事莫過於:自己費盡腦汁、花費了很長時間解決了問題,原來別人在社區或者別的地方早已經給出了更優化的方案。

開發最最懊悔的事莫過於:別人已經給出了方案,但是我們仍然在黑暗中苦逼的摸索。

因此,我從2018年4月——至今,每月都會梳理出了Elasticsearch中文社區的精華乾貨——簡稱:Elastic錯題本
問題大多來自Medcl、wood大叔等大牛的精彩回覆,結合實戰嚴選的核心問題。

放在了GitHub上。

GitHub地址:https://github.com/laoyang360/deep_elasticsearch/tree/master/es_accumulate

目的:提前加深認知,少重複走別人的彎路!

1、kibana根據歷史數據預測未來數據

Elastic 的機器學習功能剛好就能做

https://www.elastic.co/products/stack/machine-learning

2、es查詢問題。

另外你要注意一下 Lucene 的語法規則:

https://lucene.apache.org/core/2_9_4/queryparsersyntax.html

a+(D|d) 這裏 a 是可選,括號內的必要的。如果要 a 是必要條件,加號要放前面。如果是兩個關鍵字直接是任意滿足的關係,一般是用||。另外注意括號的全角和半角。

如:+a +(c||d)

3、【重要】關於elasticsearch中filter的粒度的疑問

推薦閱讀:https://elasticsearch.cn/question/6667

filter是單個緩存的,不過對於term 類型的filter是否緩存要看版本。
因爲term filter開銷很小,所以從5.1.1之後不再做緩存。

filter上下文中的查詢是獨立被cache的,所以按照你給的例子,應該是三個。
相關的資料在這裏: https://www.elastic.co/guide/cn/elasticsearch/guide/current/filter-caching.html#_獨立的過濾器緩存

只不過從5.1.1版本以後開始,term query不會被cache了。
其他類型的query,比方說range query,各種geo的query依然會被cache起來。 這點只有在5.1.1的release notes有提及。

4、ES2.3版本,delete一個索引,master日誌並沒有記錄相關delete操作?

【原因】

PUT _cluster/settings
{
  "persistent": {
    "logger.cluster.service": "DEBUG"
  }
}

打開cluster.service的debug,能看到創建、刪除索引的日誌

低版本地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/logging.html

高版本地址;https://www.elastic.co/guide/en/elasticsearch/reference/6.6/logging.html

5、【重要】es gc overhead 報錯

通過scroll方式查詢時,特別注意要設置遊標有效時間不能太久,
例如scroll=30min,過期時間越長對應數據保存在ES內存中就越久,ES內存越大。

srcoll查詢完後要及時調用clearScroll(scrollId)來清理對應遊標數據。

https://elasticsearch.cn/question/6578

6、es5.5版本,當文檔字段是1100多個的時候,報異常

Limit of total fields [1000] in index [nfvoemspm] has been exceeded

修改settings

{
"index.mapping.total_fields.limit": 2000
}

話說真的需要這麼多字段放在一起嗎,能不能從設計上優化一下。

7、Elasticsearch技術棧選型推薦

https://elasticsearch.cn/question/6676

方案1:SpringBoot+Thymeleaf+RestHighLevelClient

方案2:SpringBoot
簡單的語句用String.format複雜語句用Freemarker
然後用RestHighLevelClient甚至直接自己包裝一個HttpClient
結合ES自己的template使用

git封裝參考:https://github.com/godlockin/searchHandler

8、【警惕】數據丟失啦

https://elasticsearch.cn/question/6650

問題:今天發現ES 服務器上所有機器的所有數據都消失了。 沒有進行過任何操作。
求教有什麼原因可以導致這種結果.不管是正常的非正常的,能給個指教就是好事。

運維同學抓破頭也沒找到問題出在哪

【根因】:運維人員通過head插件把相關index刪除了,而且是憤世嫉俗一般的全部刪掉。 現在我更關心如何做安全策略

推薦閱讀:https://blog.csdn.net/laoyang360/article/details/86347480 你的Elasticsearch在裸奔嗎?

【注意事項】
1.是否暴露了公網訪問
2.是否有團隊/公司裏其他人知道地址
3.檢查一下數據導入的腳本有沒有重啓、oom、做過濾…
4.差不差錢,不差錢的買個xpack做安全策略,差錢就內網隔離部署+黑白名單,亡羊補牢猶未晚矣
5.rerun一下數據導入腳本進行數據修復
6.找到原因了之後不管多妖或者多蠢,都記得回來這裏發個帖子,詳細的聊聊整個issue的前因後果
7、先看一下數據路徑裏面的數據是否正常;
8、看一下是否開啓了通配符數據刪除;
9、看一下 ES 日誌,從中找是否集羣啓停過之類的操作
10、確認下磁盤是不是滿了,導致的異常或者磁盤路徑的問題

9、有關es forceMerge問題

https://elasticsearch.cn/question/6563

通過Kibana觀察到 每次強制給某個索引合併段時 都會發現該索引的所佔空間會跟隨段合併暴漲一倍;

現在問題是這樣的;磁盤空間所剩的空間 不足以撐起某個要合併段的索引的體積的兩倍大小
那麼這個索引是不是就不能合併了 如果仍執行強制合併段 會發生什麼?

回覆:es的合併,是將要合併的segment讀取出來,再寫入到新的segment,然後刪除老的segment,所以,消耗大量的資源和磁盤空間。
你這樣的情況,建議加大磁盤,或者限制索引合併的線程數量,減小每次合併的segment數量。

10、beats如何通過配置刪除host字段

最近在做日誌採集,發現filebeat和winlogbeat採集日誌的時候,會有host這個字段,但是是個object字段,es裏日誌索引host是text類型,想在agent裏直接通過參數把host字段,可以做到麼?看了下配置,好像沒有找到

你可以通過添加 processors 實現字段過濾的功能,例如

processors:
 - drop_fields:
     when:
        condition
     fields: ["field1", "field2", ...]

具體請參考:
https://www.elastic.co/guide/en/beats/filebeat/current/defining-processors.html

11、有沒有 ngram 和 wildcard 折中方案?

https://elasticsearch.cn/question/6733

想支持英文的部分搜索,比如 good,搜索oo也可以匹配出來。這就需要 ngram,但是 ngram 使得 index 佔用空間10X+增大,有點無法接受。wildcard 搜索效率又實在太低。有什麼折中方案麼?

你可以試試前綴搜索
good 你分詞爲 good/ood/od/
這樣使用前綴搜索就可以實現你需要的效果;
同時設置一下 mapping,可進一步加快搜索速度

"index_prefixes": {
    "min_chars": 1,
    "max_chars": 10
  }

12、 logstash吞吐量太低了怎麼優化呢?

https://elasticsearch.cn/question/6739

Logstash 性能調優主要參數

pipeline.workers:

設置啓動多少個線程執行 fliter 和 output;
當 input 的內容出現堆積而 CPU 使用率還比較充足時,可以考慮增加該參數的大小;

pipeline.batch.size:

設置單個工作線程在執行過濾器和輸出之前收集的最大事件數,較大的批量大小通常更高效,但會增加內存開銷。輸出插件會將每個批處理作爲一個輸出單元。;

例如,ES 輸出會爲收到的每個批次發出批量請求;調整 pipeline.batch.size 可調整發送到 ES 的批量請求(Bulk)的大小;

pipeline.batch.delay:

設置 Logstash 管道的延遲時間, 管道批處理延遲是 Logstash 在當前管道工作線程中接收事件後等待新消息的最長時間(以毫秒爲單位);

簡單來說,當 pipeline.batch.size 不滿足時,會等待 pipeline.batch.delay 設置的時間,超時後便開始執行 filter 和 output 操作。

請根據具體情況,調整 batch.size 或者 works 的數量

https://elasticsearch.cn/question/6739

13、請教一個多索引字段比對查詢寫法的問題

想要實現的功能例子如下:

有2個索引: company person
裏面都包含goods和price字段
需要查詢出來company和persion中當goods字段的值一樣時price字段的值不一樣的數據,目前沒有頭緒,請問該怎樣寫呢。

對 goods 字段進行 termsAgg,然後設置其子聚合爲對 _index 的 termsAgg 子聚合,並設置 min_doc_count 爲 2;
最後設置 _index 的子聚合爲 topHits,這樣就可以找到你需要的數據。

{
	"size": 0,
	"query": {
		"match_all": {
			"boost": 1.0
		}
	},
	"aggregations": {
		"goods": {
			"terms": {
				"field": "goods",
				"size": 10000,
				"min_doc_count": 1,
				"shard_min_doc_count": 0,
				"show_term_doc_count_error": false,
				"order": [{
					"_count": "desc"
				}, {
					"_key": "asc"
				}],
				"collect_mode": "breadth_first"
			},
			"aggregations": {
				"index": {
					"terms": {
						"field": "_index",
						"size": 10,
						"min_doc_count": 2,
						"shard_min_doc_count": 0,
						"show_term_doc_count_error": false,
						"order": [{
							"_count": "desc"
						}, {
							"_key": "asc"
						}]
					},
					"aggregations": {
						"top": {
							"top_hits": {
								"from": 0,
								"size": 100,
								"version": false,
								"explain": false
							}
						}
					}
				}
			}
		}
	}
}

14、search_after的SearchAfterBuilder使用範例:

首先要理解 search_after 這個功能;
例如你現在需要安裝 id 和 time 進行排序;
你獲取了第一頁的結果後,現在需要獲取第二頁內容
你需要使用第一頁最後一條的 id 和 time,作爲 search_after 的參數chuan傳遞到查詢請求中。

下面是樣例:

SearchAfterBuilder searchAfterBuilder = new SearchAfterBuilder(); 
searchAfterBuilder.setSortValues(new Object[]{"上一頁的ID", "上一頁的時間"});

15、ES數據恢復,從red恢復到yellow速度很快,從yellow到green恢復很慢

https://elasticsearch.cn/question/6714

red恢復的時候是從本地加載之前的索引文件,沒有從別的地方同步,所以比較快。
yellow恢復成GREEN的時候,很大部分都可能是從主shard同步數據,在6.x之前,通常都會很慢。
6.x之後由於translog機制的變更可能會變快,但這裏還要考慮集羣在恢復的時候可能會自己做reblance,同樣涉及到shard跨節點的搬遷

16、ElasticSearch java api,想要實現一次請求查詢多個類型的同時,每個類型只取固定數量的數據

最近在做系統的搜索功能,在一個索引下建了一些不同的類型。
頁面上的全局搜索功能是要求展示所有類型的數據。

一開始想的是按找類型發起請求,每個類型一次,只取幾條數據。
但是發現查全部類型的時候,雖然單個類型的數據查詢已經解析工作只需要幾十毫秒,但全部執行完就需要一秒左右了。
所以想要實現只請求一次,查詢所有類型的數據,並且每個類型只取固定數量的數據。
請問java api能實現這樣的功能嗎?

【實現】

換一種思路,這麼實現一下,能滿足你的要求。

POST weibo_index/weibo_type,weibo_cm_type/_search
{
  "size": 0,
  "query": {
    "bool": {
      "must": {
        "match": {
          "cont": "北京"
        }
      }
    }
  },
  "aggs": {
    "type_aggs": {
      "terms": {
        "field": "_type",
        "size": 2
      },
      "aggs": {
        "top_hits_aggs": {
          "top_hits": {
            "size": 5,
            "_source": [
              "pt",
              "url"
            ]
          }
        }
      }
    }
  }
}

17、請問copy_to字段 和 mutil_fields哪種性能好一些呢?

https://elasticsearch.cn/question/6698

因爲我們公司業務的原因,我們需要copy_to字段後,然後做全文檢索,那麼我想問一下大家,copy_to字段和直接mutil_field哪種性能更好一些呢?

【參考1】如果只是簡單的全文搜索推薦使用 copy_to,性能更佳;
使用 mutil_field 的優點在於每個字段可用設置不同的權重,這樣更有助於優化搜索結果排名;
此外 copy_to 會比 mutil_field 佔用更多一些的存儲

【參考2】
如果是全文檢索,建議使用copy_to,使用更少的字段,性能會更好一些。如果只是對某個字段單獨去做,就基本上沒有什麼差別。

18、ES重啓後head插件顯示粉紅色

粉紅色是分片relocating階段正常的顏色變化,稍安勿躁,一會就好了。

粉紅色表示分片在重新分配
如果只是臨時重啓機器,推薦配置分配延遲分配策略:

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "5m"
  }
}

【引申可能原因】:
好像硬盤出問題了吧。把副本調整下,再調整回來,讓他重新分配下。1G應該是秒級恢復的。

19、【很有代表性問題】ES匹配度的打分問題

使用ES默認的打分規則(TF-IDF),搜索“葡萄糖”時,搜索結果中“純淨葡萄糖(食用葡萄糖)”比全匹配的“葡萄糖”的得分還要高。因爲在前者中“葡萄糖”出現過兩次。
但是我更想要全匹配的或匹配度更高的,而不關心出現的次數。對我來說,相比“純淨葡萄糖(食用葡萄糖)”,我希望“葡萄糖液”得分更好。
因爲“葡萄糖液”中關鍵字佔了3/4,即使前者出現兩次“葡萄糖”。
我該怎麼修改?是修改TF-IDF配置,或者修改打分算法,還是自定義打分規則?

【回覆】

ES 支持關閉詞頻統計,設置 mapping 即可

PUT /my_index
{
"mappings": {
  "doc": {
    "properties": {
      "text": {
        "type":          "string",
        "index_options": "docs" 
      }
    }
  }
}
}

將參數 index_options 設置爲 docs 可以禁用詞頻統計及詞頻位置,這個映射的字段不會計算詞的出現次數,對於短語或近似查詢也不可用。要求精確查詢的 not_analyzed 字符串字段會默認使用該設置。

推薦閱讀:https://blog.csdn.net/paditang/article/details/79098830

20、單索引大數據量,如何優化?

【問題】單索引當前已經存儲1.5億多文檔,3節點5分片1副本,每個分片20G多。有定期刪除老數據,但是預計在刪除老數據前,可能最大存儲文檔達到24億多。

當前想到的解決方案:
1、根據預估的最大24億最大文檔,對當前資源進行擴容。
但是根據之前的數據計算,應該如何合理分配分片?如何計算需要擴容幾個節點滿足要求?
2、使用rollover根據條件,索引太大後,寫入數據切換至新索引,但是查詢數據還是對全部索引進行查詢。
這樣可能是多索引,每個索引5分片1副本。

現在疑惑是哪種方案更合理?個人傾向於方案2,比較擴容也是需要成本。
但是方案2後續索引增加,分片增加後,每次查詢是設置查詢別名指向所有索引,這樣查詢性能是不是也會持續下降?

【回覆】
這個推薦先在搜索壓力小的時段對索引進行一次 ForceMerge,這樣會之前已經刪除的文檔進行真正刪除操作;
此外,如果搜索壓力大的化,可以多增加一個副本,這樣副本也可以分擔搜索的壓力;

如果希望多個索引分擔壓力,可以使用別名,別名可以指定多個索引的某一個索引是可以寫入數據的;
搜索的時候是全部索引一起搜索.

【銘毅回覆】:
針對方案2:結合template+rollover+別名+curator可以解決問題,不存在性能問題。
相反,針對最新數據的索引,反而通過制定日期索引,會縮減檢索樣本空間,反而效率更高。

【進一步推進閱讀】
6.6 版本索引生命管理
https://elasticsearch.cn/article/6358

21、推薦閱讀新文章

自研基於StanfordNLP的ES分詞插件
https://elasticsearch.cn/article/6341

在這裏插入圖片描述
銘毅天下——Elasticsearch基礎、進階、實戰第一公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章