Elasticsearch逐步升级从v1.7到v2.4,最后到v5.5的经历
本篇文章是2017年Elasticsearch圣诞月历12/12的文章。
Elasticsearch在1.x、2.x和5.x(这个月已经发布了6.x)中进行了逐年的版本升级。在这种情况下,还有很多人在使用1.x和2.x版本的Elasticsearch。随着每个版本的升级,Elasticsearch的查询和映射都会发生重大变化。而且考虑到服务的运行率,重启集群或进行热替换都变得困难。
有足够的魅力使得5.x版本能够超越这样的障碍。在我们的搜索系统中,通过Elasticsearch升级,平均响应时间提升了2倍。光这一点就足以证明升级是非常值得的。
摘要
-
- 検索クエリごとにきちんとテストを書きましょう、Elasticsearchを実際に使ったCIを組み立てる
-
- テスト環境のElasticsearchのバージョンアップしてひたすらGreenを目指す
- Deprecated クエリをちゃんと書き換えましょう、Deprecation logを活用する
背景 – The background
我們的公司Cookpad不僅在國內,而且在全球提供21種語言的食譜服務,涵蓋67個國家。Elasticsearch被用於支持這個全球平台的食譜搜索,它可以搜尋超過21種語言的內容。我們為每種語言和地區準備了對應的索引映射,以提供最適合該語言和地區的搜索服務。
长期以来,我们一直使用Elasticsearch v1.7,但随着服务规模的扩大,性能开始成为我们关注的问题。所以在今年,我们逐步升级版本从v1.7到v2.4再到v5.5。每次主要版本升级都有很多mapping和query DSL的更改,我想讲述一下我们是如何有效解决这些问题的。
升级步骤
-
- Elasticsearch branch 作成
-
- ローカルでテストが通るまでコードを直す
-
- マニュアルチェック(テストでカバーされていないバグ発見)
-
- ステージング環境にESクラスタを立ててコード&インフラ周りのチェック
-
- プロダクションデプロイ(hot swap)
- 追加の改善, fix, deprecatedクエリ書き換え
在Cookpad中,我们为每个搜索功能都准备了一些整合测试,这些测试在Elasticsearch上实际运行查询来确认其行为。因此,我们只需升级Elasticsearch并运行测试,就能找到大部分问题所在。
当进行测试时,首先需要创建测试用的索引,否则无法开始,因此我们首先对映射进行修改。然后,我们一直在不断修改查询DSL。同时,不断查看Elasticsearch文档中的变化以保持更新。
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/breaking-changes-2.0.html
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/breaking-changes-5.0.html
主要变更是在1.7到2.4之间发生了。
映射的变化
-
- 名称変更: index_analyzer, position_offset_gap など
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/breaking_20_mapping_changes.html
マッピングのなかで同じフィールド名が使えなくなった
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/breaking_20_mapping_changes.html#_conflicting_field_mappings
stopwords, custom_stemファイルなどをElasticsearchの設定ディレクトリ以外から読めなくなった
Javaのセキュリティアップデートにより外部ファイルを指定したディレクトリからしか読み込めなくなりました。
stopwordsなどのカスタムファイルを/etc/elasticsearch/内に置いた
其他更改
-
- gem update: https://rubygems.org/gems/elasticsearch/versions
CI環境をv2.4にセットアップ
gemアップデートによるpercolateクエリの不具合
multi percolateクエリをElasticsearch::API::Utils.__bulkify(body)というメソッドを直接たたいてビルドしていたのがだめになった。
以前percolateクエリにおいてbulkifyが動いていたのが、この変更により出来なくなっていた
按照这样的处理方式,几乎所有的映射更改和CI都通过了,已修复了手动检查中发现的错误,并成功进行了升级。然而,正如您所注意到的,查询几乎没有改变。实际上,大部分查询已经过时了,但由于一直在支持,所以能正常工作。这成为了v5.5升级过程中的一个重要负担。
当2.4变为5.5时的主要改变
就像上述的那样,从v1.7升级到v2.4的过程中,几乎没有改变查询语句。在v2版本中,已经废弃的查询语句还勉强能够使用。但是当升级到v5版本时,所有废弃的查询语句都无法使用了,无法确定查询错误是由v2升级引起还是v5升级引起的,只能在v2和v5的文档之间来回切换。
从这个经验中学到的教训是,在升级到v5时,我们根据Elasticsearch的弃用日志进行了修正,以解决被弃用的API和查询。弃用日志将打印出在下一个版本中将被删除的查询的日志。因此,如果我们在计划删除的下一个版本之前修复这些查询,我认为升级将更加顺利。
映射变化
type: “string” to type: “keyword”
Significant terms aggregation機能がkeywordフィールドを推奨
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/breaking_50_aggregations_changes.html#_significant_terms_on_numeric_fields
fielddata: true
Suggestion変更
multi_field removed
percolatorの大きな変更によりpercolator用のマッピングを追加
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/breaking_50_percolator.html
更改查询
-
- v2.xで廃止されたfilterをqueryに変更
function_score クエリ書き換え
filterクエリ書き換え
{
filter: { bool: { must: filters } },
query: [queries],
functions: [functions]
}
请用中文重新表达以下句子,只需提供一种选项:
-> 请提供以下句子的中文翻译。
{
query: { bool: { must: [filters, queries] } },
functions: [functions]
}
-
- なぜかv2で使えていた時間unitの 1w が使えなくなってた
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/common-options.html#time-units
v2.xでdeprecatedになったfiltered クエリがv5.xで削除されたので書き換え
filtered: query -> bool: must
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/breaking_20_query_dsl_changes.html#_literal_filtered_literal_query_and_literal_query_literal_filter_deprecated
execution “or” deprecated
Suggestion completionの大型変更によりレスポンスボディが変わってた
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/breaking_50_suggester.html
size: 0 in terms aggregation function is deprecated
GroovyをPainlessへ書き換え
(Painlessのドキュメント少ない )
scan & scroll でreindexしていたのを、v5から新設されたreindex APIに置き換えた
其他
-
- suggestion query に約8000文字以上のリクエストが来るとクラスタが落ちる
ES6で直ったらしいです ref1, ref2
これは本当に皆さんも気をつけて下さい、アプリ側で文字制限を設けました
起動オプションが変わった
-D es.network.host=xxx to -E network.host=xxx
他に特定の言語向けの自然言語処理プラグインを新しいバージョン向けに自前で書き直す必要がありました
被v5.x版本弃用的功能需要重写。
上述的变更通过了测试,并成功进行了生产部署。在版本升级后,根据废弃日志,我们重写了以下API。
-
- Percolator API to query
-
- Suggestion API to query
- Reindex API
其他建议
使用代理工具等捕获实际发出到 Elasticsearch 的查询,然后使用 Cerebro 等工具直接发送,并使用 Cerebro 进行调试直到问题解决,非常方便。
所感 – “个人观感” (Personal impression)
Elasticsearch每次升级都变得更容易升级了,对吧。在ES6中还支持了滚动升级。默认开启了Deprecation log,当发送错误查询时会返回错误的位置。因此,调试变得更容易了。
官方文档的完善也非常有帮助。里面详细介绍了版本升级后需要如何修改的内容。
这次没能涉及到基础设施的话题。由于服务的特性,热插拔相对容易一些。另外,由于具体内容较少,可能导致文章中有一些细节不够清楚的地方,非常抱歉。如果对这些方面有任何疑问,请在评论中提问。
明天是关于“为Elasticsearch开发的新形态素解析器’Sudachi’”的主题,我期待着接下来的圣诞日历。