ElasticSearch不停機(jī)重建索引延伸思考及優(yōu)化詳解
前言
距離我第一次上手ES過去了一年半多了吧,當(dāng)時(shí)我是從零開始花了大半年時(shí)間搭建了一整套Filebeat+Kafka+數(shù)據(jù)處理服務(wù)+Elasticsearch+Kibana+Skywalking日志收集系統(tǒng)。感覺還是很刺激的,畢竟同時(shí)去深度學(xué)習(xí)和運(yùn)用多個(gè)剛上手的中間件對(duì)我來說是個(gè)極大的磨練。日志收集系統(tǒng)的數(shù)據(jù)處理服務(wù)切換到了Flink,這個(gè)后面總結(jié)完畢后我會(huì)出一篇單獨(dú)的文章講講Flink和改造過程。但是始終有一個(gè)問題困擾著我,團(tuán)隊(duì)內(nèi)部對(duì)于ES的應(yīng)用尚淺,僅僅用來做日志收集,導(dǎo)致我對(duì)ES的認(rèn)識(shí)一直不算深刻,所以我之前也沒有寫一篇優(yōu)秀的文章來闡述我的認(rèn)知。當(dāng)然現(xiàn)在我依舊算個(gè)小白,但是因?yàn)橐粌蓚€(gè)需求重新深刻認(rèn)識(shí)了ES,算是一段不錯(cuò)的經(jīng)歷,因此分享給大家,有問題的話請(qǐng)各位大佬指正。
需求
同事提給我的,說是需要對(duì)過去半年時(shí)間做一個(gè)系統(tǒng)應(yīng)用的用戶使用情況統(tǒng)計(jì),很急。具體是需要按照系統(tǒng)分組統(tǒng)計(jì)每個(gè)用戶的使用情況,很好,之前完全沒有單獨(dú)設(shè)計(jì)過相關(guān)的統(tǒng)計(jì)入口,因此只能根據(jù)日志內(nèi)容硬寫查詢語句了。因?yàn)樾枨蟊容^麻煩,所以注定是個(gè)復(fù)雜聚合查詢,不巧的是我對(duì)于ES的查詢API有點(diǎn)忘了,只能現(xiàn)學(xué)現(xiàn)賣了。為啥不熟呢?我自己總結(jié)的原因一是日志場(chǎng)景單一,JavaAPI只需要布爾查詢拼條件即可,不會(huì)很復(fù)雜,后面改成Kibana后索引模式用上就不存在什么API調(diào)用了。原因二是由于工作繁忙,沒有別的技術(shù)場(chǎng)景,因此沒有太關(guān)注ES的API部分,重點(diǎn)都是在性能優(yōu)化和日志收集系統(tǒng)的完善上面。
除了上面的復(fù)雜查詢讓我稍微感到難度之外,在聚合查詢的時(shí)候還發(fā)現(xiàn)了歷史遺留的問題,新索引優(yōu)化了映射并沒有修改老索引,因此新老索引映射是有一點(diǎn)區(qū)別的,需要重建索引。重建索引自然要上真實(shí)場(chǎng)景,不停機(jī)重建索引。
查詢本體
對(duì)應(yīng)查詢語句和執(zhí)行結(jié)果如上圖,簡(jiǎn)要提幾點(diǎn)限制打開的方法和一些優(yōu)化的手段。
查詢限制
1.查詢總數(shù)默認(rèn)限制10000條
查詢時(shí)帶上"track_total_hits": true,打開限制,返回真實(shí)條數(shù)
2.聚合查詢時(shí)使用term,默認(rèn)限制10條
聚合查詢參數(shù)中加上"size": 50,配置展示最多50條
聚合查詢優(yōu)化
聚合查詢?yōu)榱吮M量返回少的數(shù)據(jù)量,提升查詢效率,通常設(shè)置size為0,體現(xiàn)為查詢結(jié)果中hits不返回具體文檔數(shù)據(jù)。
遇到問題
1.text類型不支持聚合
報(bào)錯(cuò)內(nèi)容:
Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [userId] in order to load field data by uninverting the inverted index. Note that this can use significant memory(文本字段未針對(duì)需要每個(gè)文檔字段數(shù)據(jù)的操作(如聚合和排序)進(jìn)行優(yōu)化,因此默認(rèn)情況下禁用這些操作。請(qǐng)改用關(guān)鍵字字段?;蛘撸?[userId] 上設(shè)置 fielddata=true,以便通過反轉(zhuǎn)倒排索引來加載字段數(shù)據(jù)。請(qǐng)注意,這可能會(huì)占用大量?jī)?nèi)存)
解決方案:
text類型默認(rèn)不支持聚合和排序,因此要么修改mapping增加屬性fielddata=true,或者直接修改字段類型為keyword
2.分詞查詢時(shí)不知道寫哪些詞
查詢文檔分詞結(jié)果--索引=log-zero-pro-202302-alias1,id=1xKdCoYBeajfMMIRdyre,字段=msg
GET /log-zero-pro-202302-alias1/_doc/1xKdCoYBeajfMMIRdyre/_termvectors?fields=msg
我想這是大多數(shù)新手遇到的問題,配了分詞后,我就隨便亂輸發(fā)現(xiàn)匹配不了,開始懵逼,疑惑這分詞怎么沒有效果。但是我們把分詞當(dāng)作一個(gè)模糊查詢?nèi)ビ昧耍瑑烧哌€是有一定區(qū)別的,特別是粗分詞的時(shí)候,不太熟練的情況下,還是先查一下分成啥樣再去查詢比較好。
不停機(jī)重建索引
為啥要重建索引呢?因?yàn)樗饕齽?chuàng)建之后是不允許修改映射的,如果修改只能重建。不停機(jī)重建索引的步驟還是比較簡(jiǎn)單,就三步。
新建索引
新建索引正常建就行,因?yàn)橹亟ㄋ饕玫搅藃eIndex這個(gè)API,內(nèi)部是由scroll+bulk實(shí)現(xiàn),本質(zhì)上就是先查詢?cè)倥坎迦搿R虼丝梢宰鲆恍懭雰?yōu)化,副本數(shù)可以先設(shè)置為0,刷新間隔禁用,落盤機(jī)制調(diào)整異步和延遲。
PUT /log-zero-pro-202206_re/_settings { "index" : { "number_of_replicas" : 0, "refresh_interval": "-1" } }
切換別名指向新索引
ES的索引設(shè)計(jì)時(shí)最好提前加上一個(gè)別名,用別名去管理索引,它就像一層代理,讓我們不用在意底層索引,可以隨時(shí)切換。我們建立一個(gè)新的索引后,將別名指向新的索引,這樣新數(shù)據(jù)就會(huì)灌到新索引中,避免老索引在遷移中仍有數(shù)據(jù)進(jìn)入,導(dǎo)致數(shù)據(jù)遷移不完整,需要二次遷移。
POST /_aliases { "actions" : [ { "remove" : { "index" : "log-zero-pro-202207-alias1", "alias" : "log-zero-pro-202207" } }, { "add" : { "index" : "log-zero-pro-202207_re", "alias" : "log-zero-pro-202207" } } ] }
遷移數(shù)據(jù)
選擇ES自帶的reIndex進(jìn)行遷移,這里盡量?jī)?yōu)化一下
- slices=auto&refresh,因?yàn)閮?nèi)部使用scroll查詢,因此可以選擇分片查詢提升效率,auto意思是自動(dòng)改成索引分片數(shù)
- wait_for_completion=false,為了避免遷移時(shí)間過長(zhǎng)超時(shí),所以選擇異步執(zhí)行
- size: 5000,也是提升單次查詢數(shù)據(jù),默認(rèn)1000條,根據(jù)實(shí)際插入效率動(dòng)態(tài)調(diào)整
POST _reindex?slices=auto&refresh&wait_for_completion=false { "conflicts": "proceed", "source": { "index": "log-zero-pro-202207-alias1", "size": 5000 }, "dest": { "index": "log-zero-pro-202207_re" } } 結(jié)果 { "task" : "iDnr1JBPRjyPVqwl2TcqqA:889565588" }
查詢異步遷移任務(wù)詳情
有兩個(gè)API可以調(diào)用,上面是查詢所有reindex任務(wù),下面是查詢某個(gè)任務(wù)的詳情,一般用下面的查看任務(wù)是否完成
GET _tasks?detailed=true&actions=*reindex GET /_tasks/iDnr1JBPRjyPVqwl2TcqqA:889578807
調(diào)整正常索引配置
把之前的副本和刷新禁用重新打開
PUT /log-zero-pro-202206_re/_settings { "index" : { "number_of_replicas" : 1, "refresh_interval": "1s" } }
莫名想到了MySQL擴(kuò)容,就順道來聊聊,擴(kuò)容和重建索引不是一回事哈,不能直接對(duì)比。
MySQL擴(kuò)容
當(dāng)前已存在n臺(tái)數(shù)據(jù)庫,并且通過id取模。一般是m*n擴(kuò)容m倍,這樣做元素遷移時(shí)比較方便,當(dāng)然更建議一開始給足數(shù)據(jù)庫,盡量不要擴(kuò)容,增加操作風(fēng)險(xiǎn)。擴(kuò)容通常分為停機(jī)和不停機(jī)兩種,各有優(yōu)劣。
停機(jī)擴(kuò)容
最簡(jiǎn)單的方案,找個(gè)沒人的深夜停機(jī),寫個(gè)程序讀取老的n臺(tái)數(shù)據(jù)庫,按照id重新取模輸入到新的m*n臺(tái)數(shù)據(jù)庫上,修改應(yīng)用配置再重新上線。
回滾也方便,發(fā)現(xiàn)出問題,把配置修改為之前的,繼續(xù)用老數(shù)據(jù)庫,啥時(shí)候新的弄對(duì)了再遷過去。
優(yōu)點(diǎn)就是簡(jiǎn)單明了,缺點(diǎn)就是費(fèi)人,而且萬一運(yùn)行了一段時(shí)間后發(fā)現(xiàn)搞錯(cuò)了,只能回退到擴(kuò)容前,會(huì)丟失部分?jǐn)?shù)據(jù)。
不停機(jī)擴(kuò)容
這個(gè)就相對(duì)復(fù)雜,假設(shè)現(xiàn)在有兩臺(tái)數(shù)據(jù)庫A和B,選擇兩倍擴(kuò)容,也就是增加到四臺(tái)ABCD。
- A和C,B和D分別配置雙主同步,等待數(shù)據(jù)同步完成。
- 修改應(yīng)用路由配置同時(shí)寫入ABCD四臺(tái)數(shù)據(jù)庫,取模規(guī)則變成四等分
- 刪除雙主同步,同時(shí)刪除四臺(tái)數(shù)據(jù)庫里的冗余數(shù)據(jù)(不屬于當(dāng)前取模規(guī)則的數(shù)據(jù))
優(yōu)點(diǎn)很多啊,最重要的就是不停機(jī),而且占用資源也少,原來兩臺(tái)數(shù)據(jù)庫也用上了?;貪L也簡(jiǎn)單,只要不刪除冗余數(shù)據(jù),隨時(shí)都能切回來,直接修改取模規(guī)則即可。缺點(diǎn)就是比較復(fù)雜,雙主同步、雙寫,而且老數(shù)據(jù)庫較大的時(shí)候,擴(kuò)容相當(dāng)費(fèi)時(shí)費(fèi)力。
隨便聊聊
其實(shí)在做ES不停機(jī)重建索引的時(shí)候,我一開始是沒想到這么簡(jiǎn)單的,居然幾條命令就搞定了,WTF。但是事實(shí)就是這樣,分布式架構(gòu)面對(duì)單體架構(gòu)的優(yōu)勢(shì)是碾壓式的,這也是我最近在看分布式數(shù)據(jù)庫TiDB的原因,遲早會(huì)遷移過去的。啥也不說,運(yùn)維成本相對(duì)就低了,幾條命令就完成了,細(xì)節(jié)不用管還更有保障,排除了單體架構(gòu)時(shí)人為原因,這可太爽了。
最后
最近有個(gè)問題難住我了,flink往es寫數(shù)據(jù)放在服務(wù)器上跑老是報(bào)錯(cuò),我這菜的還解決不了,少年痛苦祈禱中?;氐紼S,本次也算是再次加深了我對(duì)ES的認(rèn)識(shí),還可以,有所收獲。下一篇絕對(duì)是口語化系列了,這篇屬于臨時(shí)小插曲,大約2個(gè)晚上寫完,還算不錯(cuò)。鴨梨很大,日子難過啊,啊啊啊啊啊,我一定要讓這痛苦壓抑的世界綻放幸??鞓分ā?/p>
以上就是ElasticSearch不停機(jī)重建索引延伸思考及優(yōu)化詳解的詳細(xì)內(nèi)容,更多關(guān)于ElasticSearch不停機(jī)重建索引的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MyBatis使用注解開發(fā)實(shí)現(xiàn)過程詳解
這篇文章主要介紹了MyBatis使用注解開發(fā)實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03java報(bào)錯(cuò):找不到或無法加載主類的解決方法簡(jiǎn)單粗暴
本文主要介紹了java報(bào)錯(cuò):找不到或無法加載主類的解決方法簡(jiǎn)單粗暴,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01mybatis中批量更新多個(gè)字段的2種實(shí)現(xiàn)方法
當(dāng)我們使用mybatis的時(shí)候,可能經(jīng)常會(huì)碰到一批數(shù)據(jù)的批量更新問題,因?yàn)槿绻粭l數(shù)據(jù)一更新,那每一條數(shù)據(jù)就需要涉及到一次數(shù)據(jù)庫的操作,本文主要介紹了mybatis中批量更新多個(gè)字段的2種實(shí)現(xiàn)方法,感興趣的可以了解一下2023-09-09java文件操作練習(xí)代碼 讀取某個(gè)盤符下的文件
這篇文章主要介紹了java讀取某個(gè)盤符下的文件示例,代碼中要求的是絕對(duì)路徑,編譯過程中要注意絕對(duì)路徑問題和異常的抓取2014-01-01Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署
今天小編就為大家分享一篇關(guān)于Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02