題記
馬雲演講中曾經提到:很多時候少聽成功專家的話。所有的創業者多花點時間學習別人是怎麼失敗的,因為成功的原因有千千萬萬,失敗的原因就一兩個點。
創業需要關注別人的失敗,而開發實戰,別人的錯誤經驗、別人的問題也非常有價值。
開發最懊悔的事莫過於:自己費盡腦汁、花費了很長時間解決了問題,原來別人在社群或者別的地方早已經給出了更優化的方案。
開發最最懊悔的事莫過於:別人已經給出了方案,但是我們仍然在黑暗中苦逼的摸索。
因此,我從2018年4月——至今,每月都會梳理出了Elasticsearch中文社群的精華乾貨——簡稱:Elastic錯題本, 問題大多來自Medcl、wood大叔等大牛的精彩回覆,結合實戰嚴選的核心問題。
放在了GitHub上。
GitHub地址:github.com/laoyang360/…
目的:提前加深認知,少重複走別人的彎路!
1、kibana根據歷史資料預測未來資料
Elastic 的機器學習功能剛好就能做
2、es查詢問題。
另外你要注意一下 Lucene 的語法規則:
lucene.apache.org/core/2_9_4/…
a+(D|d) 這裡 a 是可選,括號內的必要的。如果要 a 是必要條件,加號要放前面。如果是兩個關鍵字直接是任意滿足的關係,一般是用||。另外注意括號的全形和半形。
如:+a +(c||d)
3、【重要】關於elasticsearch中filter的粒度的疑問
推薦閱讀:elasticsearch.cn/question/66…
filter是單個快取的,不過對於term 型別的filter是否快取要看版本。
因為term filter開銷很小,所以從5.1.1之後不再做快取。
filter上下文中的查詢是獨立被cache的,所以按照你給的例子,應該是三個。
相關的資料
在這裡: www.elastic.co/guide/cn/el…
只不過從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,能看到建立、刪除索引的日誌
低版本地址:www.elastic.co/guide/en/el…
高版本地址;www.elastic.co/guide/en/el…
5、【重要】es gc overhead 報錯
通過scroll方式查詢時,特別注意要設定遊標有效時間不能太久, 例如scroll=30min,過期時間越長對應資料儲存在ES記憶體中就越久,ES記憶體越大。
srcoll查詢完後要及時呼叫clearScroll(scrollId)
來清理對應遊標資料。
6、es5.5版本,當文件欄位是1100多個的時候,報異常
Limit of total fields [1000] in index [nfvoemspm] has been exceeded
修改settings
{
"index.mapping.total_fields.limit": 2000
}
複製程式碼
話說真的需要這麼多欄位放在一起嗎,能不能從設計上優化一下。
7、Elasticsearch技術棧選型推薦
方案1:SpringBoot+Thymeleaf+RestHighLevelClient
方案2:SpringBoot 簡單的語句用String.format複雜語句用Freemarker 然後用RestHighLevelClient甚至直接自己包裝一個HttpClient 結合ES自己的template使用
git封裝參考:github.com/godlockin/s…
8、【警惕】資料丟失啦
問題:今天發現ES 伺服器上所有機器的所有資料都消失了。 沒有進行過任何操作。 求教有什麼原因可以導致這種結果.不管是正常的非正常的,能給個指教就是好事。
運維同學抓破頭也沒找到問題出在哪
【根因】:運維人員通過head外掛把相關index刪除了,而且是憤世嫉俗一般的全部刪掉。 現在我更關心如何做安全策略
推薦閱讀:blog.csdn.net/laoyang360/… 你的Elasticsearch在裸奔嗎?
【注意事項】 1.是否暴露了公網訪問 2.是否有團隊/公司裡其他人知道地址 3.檢查一下資料匯入的指令碼有沒有重啟、oom、做過濾… 4.差不差錢,不差錢的買個xpack做安全策略,差錢就內網隔離部署+黑白名單,亡羊補牢猶未晚矣 5.rerun一下資料匯入指令碼進行資料修復 6.找到原因了之後不管多妖或者多蠢,都記得回來這裡發個帖子,詳細的聊聊整個issue的前因後果 7、先看一下資料路徑裡面的資料是否正常; 8、看一下是否開啟了萬用字元資料刪除; 9、看一下 ES 日誌,從中找是否叢集啟停過之類的操作 10、確認下磁碟是不是滿了,導致的異常或者磁碟路徑的問題
9、有關es forceMerge問題
通過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", ...]
複製程式碼
具體請參考: www.elastic.co/guide/en/be…
11、有沒有 ngram 和 wildcard 折中方案?
想支援英文的部分搜尋,比如 good,搜尋oo也可以匹配出來。這就需要 ngram,但是 ngram 使得 index 佔用空間10X+增大,有點無法接受。wildcard 搜尋效率又實在太低。有什麼折中方案麼?
你可以試試字首搜尋 good 你分詞為 good/ood/od/ 這樣使用字首搜尋就可以實現你需要的效果; 同時設定一下 mapping,可進一步加快搜尋速度
"index_prefixes": {
"min_chars": 1,
"max_chars": 10
}
複製程式碼
12、 logstash吞吐量太低了怎麼優化呢?
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 的數量
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恢復很慢
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哪種效能好一些呢?
因為我們公司業務的原因,我們需要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 字串欄位會預設使用該設定。
推薦閱讀:blog.csdn.net/paditang/ar…
20、單索引大資料量,如何優化?
【問題】單索引當前已經儲存1.5億多文件,3節點5分片1副本,每個分片20G多。有定期刪除老資料,但是預計在刪除老資料前,可能最大儲存文件達到24億多。
當前想到的解決方案: 1、根據預估的最大24億最大文件,對當前資源進行擴容。 但是根據之前的資料計算,應該如何合理分配分片?如何計算需要擴容幾個節點滿足要求? 2、使用rollover根據條件,索引太大後,寫入資料切換至新索引,但是查詢資料還是對全部索引進行查詢。 這樣可能是多索引,每個索引5分片1副本。
現在疑惑是哪種方案更合理?個人傾向於方案2,比較擴容也是需要成本。 但是方案2後續索引增加,分片增加後,每次查詢是設定查詢別名指向所有索引,這樣查詢效能是不是也會持續下降?
【回覆】 這個推薦先在搜尋壓力小的時段對索引進行一次 ForceMerge,這樣會之前已經刪除的文件進行真正刪除操作; 此外,如果搜尋壓力大的化,可以多增加一個副本,這樣副本也可以分擔搜尋的壓力;
如果希望多個索引分擔壓力,可以使用別名,別名
可以指定多個索引的某一個索引是可以寫入資料的;
搜尋的時候是全部索引一起搜尋.
【銘毅回覆】: 針對方案2:結合template+rollover+別名+curator可以解決問題,不存在效能問題。 相反,針對最新資料的索引,反而通過制定日期索引,會縮減檢索樣本空間,反而效率更高。
【進一步推進閱讀】 6.6 版本索引生命管理 elasticsearch.cn/article/635…
21、推薦閱讀新文章
自研基於StanfordNLP的ES分詞外掛 elasticsearch.cn/article/634…
銘毅天下——Elasticsearch基礎、進階、實戰第一公眾號