一次elasticsearch響應緩慢的情況解決過程

調用es接口等待時間過長

查詢es集羣狀態:curl -XGET http://192.168.0.12:9200/_cluster/health?pretty   
發現集羣狀態爲red  "status" : "red"
查看每個索引的狀態:curl -XGET http://192.168.0.12:9200/_cat/indices?v  
發現有許多之前安裝X-Pack時候自帶的無用索引(X-Pack是kibana開啓系統監控必須集成的組件,用了一段時間後面過期了需要證書,就把X-Pack給下了)
刪除無用索引(帶通配符):curl -XDELETE "http://192.168.0.12:9200/.monitoring-*"
查看所以索引分配方式:curl -s "http://192.168.0.12:9200/_cat/shards" 
過濾查看所有未分配索引的方式:curl -s "http://192.168.0.12:9200/_cat/shards" | grep UNASSIGNED
發現有3個索引的狀態是UNASSIGNED(每個索引原先4個primary,但是集羣僅有3個節點,有一個主分片沒有被分配)
自動分配分片(沒試成功):curl -XPOST http://192.168.0.12:9200/_cluster/reroute?retry_failed  
手動移動分片(沒試成功):

curl -XPOST 'http://192.168.0.12:9200/_cluster/reroute?pretty' -d '

{

    "commands" : [ {

        "allocate_stale_primary" : {

            "index" : "imei",

            "shard" :0,

            "node" : "hadoop2",

            "accept_data_loss" : true

        }

    }]

}'

想嘗試動態修改分片數量(癡心妄想,只能動態修改副本數):curl -XPUT 'http://192.168.0.12:9200/users/_settings' -d '{"number_of_shards": 3}'
沒法之後嘗試重建索引,將分片數量設爲3,感覺用命令太麻煩了,直接上java方法比較方便:

 /*索引重建遷移大法*/
    private static void indexMigration() throws UnknownHostException {
        String node = "192.168.0.12";
        int port = 9300;
        String cn = "my-application";
​
        Settings settings = Settings.builder()
                .put("cluster.name", cn)//設置ES實例的名稱
                .put("client.transport.sniff", true)// 自動嗅探發現集羣節點
                .build();
​
        TransportClient client = new PreBuiltTransportClient(settings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(node), port));
        log.info("初始化客戶端成功");
​
​
        List<Map<String, Object>> addList = new ArrayList<>();
        //指定一個index和type
        SearchRequestBuilder search = client.prepareSearch("users2").setTypes("type");
        //使用原生排序優化性能
        //search.addSort("_doc", SortOrder.ASC);
        search.addSort("_doc", SortOrder.ASC);
        //設置每批讀取的數據量
        search.setSize(100);
        //默認是查詢所有
        search.setQuery(QueryBuilders.queryStringQuery("*:*"));
        //設置 search context 維護1分鐘的有效期
        search.setScroll(TimeValue.timeValueMinutes(1));
        //獲得首次的查詢結果
        SearchResponse scrollResp = search.get();
        //打印命中數量、
        log.info("命中總數量:" + scrollResp.getHits().getTotalHits());
        int count = 1;
        do {
            log.info("第" + count + "次打印數據:");
            for (SearchHit hit : scrollResp.getHits().getHits()) {
                addList.add(hit.getSource());
            }
            count++;
            //將scorllId循環傳遞
            scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
​
        } while (scrollResp.getHits().
​
                getHits().length != 0);
        //當searchHits的數組爲空的時候結束循環,至此數據全部讀取完畢
        BulkRequestBuilder bulkRequest = client.prepareBulk();
        for (
                int i = 0; i < addList.size(); i++)
​
        {
            bulkRequest.add(client.prepareIndex("users", "type").setSource(addList.get(i)));
            // 每1000條提交一次
            if (i % 1000 == 0) {
                bulkRequest.execute().actionGet();
                bulkRequest = client.prepareBulk();
            }
        }
        bulkRequest.execute().
​
                actionGet();
    }
​
​
    public static void main(String[] args) throws UnknownHostException {
        indexMigration();
    }

 

最後通過新建合適的索引,把原先的數據遷移過來,再重構舊索引,將數據導入回去後,集羣狀態恢復正常。

測試api的時候發現這樣做的話貌似_id被系統設爲自動生成(起初將某些字段同樣給_id賦值,本來是想省一個字段,但是留個心眼在結構裏都把字段寫上了),不過還好當時所有有需要的字段都預留下來了,修改一下方法裏查詢的字段名即可。

重新測試調用api,穩妥的一匹

挺好的shard問題解決方案:

https://www.datadoghq.com/blog/elasticsearch-unassigned-shards/?spm=a2c4e.11153940.blogcont395411.9.4d137dcbEami56

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章