{"id":1035,"date":"2020-06-28T22:27:14","date_gmt":"2020-06-28T13:27:14","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1035"},"modified":"2020-06-30T19:06:09","modified_gmt":"2020-06-30T10:06:09","slug":"elasticsearch-%eb%ac%b4%ec%a4%91%eb%8b%a8-%eb%a6%ac%ec%9d%b8%eb%8d%b1%ec%8b%b1","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1035","title":{"rendered":"Elasticsearch zero downtime reindex"},"content":{"rendered":"<h1>Elasticsearch zero downtime reindex<\/h1>\n<p><a href=\"\/wordpress\/?p=935\">JDBC \ub97c \uc774\uc6a9\ud55c RDBMS \uc5f0\ub3d9\ud658\uacbd<\/a> \uc5d0\uc11c\uc758 \ubb34\uc911\ub2e8 \ub9ac\uc778\ub371\uc2f1\uc785\ub2c8\ub2e4.<\/p>\n<h2>\ubb34\uc911\ub2e8 \ub9ac\uc778\ub371\uc2f1 \uc804\ub7b5<\/h2>\n<ol>\n<li>\n<p>\ucd5c\ucd08\uc5d0 <code>testindex_1<\/code> \uc778\ub371\uc2a4\uc640 <code>testindex<\/code> \ub77c\ub294 alias \uac00 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<\/li>\n<li>\n<p><code>testindex_\ud0c0\uc784\uc2a4\ud0ec\ud504<\/code> \ub77c\ub294 \uc778\ub371\uc2a4\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<\/li>\n<li>\n<p><code>reindex<\/code> \ud569\ub2c8\ub2e4.<\/p>\n<\/li>\n<li>\n<p>alias \uac00 \uc0c8\ub85c \uc0dd\uae34 <code>testindex_\ud0c0\uc784\uc2a4\ud0ec\ud504<\/code> \ub97c \ud5a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud569\ub2c8\ub2e4.<\/p>\n<\/li>\n<li>\n<p>\uc6d0\ub798\uc758 \uc778\ub371\uc2a4\ub294 \uc0ad\uc81c\ud569\ub2c8\ub2e4.<\/p>\n<\/li>\n<li>\n<p>reindex \ub3c4\uc911\uc5d0 \ubc1c\uc0dd\ud558\ub294 update \uac00 \ub204\ub77d\ub420 \uc218 \uc788\uc73c\ubbc0\ub85c \ub514\ube44\ub97c \uc5c5\ub370\uc774\ud2b8 \ud574\uc11c \ubcc0\uacbd\ubd84\uc744 \uc0c8\ub85c \uc0dd\uae34 \uc778\ub371\uc2a4\uc5d0 \uc7ac\uc804\uc1a1\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4.<\/p>\n<\/li>\n<\/ol>\n<h2>python \ud655\uc778<\/h2>\n<pre><code class=\"language-bash\">python3 -V\nPython 3.6.9\n\nsudo apt install python3-pip\n\npip3 install elasticsearch\npip3 install pymysql\n\npip3 install --upgrade requests<\/code><\/pre>\n<h2>mappings.json \uc0dd\uc131<\/h2>\n<pre><code class=\"language-bash\">cat mappings.json<\/code><\/pre>\n<pre><code class=\"language-json\">{\n  &quot;settings&quot; : {\n    &quot;number_of_shards&quot;: &quot;5&quot;,\n    &quot;number_of_replicas&quot;: &quot;1&quot;,\n    &quot;index&quot;:{\n      &quot;analysis&quot;:{\n        &quot;analyzer&quot;:{\n          &quot;korean&quot;:{\n            &quot;type&quot;:&quot;custom&quot;,\n            &quot;tokenizer&quot;:&quot;seunjeon_default_tokenizer&quot;,\n            &quot;filter&quot; : [&quot;lowercase&quot;, &quot;synonym&quot;, &quot;stopword&quot;]\n          },\n          &quot;whitespace&quot;: {\n            &quot;type&quot;: &quot;custom&quot;,\n            &quot;tokenizer&quot;: &quot;whitespace&quot;,\n            &quot;char_filter&quot;: [\n              &quot;sepcial_char_filter&quot;\n            ],\n            &quot;filter&quot;: [\n              &quot;lowercase&quot;,\n              &quot;stop&quot;,\n              &quot;snowball&quot;\n            ]\n          },\n          &quot;standard&quot;: {\n            &quot;type&quot;: &quot;custom&quot;,\n            &quot;tokenizer&quot;: &quot;standard&quot;,\n            &quot;char_filter&quot;: [\n              &quot;sepcial_char_filter&quot;\n            ],\n            &quot;filter&quot;: [\n              &quot;lowercase&quot;,\n              &quot;stop&quot;,\n              &quot;snowball&quot;\n            ]\n          }\n        },\n        &quot;char_filter&quot;: {\n          &quot;sepcial_char_filter&quot;: {\n            &quot;type&quot;: &quot;mapping&quot;,\n            &quot;mappings&quot;: [ &quot;+ =&gt; _plus_&quot;, &quot;- =&gt; _minus_&quot;, &quot;# =&gt; _sharp_&quot; ]\n          }\n        },\n        &quot;filter&quot; : {\n          &quot;synonym&quot; : {\n            &quot;type&quot; : &quot;synonym&quot;,\n            &quot;synonyms_path&quot; : &quot;synonyms.txt&quot;\n          },\n          &quot;stopword&quot; : {\n            &quot;type&quot; : &quot;stop&quot;,\n            &quot;stopwords_path&quot; : &quot;stopwords.txt&quot;\n          }\n        },\n        &quot;tokenizer&quot;: {\n          &quot;seunjeon_default_tokenizer&quot;: {\n            &quot;index_eojeol&quot;: &quot;true&quot;,\n            &quot;user_dict_path&quot;: &quot;user_dict.csv&quot;,\n            &quot;index_poses&quot;: [\n                &quot;UNK&quot;, &quot;EP&quot;, &quot;I&quot;, &quot;J&quot;, &quot;M&quot;,\n                &quot;N&quot;, &quot;SL&quot;, &quot;SH&quot;, &quot;SN&quot;, &quot;VCP&quot;,\n                &quot;XP&quot;, &quot;XS&quot;, &quot;XR&quot;\n            ],\n            &quot;decompound&quot;: &quot;true&quot;,\n            &quot;type&quot;: &quot;seunjeon_tokenizer&quot;\n          }\n        }\n      }\n    }\n  },\n  &quot;mappings&quot; : {\n    &quot;_doc&quot; : {\n      &quot;properties&quot; : {\n        &quot;@timestamp&quot; : {\n          &quot;type&quot; : &quot;date&quot;\n        },\n        &quot;itemid&quot; : {\n          &quot;type&quot; : &quot;integer&quot;\n        },\n        &quot;itemname&quot; : {\n          &quot;type&quot; : &quot;text&quot;,\n          &quot;fields&quot;: {\n            &quot;en&quot;: {\n              &quot;type&quot;: &quot;text&quot;,\n              &quot;analyzer&quot;: &quot;standard&quot;\n            },\n            &quot;ko&quot;: {\n              &quot;type&quot;: &quot;text&quot;,\n              &quot;analyzer&quot;: &quot;korean&quot;\n            }\n          }\n        },\n        &quot;category&quot; : {\n          &quot;type&quot; : &quot;text&quot;,\n          &quot;analyzer&quot;: &quot;korean&quot;\n        },\n        &quot;price&quot; : {\n          &quot;type&quot;: &quot;scaled_float&quot;,\n          &quot;scaling_factor&quot;: 10000\n        },\n        &quot;lastupdate&quot; : {\n          &quot;type&quot; : &quot;date&quot;\n        },\n        &quot;regdate&quot; : {\n          &quot;type&quot; : &quot;date&quot;\n        }\n      }\n    }\n  }\n}<\/code><\/pre>\n<h2>python \ud30c\uc77c \uc0dd\uc131<\/h2>\n<pre><code class=\"language-bash\">cat reindex.py<\/code><\/pre>\n<pre><code class=\"language-python\">from elasticsearch import Elasticsearch\nimport pymysql\nimport json\nfrom datetime import datetime\n\ndef _suffix():\n    return datetime.now().strftime(&quot;%Y%m%d%H%M%S%f&quot;)\n\nes = Elasticsearch(&#039;localhost:9200&#039;)\nindex = &#039;items_1&#039;\nalias = &#039;items&#039;\n\nwith open(&#039;mappings.json&#039;, &#039;r&#039;) as f:\n    mappings = json.load(f)\n\n# if es.indices.exists(index=index):\n#     pass\n# else:\n#     es.indices.create(index=index, body=mappings)\n#     es.indices.update_aliases({\n#         &quot;actions&quot;: [\n#             {&quot;add&quot;: {&quot;index&quot;: index, &quot;alias&quot;: alias}}\n#         ]\n#     })\n\nold_index, new_index = &#039;&#039;, &#039;&#039;\nfor idx in es.indices.get(&#039;items*&#039;):\n    if old_index == &#039;&#039;:\n        old_index = idx\n    elif new_index == &#039;&#039;:\n        new_index = idx\n\n    if old_index != &#039;&#039; and new_index != &#039;&#039;:\n        print(&#039;reindexing in process...&#039;)\n        quit()\n\nnew_index = &#039;%s_%s&#039; % (alias, _suffix())\nes.indices.create(index=new_index, body=mappings)\n\nnow = datetime.now()\n\nresult = es.reindex({\n        &quot;source&quot;: { &quot;index&quot;: old_index },\n        &quot;dest&quot;: { &quot;index&quot;: new_index }\n    }, wait_for_completion=True, request_timeout=600)\n\nprint(&#039;reindex finished.&#039;)\n\nes.indices.update_aliases({\n    &quot;actions&quot;: [\n        {&quot;remove&quot;: { &quot;index&quot;: old_index, &quot;alias&quot;: alias }},\n        {&quot;add&quot;: { &quot;index&quot;: new_index, &quot;alias&quot;: alias }}\n    ]\n})\n\nes.indices.delete(index=old_index, ignore=[400, 404])\n\nconn = pymysql.connect(host=&#039;localhost&#039;, user=&#039;testuser&#039;, password=&#039;test1234&#039;,\n                       db=&#039;db_test&#039;, charset=&#039;utf8&#039;)\n\nsql = &quot;update items set lastupdate = now() where lastupdate &gt;= %s&quot;\n\ncurs = conn.cursor()\ncurs.execute(sql, (now))\nconn.commit()\n\nconn.close()<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Elasticsearch zero downtime reindex JDBC \ub97c \uc774\uc6a9\ud55c RDBMS \uc5f0\ub3d9\ud658\uacbd \uc5d0\uc11c\uc758 \ubb34\uc911\ub2e8 \ub9ac\uc778\ub371\uc2f1\uc785\ub2c8\ub2e4. \ubb34\uc911\ub2e8 \ub9ac\uc778\ub371\uc2f1 \uc804\ub7b5 \ucd5c\ucd08\uc5d0 testindex_1 \uc778\ub371\uc2a4\uc640 testindex \ub77c\ub294 alias \uac00 \uc788\uc2b5\ub2c8\ub2e4. testindex_\ud0c0\uc784\uc2a4\ud0ec\ud504 \ub77c\ub294 \uc778\ub371\uc2a4\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. reindex \ud569\ub2c8\ub2e4. alias \uac00 \uc0c8\ub85c \uc0dd\uae34 testindex_\ud0c0\uc784\uc2a4\ud0ec\ud504 \ub97c \ud5a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud569\ub2c8\ub2e4. \uc6d0\ub798\uc758 \uc778\ub371\uc2a4\ub294 \uc0ad\uc81c\ud569\ub2c8\ub2e4. reindex \ub3c4\uc911\uc5d0 \ubc1c\uc0dd\ud558\ub294 update \uac00 \ub204\ub77d\ub420 \uc218 \uc788\uc73c\ubbc0\ub85c \ub514\ube44\ub97c \uc5c5\ub370\uc774\ud2b8 \ud574\uc11c \ubcc0\uacbd\ubd84\uc744 \uc0c8\ub85c \uc0dd\uae34 \uc778\ub371\uc2a4\uc5d0\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1035\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-1035","post","type-post","status-publish","format-standard","hentry","category-elasticsearch"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1035"}],"version-history":[{"count":13,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1035\/revisions"}],"predecessor-version":[{"id":1069,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1035\/revisions\/1069"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}