Elasticsearch 實戰案例(索引切分、模板、別名、數據遷移)

背景

基於ELK搭建的日誌平臺,前期匆忙建設過程中一些參數和設計未做過多的考慮,上線後就需要不斷根據實際情況做調整,而一些調整限於ELK的一些特性,一旦操作不當就會出現丟數據、數據寫入異常、數據查不到等情況。

因此如何在這種背景下,做到對使用方無感知的動態調整是我們所要實現的目標。所以本文更加註重實踐而非深層次的理論講解,有興趣深入瞭解的可以自行研習。

總體架構

5401760-1834f9c5d29a84dc.png
image.png

CASES

CASE1:按日/月生成索引

創建的nginx access_log索引,開始採集2周後,數據達到25G+(number_of_replicas=1,因此總體數據超過50G),如果不進行索引拆分,該索引將越來越大,最終會嚴重影響查詢效率,並且一旦出現索引損壞造成的風險也更大。

通過配置logstash ouput 插件實現按照日期生成新索引:

output {
 elasticsearch {
   hosts => ["192.168.0.1:9200"]
   index => "php-nginx-log-%{+YYYY.MM.DD}" #按照天生成索引
 }
}

通過我們的配置,目前會存在2個index,分別爲歷史的php-nginx-log索引和以php-nginx-log.2019-01-15索引。

CASE2:Kibana查詢所有數據

由於目前我們的索引不再是指定的具體索引,還是一類按照事先約定的命名格式索引集合,這時我們想要能夠在Kibana查詢數據時不受影響,能夠正常查詢到數據,此時主要有兩種解決方式:

1、更改Kibana的Create index pattern,使用通配符關聯出所有index

5401760-23a2d8e1e9a061f0.png
image.png

2、使用index aliases,詳情:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/indices-templates.html

Elasticsearch的別名,就類似數據庫的視圖,別名不僅僅可以關聯一個索引,它能聚合多個索引,下文還會提到別名的更重要的特性。

通過別名的方式是更加建議的方式。

POST /_aliases
{
    "actions" : [
        { "add" : { "index" : "new_index1", "alias" : "alias1" } }
    ]
}

說明:這裏使用Elasticsearch的REST API進行設置,具體詳情參考官網:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/docs.html ,下文中的類似代碼塊都是此類調用。

CASE3:通過模板創建Index

創建index後,如果未指定具體mapping,則在插入具體doc數據時,會自動生成,具體數據字段的數據類型Elasticsearch會做一定的動態識別,但是大部分都將以string定義,這種情況下我們在使用數據時 ,就會出現一些不便,如 Kibana一些函數必須是整型類型、ip類型的字段纔可以使用,另外全部默認爲string類型會導致查詢效率的低下和存儲容量的浪費。

這時就需要我們去指定index的mapping,而很重要的一點:mapping中的filed一點指定後(無論是默認生成還是手動聲明)就無法進行update filed操作,如果要修改通常只能進行create 新的index。因此我們往往會在index寫入數據前就創建好index的mapping,如下:

PUT new_index1
{
    "settings" : {
        "number_of_shards" : 1
    },
    "mappings" : {
        "_doc" : {
            "properties" : {
                "field1" : { "type" : "text" }
            }
        }
    }
}

而通過CASE1中,已經說明了我們的index都是由Logstash按照日期自動創建的,因此手動通過API的方式無法滿足我們的需求,這時我們就需要使用Elasticsearch的template特性:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/indices-templates.html

創建template:

PUT _template/template_nginx_log
{
  "index_patterns": ["php-nginx-log*"],
  "settings": {
    "number_of_shards": "5",
    "number_of_replicas": "1"
  },
  "aliases": {
    "php-nginx-log": {}
  },
  "mapping": {
    "doc": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "geoip": {
          "type": "object"
        },
        "geoip_city_name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "geoip_continent_code": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "geoip_country_code2": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
       
        "user_device_os_name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

具體說明:

  • index_patterns:指定index匹配表達式,這個特性十分重要,如果配置爲 ”php-nginx-log*“,則所有以php-nginx-log爲前綴的索引都將自動使用該template進行索引創建,而不需要特殊指定

  • aliases:爲索引指定一個別名,同樣的,通過該配置就能實現我們前面提到的問題,讓按照日期創建的新index能夠被正確的查詢到

CASE4:原index數據遷移(mapping有修改)

1)CASE3開頭的時候提到過,需要按照固定的mapping創建index,來達到生成的index能使用規範的數據類型的目的,而歷史index中數據想要修改mapping只能重新創建,這時我們通常使用Elasticsearch的reindex特性:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/docs-reindex.html

POST _reindex?slices=5&refresh
{
  "source": {
    "index": "php-nginx-log-2019.01",
    "size": 10000
  },
  "dest": {
    "index": "php-nginx-log-2019.01.15"
  }
    
}

說明:

  • 默認情況下,_reindex使用1000進行批量操作,您可以在source中調整batch_size,如上面設置爲了1萬

  • Reindex支持Sliced Scroll以並行化重建索引過程。 這種並行化可以提高效率,並提供一種方便的方法將請求分解爲更小的部分,如上面設置爲了slices=5

    • 1)slices大小的設置可以手動指定,或者設置slices設置爲auto,auto的含義是:針對單索引,slices大小=分片數;針對多索引,slices=分片的最小值。

    • 2)當slices的數量等於索引中的分片數量時,查詢性能最高效。slices大小大於分片數,非但不會提升效率,反而會增加開銷。

    • 3)如果這個slices數字很大(例如500),建議選擇一個較低的數字,因爲過大的slices 會影響性能。

  • 如果要進行大量批量導入,請考慮通過設置index.number_of_replicas來禁用副本:0。

    • 主要原因在於:複製文檔時,將整個文檔發送到副本節點,並逐字重複索引過程。這意味着每個副本都將執行分析,索引和潛在合併過程。

    • 相反,如果使用零副本進行索引,然後在提取完成時啓用副本,則恢復過程本質上是逐字節的網絡傳輸。 這比複製索引過程更有效。

2)我們要保證新舊index的數據平滑遷移對用戶無感知,此時可以使用前文提到的alias,流程爲:

1 . 就index使用alias,數據使用方通過alias查詢數據
2 . reindex生成的新index不要創建別名,進行數據reindex操作
3 . 待數據複製完成後,調用remove+add alias接口,該操作爲原子操作,可以保證數據無縫遷移,具體代碼如下:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/indices-aliases.html

POST /_aliases
{
    "actions" : [
        { "remove" : { "index" : "test1", "alias" : "alias1" } },
        { "add" : { "index" : "test2", "alias" : "alias1" } }
    ]
}

總結

至此我們就總結完了一些Elasticsearch及ELK架構下常用CASE,通過合理的使用組件的特性,來滿足我們的業務需求。

後面我們還將總結一些Logstash的經典CASE。


歡迎關注 高廣超的簡書博客 與 收藏文章 !
歡迎關注 頭條號:互聯網技術棧

個人介紹:

高廣超:多年一線互聯網研發與架構設計經驗,擅長設計與落地高可用、高性能、可擴展的互聯網架構。目前從事大數據相關研發與架構工作。

本文首發在 高廣超的簡書博客 轉載請註明!

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