大版本升級(jí)婆廊,從ES 2.1到ES5.5迅细,兩年的數(shù)據(jù),每天15GB淘邻,5個(gè)節(jié)點(diǎn)茵典,前后歷時(shí)一個(gè)月左右。
限制條件:
- 升級(jí)過(guò)程有新的數(shù)據(jù)不斷進(jìn)來(lái)宾舅,不能停止整個(gè)集群统阿,否則會(huì)丟失數(shù)據(jù)。
- 沒(méi)有額外的機(jī)器搭建一個(gè)全新的ES5集群筹我,只有一個(gè)機(jī)器供緩沖使用扶平。
- 一個(gè)臨時(shí)的ES5節(jié)點(diǎn)cpu 8核,內(nèi)存32GB蔬蕊,10T 磁盤蜻直,升級(jí)完成后需要釋放掉這臺(tái)機(jī)器。
- 很多線上的服務(wù)依賴于目前的ES2提供服務(wù)袁串,線上服務(wù)不能中斷概而。
記錄一下整個(gè)流程。
首先是做決定到底是采用全集群方式升級(jí)還是平滑方式升級(jí)囱修。
升級(jí)方案選擇
全集群升級(jí)
1.關(guān)閉shard分配赎瑰,防止關(guān)閉一個(gè)節(jié)點(diǎn)后ES集群誤認(rèn)為node故障,在剩余節(jié)點(diǎn)上執(zhí)行 shard 恢復(fù)破镰,如果數(shù)據(jù)過(guò)多餐曼,可能會(huì)由于產(chǎn)生大量IO造成ES集群掛起。
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "none"
}
}
2.執(zhí)行同步刷新鲜漩, 這樣集群重新啟動(dòng)后shard恢復(fù)更快源譬。
POST _flush/synced
3.關(guān)閉集群中所有的ES進(jìn)程。
4.安裝ES5孕似,并且修改配置文件踩娘,配置好data路徑。不要直接指向2.x的路徑喉祭,否則一旦升級(jí)失敗养渴,老數(shù)據(jù)無(wú)法恢復(fù)。
5.配置好路徑后將2.x的data目錄copy到新的路徑下泛烙。
6.啟動(dòng)ES5 集群理卑,等待集群狀態(tài)變?yōu)間reen即可
優(yōu)點(diǎn)
簡(jiǎn)單,速度快蔽氨,一步到位
缺點(diǎn)
- 由于ES2.x到ES5.x內(nèi)部結(jié)構(gòu)變化較大藐唠,升級(jí)過(guò)程不可控帆疟,中間可能會(huì)有大坑或者升級(jí)失敗
- 目前ES存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)有需要改進(jìn)的部分(比如某些字段類型,analyzed等)宇立,這樣升級(jí)后還是原來(lái)的結(jié)構(gòu)踪宠,后續(xù)可能還需要對(duì)數(shù)據(jù)進(jìn)行reindex。
Reindex 平滑升級(jí)
這種升級(jí)方式其實(shí)就是對(duì)所有的數(shù)據(jù)做一次重新處理然后自己通過(guò)http接口重新寫入到新的 ES5緩沖節(jié)點(diǎn)泄伪,然后再將原來(lái)的ES2的節(jié)點(diǎn)逐臺(tái)加入的新的集群,之前的數(shù)據(jù)和配置都清空匿级。
程序大致流程
ES2 -> scanner -> redis -> reindex -> ES5
引入Redis作為中間緩沖的考慮:
- 數(shù)據(jù)量巨大蟋滴,索引過(guò)程很難保證一次成功,基于scroll方式取數(shù)據(jù)無(wú)法保證順序痘绎,所以一旦中途失敗無(wú)法判斷offset津函,為了不丟不重復(fù),只能從頭再來(lái)
- 需要對(duì)每一個(gè)doc進(jìn)行特有字段的部分處理孤页, Redis中緩存的是處理后的doc
- ES的查詢速度和索引速度不一致尔苦,從ES2讀取數(shù)據(jù)經(jīng)過(guò)處理后寫入ES5整個(gè)流水線耗時(shí)太長(zhǎng),容易網(wǎng)絡(luò)超時(shí)失敗
升級(jí)方案踩坑記
經(jīng)過(guò)內(nèi)部討論決定采用平滑升級(jí)的方式行施。
使用python將每天的數(shù)據(jù)從ES2->ES5允坚,每天大概2000萬(wàn)條數(shù)據(jù),使用官方的elasticsearch python庫(kù)每次到幾百萬(wàn)數(shù)據(jù)的時(shí)候就會(huì)出現(xiàn)連接超時(shí)蛾号,由于沒(méi)有offset機(jī)制稠项,所以只能刪除從頭再來(lái)。后來(lái)基于requests庫(kù)自己封裝scroll API來(lái)進(jìn)行reindex鲜结,有時(shí)發(fā)現(xiàn)1000多萬(wàn)的時(shí)候scroll API就返回沒(méi)有誰(shuí)了展运,后來(lái)經(jīng)過(guò)調(diào)試發(fā)現(xiàn)不能只是簡(jiǎn)單的根據(jù)hits的條數(shù)是否為0來(lái)判斷數(shù)據(jù)是否全都讀取完畢。這里官方文檔中并沒(méi)有提及精刷,最終添加了好幾個(gè)判斷條件和錯(cuò)誤處理拗胜,終于可以完整的讀完所有數(shù)據(jù),一條不差怒允。
中間引入了redis作為緩存埂软,防止reindex程序中間掛了,從頭再來(lái)纫事。es2->redis->es5仰美,由于讀的速度遠(yuǎn)遠(yuǎn)大于寫的速度,而且只有一臺(tái)es5節(jié)點(diǎn)儿礼,所以需要開(kāi)多個(gè)進(jìn)程往es5中寫咖杂。突然有一天發(fā)現(xiàn)es5掛掉了,查找原因蚊夫,發(fā)現(xiàn)redis的內(nèi)存已經(jīng)占滿了所有機(jī)器的內(nèi)存诉字,操作系統(tǒng)自動(dòng)殺掉了es5節(jié)點(diǎn)。于是加入流控機(jī)制,一旦redis中的數(shù)據(jù)超過(guò)限制壤圃,那么讀取程序需要掛起陵霉。
數(shù)據(jù)全都寫入到ES5的臨時(shí)節(jié)點(diǎn)后,開(kāi)始一臺(tái)一臺(tái)的升級(jí)ES2伍绳。之前在ES2的升級(jí)過(guò)程中通過(guò)yum安裝ES時(shí)發(fā)現(xiàn)ES已經(jīng)從5.5.1升級(jí)到了5.5.2踊挠,ES對(duì)于版本的控制非常嚴(yán)格,雖然可以同時(shí)正常的查詢工作冲杀,但是之前的數(shù)據(jù)都是5.5.1版本效床,無(wú)法在5.5.2版本的node上寫入數(shù)據(jù),沒(méi)辦法权谁,只能先升級(jí)原先的es5tmp節(jié)點(diǎn)到5.5.2版本剩檀,由于是小版本升級(jí),直接yum update然后重新啟動(dòng)節(jié)點(diǎn)即可旺芽。
數(shù)據(jù)的存儲(chǔ)之前并沒(méi)有采用LVM管理沪猴,所以添加一塊磁盤,需要修改ES的配置文件采章,然后重新啟動(dòng)機(jī)器运嗜,這次升級(jí)順便將所有的ES的數(shù)據(jù)盤配置為L(zhǎng)VM方式。由于之前已經(jīng)有一部分?jǐn)?shù)據(jù)寫入到了新加入的非LVM節(jié)點(diǎn)上悯舟,所以需要將其中的shards再寫回到es5tmp臨時(shí)節(jié)點(diǎn)洗出,查看文檔,發(fā)現(xiàn)使用cluster.routing.allocation.exclude._ip設(shè)置可以達(dá)到要求图谷,設(shè)置完成后分片會(huì)自動(dòng)寫回到臨時(shí)節(jié)點(diǎn)上翩活。LVM磁盤配置好后,重新加入集群便贵,使用cluster.routing.allocation.include._ip設(shè)置后發(fā)現(xiàn)并沒(méi)有作用菠镇,經(jīng)過(guò)嘗試發(fā)現(xiàn),必須cluster.routing.allocation.exclude._ip設(shè)置為空字符串承璃,同時(shí)cluster.routing.allocation.include._ip也必須設(shè)置為空利耍。等待所有的ES2的節(jié)點(diǎn)都加入集群后,將臨時(shí)節(jié)點(diǎn)的ip設(shè)置到exclude中盔粹,這樣所有的shards和副本都會(huì)自動(dòng)轉(zhuǎn)移到新的節(jié)點(diǎn)上隘梨。
由于內(nèi)存和資源限制,整個(gè)升級(jí)過(guò)程是每次打開(kāi)一個(gè)月的index舷嗡,所有的主分片都從臨時(shí)節(jié)點(diǎn)轉(zhuǎn)移后轴猎,再設(shè)置replica個(gè)數(shù)為1,等所有副本都完成后进萄,close這個(gè)月的所有index捻脖,然后開(kāi)始下一個(gè)月锐峭。這樣整個(gè)過(guò)程只保留了當(dāng)前最新的一個(gè)月的數(shù)據(jù)(供在線服務(wù)使用)和正在進(jìn)行中的那個(gè)月的數(shù)據(jù),整個(gè)集群壓力較小可婶。
升級(jí)完成后安裝Kibana沿癞,發(fā)現(xiàn)ES已經(jīng)升級(jí)到5.6了,不想折騰ES的各個(gè)節(jié)點(diǎn)升級(jí)到5.6矛渴,所以通過(guò)yum安裝5.5.2的Kibana椎扬。
升級(jí)完成后http query的接口已經(jīng)完全變了,所有之前依賴es2的查詢接口都需要重寫具温。
所以的kibana和ES節(jié)點(diǎn)都監(jiān)聽(tīng)內(nèi)網(wǎng)地址蚕涤,不安裝x-pack,通過(guò)部署一個(gè)nginx的代理和簡(jiǎn)單的用戶名密碼認(rèn)證來(lái)做簡(jiǎn)單的安全驗(yàn)證桂躏。使用cerebro(之前的kopf)來(lái)對(duì)集群的狀態(tài)進(jìn)行簡(jiǎn)單的監(jiān)控和更新配置钻趋。
中間還包括了logstash配置更新川陆,kibana配置更新,ES->Hadoop的代碼更新不再一一細(xì)說(shuō)。
知識(shí)點(diǎn)總結(jié)
整個(gè)過(guò)程涉及到的知識(shí)點(diǎn)如下:
- python requests庫(kù)使用严蓖。
- es scroll API使用龙填。
- yum 安裝特定版本軟件包以及配置清華源。
- 阿里云系統(tǒng)盤鏡像創(chuàng)建以及替換部署尸曼。
- lvm管理多個(gè)磁盤们何。
- systemctl 使用以及service配置文件。
- es index template 配置控轿。
- nginx basic auth反向代理配置冤竹。
- es hadoop map reduce API使用。
- python redis 使用茬射。
- Logstash鹦蠕,ES,Kibana 安裝部署以及配置在抛。