「Elasticsearch」ES重建索引怎么才能做到數(shù)據(jù)無(wú)縫遷移呢?

背景

眾所周知氓皱,Elasticsearch是?個(gè)實(shí)時(shí)的分布式搜索引擎路召,為?戶提供搜索服務(wù)。當(dāng)我們決定存儲(chǔ)某種數(shù)據(jù)波材,在創(chuàng)建索引的時(shí)候就需要將數(shù)據(jù)結(jié)構(gòu)优训,即Mapping確定下來(lái),于此同時(shí)索引的設(shè)定和很多固定配置將不能改變各聘。

那如果后續(xù)業(yè)務(wù)發(fā)生變化,需要改變數(shù)據(jù)結(jié)構(gòu)或者更換ES更換分詞器怎么辦呢抡医?為此躲因,Elastic團(tuán)隊(duì)提供了很多通過輔助?具來(lái)幫助開發(fā)?員進(jìn)?重建索引的方案。
如果對(duì) reindex API 不熟悉忌傻,那么在遇到重構(gòu)的時(shí)候大脉,必然事倍功半,效率低下水孩。反之镰矿,就可以方便地進(jìn)行索引重構(gòu),省時(shí)省力俘种。

步驟

假設(shè)之前我們已經(jīng)存在一個(gè)blog索引秤标,因?yàn)楦鼡Q分詞器需要對(duì)該索引中的數(shù)據(jù)進(jìn)行重建索引绝淡,以便支持業(yè)務(wù)使用新的分詞規(guī)則搜索數(shù)據(jù),并且盡可能使這個(gè)變化對(duì)外服務(wù)沒有感知苍姜,大概分為以下幾個(gè)步驟:?

  • 新增?個(gè)索引blog_lastest牢酵,Mapping數(shù)據(jù)結(jié)構(gòu)與blog索引一致
  • blog數(shù)據(jù)同步至blog_lastest
  • 刪除blog索引
  • 數(shù)據(jù)同步后給blog_lastest添加別名blog

新建索引

在這里推薦一個(gè)ES管理工具Kibana,主要針對(duì)數(shù)據(jù)的探索衙猪、可視化和分析馍乙。

官網(wǎng)
put /blog_lastest/
{
    "mappings":{
        "properties":{
            "title":{
                "type":"text",
                "analyzer":"ik_max_word"
            },
            "author":{
                "type":"keyword",
                "fields":{
                    "seg":{
                        "type":"text",
                        "analyzer":"ik_max_word"
                    }
                }
            }
        }
    }
}

將舊索引數(shù)據(jù)copy到新索引

同步等待

接?將會(huì)在 reindex 結(jié)束后返回

POST /_reindex
{
    "source": {
        "index": "blog"
    },
    "dest": {
        "index": "blog_lastest"
    }
}

kibana 中的使用如下所示

-w706

當(dāng)然高版本(7.1.1)中,ES都有提供對(duì)應(yīng)的Java REST Client垫释,比如

ReindexRequest reindexRequest = new ReindexRequest();
reindexRequest.setSourceIndices("blog").setSource.setDestIndex("blog_lastest");
TaskSubmissionResponse taskSubmissionResponse = client.submitReindexTask(reindexRequest, RequestOptions.DEFAULT);

為了防止贅述丝格,接下來(lái)舉例全部以kibana中請(qǐng)求介紹,如果有需要用Java REST Client棵譬,可以自行去ES官網(wǎng)查看显蝌。

異步執(zhí)?

如果 reindex 時(shí)間過?,建議加上 wait_for_completion=false 的參數(shù)條件茫船,這樣 reindex 將直接返回 taskId琅束。

POST /_reindex?wait_for_completion=false
{
    "source": {
        "index": "blog"
    },
    "dest": {
        "index": "blog_lastest"
    }
}

返回:

{
  "task" : "dpBihNSMQfSlboMGlTgCBA:4728038"
}

op_type 參數(shù)

op_type 參數(shù)控制著寫入數(shù)據(jù)的沖突處理方式,如果把 op_type 設(shè)置為 create【默認(rèn)值】算谈,在 _reindex API 中涩禀,表示寫入時(shí)只在 dest index中添加不存在的 doucment,如果相同的 document 已經(jīng)存在然眼,則會(huì)報(bào) version confilct 的錯(cuò)誤艾船,那么索引操作就會(huì)失敗「呙浚【這種方式與使用 _create API 時(shí)效果一致】

POST _reindex
{
  "source": {
    "index": "blog"
  },
  "dest": {
    "index": "blog_lastest",
    "op_type": "create"
  }
}

如果這樣設(shè)置了屿岂,也就不存在更新數(shù)據(jù)的場(chǎng)景了【沖突數(shù)據(jù)無(wú)法寫入】,我們也可以把 op_type 設(shè)置為 index鲸匿,表示所有的數(shù)據(jù)全部重新索引創(chuàng)建爷怀。

conflicts 配置

默認(rèn)情況下,當(dāng)發(fā)生 version conflict 的時(shí)候带欢,_reindex 會(huì)被 abort运授,任務(wù)終止【此時(shí)數(shù)據(jù)還沒有 reindex 完成】,在返回體中的 failures 指標(biāo)中會(huì)包含沖突的數(shù)據(jù)【有時(shí)候數(shù)據(jù)會(huì)非常多】渡贾,除非把 conflicts 設(shè)置為 proceed逗宜。

關(guān)于 abort 的說(shuō)明,如果產(chǎn)生了 abort擂仍,已經(jīng)執(zhí)行的數(shù)據(jù)【例如更新寫入的】仍然存在于目標(biāo)索引,此時(shí)任務(wù)終止,還會(huì)有數(shù)據(jù)沒有被執(zhí)行亿昏,也就是漏數(shù)了。換句話說(shuō),該執(zhí)行過程不會(huì)回滾脊髓,只會(huì)終止。如果設(shè)置了 proceed,任務(wù)在檢測(cè)到數(shù)據(jù)沖突的情況下律罢,不會(huì)終止,會(huì)跳過沖突數(shù)據(jù)繼續(xù)執(zhí)行悦冀,直到所有數(shù)據(jù)執(zhí)行完成师骗,此時(shí)不會(huì)漏掉正常的數(shù)據(jù),只會(huì)漏掉有沖突的數(shù)據(jù)。

POST _reindex
{
  "source": {
    "index": "blog"
  },
  "dest": {
    "index": "blog_lastest",
    "op_type": "create"
  },
  "conflicts": "proceed"
}

我們可以故意把 op_type 設(shè)置為 create厂置,人為制造數(shù)據(jù)沖突的場(chǎng)景野揪,測(cè)試時(shí)更容易觀察到?jīng)_突現(xiàn)象。

如果把 conflicts 設(shè)置為 proceed,在返回體結(jié)果中不會(huì)再出現(xiàn) failures 的信息,但是通過 version_conflicts 指標(biāo)可以看到具體的數(shù)量。

批次大小配置

當(dāng)你發(fā)現(xiàn)reindex的速度有些慢的時(shí)候,可以在 query 參數(shù)的同一層次【即 source 參數(shù)中】添加 size 參數(shù),表示 scroll size 的大小【會(huì)影響批次的次數(shù),進(jìn)而影響整體的速度】捧韵,如果不顯式設(shè)置磷瘤,默認(rèn)是一批 1000 條數(shù)據(jù),在一開始的簡(jiǎn)單示例中也看到了膀斋。
如下梭伐,設(shè)置 scroll size 為 5000:

POST /_reindex?wait_for_completion=false
{
    "source": {
        "index": "blog",
        "size":5000
    },
    "dest": {
        "index": "blog_lastest",
        "op_type": "create"
    },
    "conflicts": "proceed"
}

測(cè)試后糊识,速度達(dá)到了 30 分鐘 500 萬(wàn)左右拌滋,明顯提升了很多。

根據(jù)taskId可以實(shí)時(shí)查看任務(wù)的執(zhí)行狀態(tài)

一般來(lái)說(shuō)沧竟,如果我們的 source index 很大【比如幾百萬(wàn)數(shù)據(jù)量】铸敏,則可能需要比較長(zhǎng)的時(shí)間來(lái)完成 _reindex 的工作,可能需要幾十分鐘悟泵。而在此期間不可能一直等待結(jié)果返回桩撮,可以去做其它事情敦第,如果中途需要查看進(jìn)度,可以通過 _tasks API 進(jìn)行查看店量。

GET /_tasks/{taskId}

返回:

{
  "completed" : false,
  "task" : {
    "node" : "dpBihNSMQfSlboMGlTgCBA",
    "id" : 4704218,
    "type" : "transport",
    "action" : "indices:data/write/reindex",
    ……
}

當(dāng)執(zhí)行完畢時(shí),completed為true
查看任務(wù)進(jìn)度以及取消任務(wù)鞠呈,除了根據(jù)taskId查看以外融师,我們還可以通過查看所有的任務(wù)中篩選本次reindex的任務(wù)。

GET _tasks?detailed=true&actions=*reindex

返回結(jié)果:

{
  "nodes" : {
    "dpBihNSMQfSlboMGlTgCBA" : {
      "name" : "node-16111-9210",
      "transport_address" : "192.168.XXX.XXX:9310",
      "host" : "192.168.XXX.XXX",
      "ip" : "192.168.16.111:9310",
      "roles" : [
        "ingest",
        "master"
      ],
      "attributes" : {
        "xpack.installed" : "true",
        "transform.node" : "false"
      },
      "tasks" : {
        "dpBihNSMQfSlboMGlTgCBA:6629305" : {
          "node" : "dpBihNSMQfSlboMGlTgCBA",
          "id" : 6629305,
          "type" : "transport",
          "action" : "indices:data/write/reindex",
          "status" : {
            "total" : 8361421,
            "updated" : 0,
            "created" : 254006,
            "deleted" : 0,
            "batches" : 743,
            "version_conflicts" : 3455994,
            "noops" : 0,
            "retries" : {
              "bulk" : 0,
              "search" : 0
            },
            "throttled_millis" : 0,
            "requests_per_second" : -1.0,
            "throttled_until_millis" : 0
          },
          "description" : "reindex from [blog] to [blog_lastest][_doc]",
          "start_time_in_millis" : 1609338953464,
          "running_time_in_nanos" : 1276738396689,
          "cancellable" : true,
          "headers" : { }
        }
      }
    }
  }
}

注意觀察里面的幾個(gè)重要指標(biāo)蚁吝,例如從 description 中可以看到任務(wù)描述旱爆,從 tasks 中可以找到任務(wù)的 id【例如 dpBihNSMQfSlboMGlTgCBA:6629305】,從 cancellable 可以判斷任務(wù)是否支持取消操作窘茁。
這個(gè) API 其實(shí)就是模糊匹配怀伦,同理也可以查詢其它類型的任務(wù)信息,例如使用 GET _tasks?detailed=true&actions=*byquery 查看查詢請(qǐng)求的狀態(tài)山林。
當(dāng)集群的任務(wù)太多時(shí)我們就可以根據(jù)task_id房待,也就是上面提到GET /_tasks/task_id 方式更加準(zhǔn)確地查詢指定任務(wù)的狀態(tài),避免集群的任務(wù)過多驼抹,不方便查看桑孩。
如果遇到操作失誤的場(chǎng)景,想取消任務(wù)框冀,有沒有辦法呢流椒?
當(dāng)然有啦,雖然覆水難收明也,通過調(diào)用
_tasks API

POST _tasks/task_id/_cancel

這里的 task_id 就是通過上面的查詢?nèi)蝿?wù)接口獲取的任務(wù)id(任務(wù)要支持取消操作宣虾,即【cancellable 為 true】時(shí)方能收效)。

刪除舊索引

當(dāng)我們通過 API 查詢發(fā)現(xiàn)任務(wù)完成后温数,就可以進(jìn)行后續(xù)操作绣硝,我這里是要?jiǎng)h除舊索引,然后再給新索引起別名帆吻,用于替換舊索引域那,這樣才能保證對(duì)外服務(wù)沒有任何感知。

DELETE /blog

使用別名

POST /_aliases
{
    "actions":[
        {
            "add":{
                "index":"blog_lastest",
                "alias":"blog"
            }
        }
    ]
}

通過別名訪問新索引

進(jìn)行過以上操作后猜煮,我們可以使用一個(gè)簡(jiǎn)單的搜索驗(yàn)證服務(wù)次员。

POST /blog/_search
{
    "query": {
        "match": {
            "author": "james"
        }
    }
}

如果搜索結(jié)果達(dá)到我們的預(yù)期目標(biāo),至此王带,數(shù)據(jù)索引重建遷移完成淑蔚。

本文可轉(zhuǎn)載,但需聲明原文出處愕撰。 程序員小明刹衫,一個(gè)很少加班的程序員醋寝。歡迎關(guān)注微信公眾號(hào)“程序員小明”,獲取更多優(yōu)質(zhì)文章带迟。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末音羞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仓犬,更是在濱河造成了極大的恐慌嗅绰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搀继,死亡現(xiàn)場(chǎng)離奇詭異窘面,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叽躯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門财边,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人点骑,你說(shuō)我怎么就攤上這事酣难。” “怎么了畔况?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵鲸鹦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我跷跪,道長(zhǎng)馋嗜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任吵瞻,我火速辦了婚禮葛菇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘橡羞。我一直安慰自己眯停,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布卿泽。 她就那樣靜靜地躺著莺债,像睡著了一般。 火紅的嫁衣襯著肌膚如雪签夭。 梳的紋絲不亂的頭發(fā)上齐邦,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音第租,去河邊找鬼措拇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛慎宾,可吹牛的內(nèi)容都是我干的丐吓。 我是一名探鬼主播浅悉,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼券犁!你這毒婦竟也來(lái)了术健?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤粘衬,失蹤者是張志新(化名)和其女友劉穎苛坚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體色难,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年等缀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枷莉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尺迂,死狀恐怖笤妙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情噪裕,我是刑警寧澤蹲盘,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站膳音,受9級(jí)特大地震影響召衔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜祭陷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一苍凛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兵志,春花似錦醇蝴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至按价,卻和暖如春惭适,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俘枫。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工腥沽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸠蚪。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓今阳,卻偏偏與公主長(zhǎng)得像师溅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盾舌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容