ElasticSearch排序引發的all shards failed異常緣由分析

背景

注:ElasticSearch版本爲5.4html

在咱們的日誌系統裏須要一些系統索引,這些系統索引在應用初始化的時候就會被添加到ElasticSearch中去,這些在ElasticSearch中的系統索引在沒有索引數據的時候,只有索引名和一些配置信息,沒有mapping信息。當用戶去根據時間區間排序搜索日誌信息的時候,ElasticSearch就會產生all shards failed異常。具體異常信息以下:java

Caused by: [.alert/NXa3zq5WSb-wGBKgyZibzw] QueryShardException[No mapping found for [timestamp] in order to sort on]
	at org.ElasticSearch.search.sort.FieldSortBuilder.build(FieldSortBuilder.java:262)
	at org.ElasticSearch.search.sort.SortBuilder.buildSort(SortBuilder.java:156)
	at org.ElasticSearch.search.SearchService.parseSource(SearchService.java:617)
	at org.ElasticSearch.search.SearchService.createContext(SearchService.java:468)
	at org.ElasticSearch.search.SearchService.createAndPutContext(SearchService.java:444)
	at org.ElasticSearch.search.SearchService.executeQueryPhase(SearchService.java:252)
	at org.ElasticSearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:331)
	at org.ElasticSearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:328)
	at org.ElasticSearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:69)
	at org.ElasticSearch.transport.TransportService$7.doRun(TransportService.java:627)
	at org.ElasticSearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:638)
	at org.ElasticSearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
	... 3 more

查看了.alert的索引數據再結合ElasticSearch的異常信息判斷,我懷疑是因爲.alert系統索引沒有timestamp mapping信息引發的,.alert索引初始化沒有任何數據時,ElasticSearch中的信息以下:api

http://dev:9200/.alert
{
    ".alert": {
        "aliases": {
            "alert": {}
        },
        "mappings": {
            "alert": {}
        },
        "settings": {
            "index": {
                "refresh_interval": "-1",
                "number_of_shards": "5",
                "provided_name": ".alert",
                "creation_date": "1533613744728",
                "store": {
                    "type": "fs"
                },
                "number_of_replicas": "1",
                "uuid": "YuPjsObOTMO6u3fEdG6hVw",
                "version": {
                    "created": "5040099"
                }
            }
        }
    }
}

看到這些信息以後,我開始了用如下方法嘗試解決。服務器

解決方法

如下方法1和方法2都以失敗而了結,只有方法3能夠成功解決該問題。但在解決問題中我查找了不少資料,讓我對ElasticSearchmapping有了更深地理解,所以我將解決該問題的過程記錄了下來。app

方法1:添加索引模板

首先,因爲是沒有timestamp這個mapping信息,所以我想到建立索引模板,將.alert這個索引的mappings信息用模板來設置,以便在索引建立的時候就有相應的mapping信息。模板信息以下:ide

{
    "alert": {
        "order": 0,
        "template": "alert",
        "settings": {
            "index": {
                "number_of_shards": "5",
                "number_of_replicas": "1",
                "refresh_interval": "2s"
            }
        },
        "mappings": {
            "alert": {
                "properties": {
                    "timestamp": {
                        "type": "date"
                    }
                }
            }
        },
        "aliases": {}
    }
}

可是,通過測試後發現,all shards failed的問題仍是會產生。究其緣由是因爲:測試

索引模板只會在插入新索引數據的時候生效,若是沒有索引數據,索引模板定義的mappings信息不會生效,並且對模板的改變不會影響到已存在的索引。大數據

此時,.alert這個索引爲空,尚未新數據插入,所以,模板不會生效,也就導致該方法不會解決all shards failed的問題。ui

方法2:建立索引時添加mapping

因爲ElasticSearch容許在建立索引時就建立mapping信息,因而我想到了這個方法,通過測試後,能夠解決all shards failed的問題。可是,產生了一個嚴重的後果,咱們用.alert索引來記錄服務器報警信息,當我往.alert這個索引裏添加數據時,只有timestamp這個字段的數據添加進去了,其餘數據像產生報警的主機、報警內容等信息添加失敗。日誌

查詢官方文檔發現:

mapping信息一旦被建立,就不容許被修改。改變已有的mapping就意味着使已經存在的索引數據無效,解決的辦法就是使用正確的mappings信息來建立新的索引,而後從新把數據添加到新索引中。雖然官方提供了reindex方法來解決這個問題,可是,在大數據量的狀況下,reindex代價比較高,所以,建立索引時添加mapping這個方法也行不通。

方法3:給排序條件加unmapped_type

ElasticSearchsearch api能夠設置排序時忽略字段的哪些映射。默認狀況下,若是沒有與排序字段關聯的映射,則搜索請求將失敗。unmapped_type選項容許設置忽略沒有映射的字段,從而不對該字段排序。因爲timestampmappingdate類型,所以,在搜索排序條件中增長{"timestamp":{"unmapped_type":"date"}}成功解決因爲排序字段沒有date映射引發的all shards failed問題。

參考資料

索引模板官方文檔:Index Templates

索引排序官方文檔:Sort

更新已存在的mapping信息官方文檔:updating_existing_mappings

stackoverflow問題連接:No mapping found for field in order to sort on in ElasticSearch

相關文章
相關標籤/搜索