一.Elasticsearch7.x簡介
1.1概述
Elasticsearch官網(wǎng):https://www.elastic.co/cn/products/elasticsearch 。
Elasticsearch是一個基于Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,能夠達到實時、穩(wěn)定、可靠、快速搜索。也可以看做是布式的實時文件存儲,每個字段都能被索引并可被搜索。
目前大多數(shù)公司把Elasticsearch作為elk日志系統(tǒng)中日志數(shù)據(jù)儲存和實時搜索工具。這一部分用戶,他們注重的是數(shù)據(jù)的實時寫入,在大量日志數(shù)據(jù)產(chǎn)生時,不堆積。另一部分公司,把Elasticsearch作為全文搜索工具,一次會在幾千萬上億條數(shù)據(jù)中進行搜索、聚合,對數(shù)據(jù)寫入效率要求不高,注重的是搜索效率。
1.2 什么是全文搜索
什么是全文搜索引擎?
百度百科中的定義:
全文搜索引擎是目前廣泛應用的主流搜索引擎。它的工作原理是計算機索引程序通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現(xiàn)的次數(shù)和位置,當用戶查詢時,檢索程序就根據(jù)事先建立的索引進行查找,并將查找的結果反饋給用戶的檢索方式。這個過程類似于通過字典中的檢索字表查字的過程。
從定義中我們已經(jīng)可以大致了解全文檢索的思路了,為了更詳細的說明,我們先從生活中的數(shù)據(jù)說起。
我們生活中的數(shù)據(jù)總體分為兩種:結構化數(shù)據(jù) 和 非結構化數(shù)據(jù)。
- 結構化數(shù)據(jù): 指具有固定格式或有限長度的數(shù)據(jù),如數(shù)據(jù)庫,元數(shù)據(jù)等。
- 非結構化數(shù)據(jù): 非結構化數(shù)據(jù)又可稱為全文數(shù)據(jù),指不定長或無固定格式的數(shù)據(jù),如郵件,word文檔等。
當然有的地方還會有第三種:半結構化數(shù)據(jù),如XML,HTML等,當根據(jù)需要可按結構化數(shù)據(jù)來處理,也可抽取出純文本按非結構化數(shù)據(jù)來處理。
根據(jù)兩種數(shù)據(jù)分類,搜索也相應的分為兩種:結構化數(shù)據(jù)搜索和非結構化數(shù)據(jù)搜索。
對于結構化數(shù)據(jù),我們一般都是可以通過關系型數(shù)據(jù)庫(mysql,oracle等)的 table 的方式存儲和搜索,也可以建立索引。
對于非結構化數(shù)據(jù),也即對全文數(shù)據(jù)的搜索主要有兩種方法:順序掃描法,全文檢索。
順序掃描:通過文字名稱也可了解到它的大概搜索方式,即按照順序掃描的方式查詢特定的關鍵字。
例如給你一張報紙,讓你找到該報紙中“RNG”的文字在哪些地方出現(xiàn)過。你肯定需要從頭到尾把報紙閱讀掃描一遍然后標記出關鍵字在哪些版塊出現(xiàn)過以及它的出現(xiàn)位置。
這種方式無疑是最耗時的最低效的,如果報紙排版字體小,而且版塊較多甚至有多份報紙,等你掃描完你的眼睛也差不多了。
全文搜索:對非結構化數(shù)據(jù)順序掃描很慢,我們是否可以進行優(yōu)化?把我們的非結構化數(shù)據(jù)想辦法弄得有一定結構不就行了嗎?將非結構化數(shù)據(jù)中的一部分信息提取出來,重新組織,使其變得有一定結構,然后對此有一定結構的數(shù)據(jù)進行搜索,從而達到搜索相對較快的目的。這種方式就構成了全文檢索的基本思路。這部分從非結構化數(shù)據(jù)中提取出的然后重新組織的信息,我們稱之索引。
還以讀報紙為例,我們想關注最近英雄聯(lián)盟S8全球總決賽的新聞,假如都是 RNG 的粉絲,如何快速找到 RNG 新聞的報紙和版塊呢?全文搜索的方式就是,將所有報紙中所有版塊中關鍵字進行提取,如"EDG","RNG","FW","戰(zhàn)隊","英雄聯(lián)盟"等。然后對這些關鍵字建立索引,通過索引我們就可以對應到該關鍵詞出現(xiàn)的報紙和版塊。注意區(qū)別目錄搜索引擎。
1.3 為什么要用全文搜索搜索引擎
為什么要用搜索引擎?我們的所有數(shù)據(jù)在數(shù)據(jù)庫里面都有,而且 Oracle、SQL Server 等數(shù)據(jù)庫里也能提供查詢檢索或者聚類分析功能,直接通過數(shù)據(jù)庫查詢不就可以了嗎?確實,我們大部分的查詢功能都可以通過數(shù)據(jù)庫查詢獲得,如果查詢效率低下,還可以通過建數(shù)據(jù)庫索引,優(yōu)化SQL等方式進行提升效率,甚至通過引入緩存來加快數(shù)據(jù)的返回速度。如果數(shù)據(jù)量更大,就可以分庫分表來分擔查詢壓力。
那為什么還要全文搜索引擎呢?我們主要從以下幾個原因分析:
-
數(shù)據(jù)類型
全文索引搜索支持非結構化數(shù)據(jù)的搜索,可以更好地快速搜索大量存在的任何單詞或單詞組的非結構化文本。
例如 Google,百度類的網(wǎng)站搜索,它們都是根據(jù)網(wǎng)頁中的關鍵字生成索引,我們在搜索的時候輸入關鍵字,它們會將該關鍵字即索引匹配到的所有網(wǎng)頁返回;還有常見的項目中應用日志的搜索等等。對于這些非結構化的數(shù)據(jù)文本,關系型數(shù)據(jù)庫搜索不是能很好的支持。 -
索引的維護
一般傳統(tǒng)數(shù)據(jù)庫,全文檢索都實現(xiàn)的很雞肋,因為一般也沒人用數(shù)據(jù)庫存文本字段。進行全文檢索需要掃描整個表,如果數(shù)據(jù)量大的話即使對SQL的語法優(yōu)化,也收效甚微。建立了索引,但是維護起來也很麻煩,對于 insert 和 update 操作都會重新構建索引。
什么時候使用全文搜索引擎:
- 搜索的數(shù)據(jù)對象是大量的非結構化的文本數(shù)據(jù)。
- 文件記錄量達到數(shù)十萬或數(shù)百萬個甚至更多。
- 支持大量基于交互式文本的查詢。
- 需求非常靈活的全文搜索查詢。
- 對高度相關的搜索結果的有特殊需求,但是沒有可用的關系數(shù)據(jù)庫可以滿足。
- 對不同記錄類型、非文本數(shù)據(jù)操作或安全事務處理的需求相對較少的情況。
1.4 Lucene vs Solr vs ElasticSearch
現(xiàn)在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它們的索引建立都是根據(jù)倒排索引的方式生成索引,何謂倒排索引?
維基百科
倒排索引(英語:Inverted index),也常被稱為反向索引、置入檔案或反向檔案,是一種索引方法,被用來存儲在全文搜索下某個單詞在一個文檔或者一組文檔中的存儲位置的映射。它是文檔檢索系統(tǒng)中最常用的數(shù)據(jù)結構。
Elasticsearch是一個開源(Apache 2許可證),是一個基于Apache Lucene庫構建的RESTful搜索引擎。
Elasticsearch是在Solr之后幾年推出的。它提供了一個分布式,多租戶能力的全文搜索引擎,具有HTTP Web界面(REST)和無架構JSON文檔。Elasticsearch的官方客戶端庫提供Java,Groovy,PHP,Ruby,Perl,Python,.NET和Javascript。
分布式搜索引擎包括可以劃分為分片的索引,并且每個分片可以具有多個副本。每個Elasticsearch節(jié)點都可以有一個或多個分片,其引擎也可以充當協(xié)調器,將操作委派給正確的分片。
Elasticsearch可通過近實時搜索進行擴展。
Solr與Elasticsearch差異清單:
| 特征 | Solr/SolrCloud | Elasticsearch |
|---|---|---|
| 社區(qū)和開發(fā)者 | Apache 軟件基金和社區(qū)支持 | 單一商業(yè)實體及其員工 |
| 節(jié)點發(fā)現(xiàn) | Apache Zookeeper,在大量項目中成熟且經(jīng)過實戰(zhàn)測試 | Zen內置于Elasticsearch本身,需要專用的主節(jié)點才能進行分裂腦保護 |
| 碎片放置 | 本質上是靜態(tài),需要手動工作來遷移分片,從Solr 7開始 - Autoscaling API允許一些動態(tài)操作 | 動態(tài),可以根據(jù)群集狀態(tài)按需移動分片 |
| 高速緩存 | 全局,每個段更改無效 | 每段,更適合動態(tài)更改數(shù)據(jù) |
| 分析引擎性能 | 非常適合精確計算的靜態(tài)數(shù)據(jù) | 結果的準確性取決于數(shù)據(jù)放置 |
| 全文搜索功能 | 基于Lucene的語言分析,多建議,拼寫檢查,豐富的高亮顯示支持 | 基于Lucene的語言分析,單一建議API實現(xiàn),高亮顯示重新計算 |
| DevOps支持 | 尚未完全,但即將到來 | 非常好的API |
| 非平面數(shù)據(jù)處理 | 嵌套文檔和父-子支持 | 嵌套和對象類型的自然支持允許幾乎無限的嵌套和父-子支持 |
| 查詢DSL | JSON(有限),XML(有限)或URL參數(shù) | JSON |
| 索引/收集領導控制 | 領導者安置控制和領導者重新平衡甚至可以節(jié)點上的負載 | 不可能 |
| 機器學習 | 內置 - 在流聚合之上,專注于邏輯回歸和學習排名貢獻模塊 | 商業(yè)功能,專注于異常和異常值以及時間序列數(shù)據(jù) |

1.5 Elasticsearch 7.x 新特性
學習技術棧得看版本,那么 Elasticsearch 7.x 有什么好的特性呢?
ES 7.0 是 2019 年 4 月份發(fā)布的,底層是 Lucene 8.0。其他還有需要了解的是:
- 廢除單個索引下多 Type 的支持
- ES Security 免費使用
- ECK – ES Operator on K8s
- 新功能:New Cluster coordination
- 新功能:完整的 High Level REST Client
- 新功能:Script Score Query
- 性能:默認 Primary Shard 數(shù)從 5 到 1 ,避免 Over Sharding;性能優(yōu)化更快的 Top K
二.Elasticsearch 7.x安裝與啟動(Windows)
2.1 下載 Elasticsearch 7.4.0
下載地址:https://www.elastic.co/cn/downloads/elasticsearch

如圖,下載對應需要的 ES 。我這邊是 Windows,所以直接下載了 Windows的版本。另外 ES 支持 Docker 方式啟動。另外,ES 7.x 不需要本地 JDK 環(huán)境支持:
- ES 5,安裝需要 JDK 8 以上
- ES 6.5,安裝需要 JDK 11 以上
- ES 7.2.1,內置了 JDK 12
下載完后,ES 文件目錄結構如下圖所示:

Elasticsearch 7.4.0 目錄結構如下:
- bin :腳本文件,包括 ES 啟動 & 安裝插件等等
- config : elasticsearch.yml(ES 配置文件)、jvm.options(JVM 配置文件)、日志配置文件等等
- jdk: 內置的 JDK,JAVA_VERSION="12.0.1"
- lib : 類庫
- logs : 日志文件
- modules : ES 所有模塊,包括 X-pack 等
- plugins : ES 已經(jīng)安裝的插件。默認沒有插件
具體看看關鍵的 jvm.options JVM 配置文件,默認配置如下:
-Xms1g
-Xmx1g
ES 默認安裝后設置的堆內存是 1 GB,對于任何業(yè)務來說這個設置肯定是少了。那設置多少?
推薦:如果足夠的內存,也盡量不要 超過 32 GB。即每個節(jié)點內存分配不超過 32 GB。 因為它浪費了內存,降低了 CPU 的性能,還要讓 GC 應對大內存。如果你想保證其安全可靠,設置堆內存為 31 GB 是一個安全的選擇。
上述推薦,理由來自《堆內存:大小和交換編輯》:https://www.elastic.co/guide/cn/elasticsearch/guide/current/heap-sizing.html
2.2 啟動 Elasticsearch 7.4.0
啟動方式很簡單,在 ES 根目錄下面,執(zhí)行啟動腳本文件:
cd elasticsearch-7.4.0/bin
elasticsearch
運行完后,會出現(xiàn)下面的日志:


日志中有兩個信息需要注意:
- 本機環(huán)境是 JDK 8 ,它會提醒后面版本需要 JDK 11 支持。但它是向下兼容的
- 表示本機 ES 啟動成功 [DESKTOP-9U6FM10] started
2.3 驗證是否啟動成功
打開瀏覽器,輸入 http://localhost:9200/ 地址,然后可以得到下面的信息:

{
"name" : "DESKTOP-9U6FM10",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "x35OuAezQiSjHAZaJdzuhg",
"version" : {
"number" : "7.4.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "22e1767283e61a198cb4db791ea66e3f11ab9910",
"build_date" : "2019-09-27T08:36:48.569419Z",
"build_snapshot" : false,
"lucene_version" : "8.2.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
重點幾個關注下即可:
name : 默認啟動的時候指定了 ES 實例名稱,name 為 BYSocketdeMacBook-Pro-2.local
cluster_name : 默認名為 elasticsearch
version :版本信息
同樣通過 http://localhost:9200/_cat/nodes?v 地址,可以看到當前節(jié)點信息,如下:
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1 27 46 6 dilm * DESKTOP-9U6FM10
2.4 單機集群多個 ES 實例安裝
單機多個 ES 實例,形成一個 ES 單機偽集群,啟動腳本如下:
bin/elasticsearch -E node.name=node01 -E cluster.name=bysocket_es_cluster -E path.data=node01_data -d
bin/elasticsearch -E node.name=node02 -E cluster.name=bysocket_es_cluster -E path.data=node02_data -d
bin/elasticsearch -E node.name=node03 -E cluster.name=bysocket_es_cluster -E path.data=node03_data -d
命令簡單解釋如下:
- node.name : ES 節(jié)點名稱,即實例名
- cluster.name : ES 集群名稱
- path.data : 指定了存儲文檔數(shù)據(jù)目錄
執(zhí)行完腳本后,需要等一會 ES 啟動,也可以查看 logs 看看執(zhí)行情況。
打開瀏覽器,輸入 http://localhost:9200/_cat/nodes?v 地址,可以看到啟動情況:node01 為當前 master 節(jié)點

2.5 ElasticSearch7.x—head插件安裝
2.5.1 下載head插件,地址:https://github.com/mobz/elasticsearch-head
2.5.2 解壓到非es安裝目錄的任意目錄
2.5.3 下載并安裝node.js
2.5.4 安裝grunt
elasticsearch-head-master]# npm install -g grunt-cli
elasticsearch-head-master]# npm install
2.5.5 運行
進入head插件解壓目錄,cmd輸入npm install將安裝的grunt安裝到本地,

安裝成功后執(zhí)行grunt server

2.5.6 瀏覽器訪問: http://localhost:9100/

2.5.7 修改es配置文件:elasticsearch.yml
http.cors.enabled: true
http.cors.allow-origin: "*"
2.5.8 重啟es與head插件,再次訪問: http://localhost:9100/

三.Elasticsearch 7.x安裝與啟動(Linux)
在linux下安裝elasticsearch:
- 下載壓縮包, 并解壓
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-linux-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-7.9.3-linux-x86_64.tar.gz.sha512
tar -xzf elasticsearch-7.9.3-linux-x86_64.tar.gz
cd elasticsearch-7.9.3/
- 修改配置文件: $ES_HOME/config/elasticsearch.yml, 主要修改es數(shù)據(jù)路徑和es日志路徑, 已經(jīng)網(wǎng)絡和端口
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /home/esdata
#
# Path to log files:
#
path.logs: /home/log/eslog
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 10.10.1.11
#
# Set a custom port for HTTP:
#
http.port: 9200
- 修改$ES_HOME/config/jvm.options, 根據(jù)機器性能修改es內存
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms2g
-Xmx2g
- 以守護者模式啟動elasticsearch
./bin/elasticsearch -d
- 訪問頁面(ip+默認端口):
http://10.10.1.11:9200
如果能訪問則安裝成功!
在linux下安裝kibana:
1. 下載壓縮包, 并解壓
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.9.3-linux-x86_64.tar.gz
tar -xzf kibana-7.9.3-linux-x86_64.tar.gz
2.修改配置文件 kibana-7.9.3-linux-x86_64/config/kibana.yml, 主要配置elasticsearch相關:
# The URLs of the Elasticsearch instances to use for all your queries.
elasticsearch.hosts: ["http://10.10.1.11:9200"]
# 如果生產(chǎn)環(huán)境es設置了密碼, 使用此配置
elasticsearch.username: "elastic"
elasticsearch.password: "<password>"
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
i18n.locale: "zh-CN"
- 以守護者模式啟動kibana:
./bin/kibana -d
- 訪問頁面(ip+默認端口):
http://10.10.1.11:5601
如果能訪問則安裝成功!
額外配置(根據(jù)機器性能適當調整):
- 設置虛擬內存大小:vim /etc/sysctl.conf, 官方建議設置為此值
vm.max_map_count= 262144
- #禁用內存與硬盤交換 (防止內存不夠,交換到磁盤,這樣會把ES的速度拉下來):vim /etc/sysctl.conf
vm.swappiness = 1
- 設置文件句柄數(shù): vim /etc/security/limits.conf, 可以參考如下配置:
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535
(非必須)配置elasticsearch密碼
- 修改配置文件: $ES_HOME/config/elasticsearch.yml, 并重新啟動es
xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true
- 進入elasticsearch/bin目錄, 執(zhí)行, 按提示修改密碼, 注: 測試發(fā)現(xiàn)只有用戶:elastic擁有全部權限, 其他用戶需要自行配置權限
./elasticsearch-setup-passwords interactive
- 配置完成之后, 所有對elasticsearch的請求, 都需要配置用戶名密碼, 如kibana
四.Elasticsearch文檔、索引和 REST API
索引(Index)、類型(Type)、文檔(Document)
- 索引Index是含有相同屬性的文檔集合。索引在ES中是通過一個名字來識別的,且必須是英文字母小寫,且不含中劃線(-);可類比于 MySQL 中的 database ;在 7.0中,由于類型(Type)的移除,我們可以理解為,一個索引就是一張 table。
- 一個索引中可以定義一個或多個類型Type,文檔必須屬于一個類型;可類比于 MySQL 中的 table;
- 文檔Document是可以被索引的基本數(shù)據(jù)單位。文檔是Elasticsearch中最小的數(shù)據(jù)存儲單位??深惐扔?MySQL 中 一個table 中的一行記錄
注意事項:
從ES6.0開始,官方便不建議一個索引中創(chuàng)建多個類型;在ES7.0中,更是移除了類型(Type)這個概念。為什么呢?
在Elasticsearch索引中,不同類型(Type)中具有相同名稱的字段在內部由相同的Lucene字段支持。一個index中多個Type在Lucene中會有許多問題。具體的可以參考官方說明:Removal of mapping types
更多細節(jié)可以參考: https://mp.weixin.qq.com/s/O8Pvd8OHBDXiBUrGbprmJQ
五.Elasticsearch配置
5.1 ES的集群配置
ES的集群配置(都是修改ES的配置文件elasticsearch.yml)主要分為:主節(jié)點配置和從節(jié)點配置。
配置主節(jié)點jack_master:
# 配置分布式主節(jié)點
# 集群名
cluster.name: jack
# 節(jié)點名
node.name: jack_master
# 是否為主節(jié)點
node.master: true
# 綁定IP
network.host: 127.0.0.1
然后再次解壓ES安裝包到其他目錄,每解壓一個出來就可以配置一個ES的從節(jié)點,比如這里是解壓兩次就可以配置2個從節(jié)點,分別修改它們的配置文件讓它們加入到集群jack中:
配置從節(jié)點jack_slave1:
# 配置從節(jié)點的信息
# 集群名一定要和主節(jié)點所在集群名一致,默認集群按名字匹配
cluster.name: jack
# 節(jié)點名
node.name: jack_slave1
# 綁定IP
network.host: 127.0.0.1
# 默認端口是9200,如果不配置就會和主節(jié)點端口沖突
http.port: 8100
# 用于尋找集群,不加這個配置這個節(jié)點是游離在集群之外的
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
配置從節(jié)點jack_slave2:
# 配置從節(jié)點的信息
# 集群名一定要和主節(jié)點所在集群名一致,默認集群按名字匹配
cluster.name: jack
# 節(jié)點名
node.name: jack_slave2
# 綁定IP
network.host: 127.0.0.1
# 默認端口是9200,如果不配置就會和主節(jié)點端口沖突
http.port: 8200
# 用于尋找集群,不加這個配置這個節(jié)點是游離在集群之外的
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
就照著上面的步驟ES可以輕松實現(xiàn)擴容,啟動的時候注意節(jié)點啟動順序,先主節(jié)點再從節(jié)點
5.2 ES配置
ES有很好的默認值,所以只需要很少的配置,可以使用Cluster Update Settings API在正在運行的群集上更改大多數(shù)設置。主要是指本地的一些配置,借助于配置文件進行配置,主要分為3塊:
elasticsearch.yml,ES的配置文件;
jvm.options,ES的JVM配置文件;
log4j2.properties,ES的日志配置文件;
關于配置文件的路徑,默認是解壓縮包的解壓路徑$ES_HOME/config,但是具體的配置路徑可以通過ES_PATH_CONF環(huán)境變量來改變,比如:
ES_PATH_CONF=/path/to/my/config ./bin/elasticsearch
ES的配置文件是yaml格式,下面是配置data和logs目錄的方法:
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
環(huán)境變量還可以使用${...}這樣的形式配置,比如:
node.name: ${HOSTNAME}
network.host: ${ES_NETWORK_HOST}
ES配置文件中,可配置的參數(shù)有(匯總,來源于網(wǎng)絡):
# es集群名,默認是elasticsearch,es會自動發(fā)現(xiàn)在同一網(wǎng)段下的es,如果在同一網(wǎng)段下有多個集群,就可以用這個屬性來區(qū)分不同的集群
cluster.name: elasticsearch
# 節(jié)點名,默認隨機指定一個name列表中名字,該列表在es的jar包中config文件夾里name.txt文件中,6.4.0版本中好像已經(jīng)沒有這個文件了
node.name: "Franz Kafka"
# 候選資格,表示該節(jié)點是否有資格被選舉成為master,默認是true,es默認集群中的第一臺機器為master,如果這臺機掛了就會重新選舉master
node.master: true
# 表示該節(jié)點是否存儲索引數(shù)據(jù),默認為true
node.data: true
# 設置索引分片個數(shù),默認為5
index.number_of_shards: 5
# 設置索引副本個數(shù),默認為1
index.number_of_replicas: 1
# 設置ES配置文件的存儲路徑,默認是es根目錄下的config文件夾下
path.conf: /path/to/conf
# 設置索引數(shù)據(jù)的存儲路徑,默認是es根目錄下的data文件夾下,可以設置多個存儲路徑,用逗號隔開,例:path.data: /path/to/data1,/path/to/data2
path.data: /path/to/data
# 設置臨時文件的存儲路徑,默認是es根目錄下的work文件夾
path.work: /path/to/work
# 設置日志文件的存儲路徑,默認是es根目錄下的logs文件夾
path.logs: /path/to/logs
# 設置插件的存放路徑,默認是es根目錄下的plugins文件夾
path.plugins: /path/to/plugins
# 設置ES可以是否可以鎖定內存,因為當jvm開始swapping時es的效率會降低,所以要保證它不swap,可以把ES_MIN_MEM和ES_MAX_MEM兩個環(huán)境變量設置成同一個值,并且保證機器有足夠的內存分配給es。同時也要允許ES的進程可以鎖住內存,linux下可以通過`ulimit -l unlimited`命令
bootstrap.mlockall: true
# 設置綁定的ip地址,可以是ipv4或ipv6的,默認為0.0.0.0
network.bind_host: 192.168.0.1
# 設置其它節(jié)點和該節(jié)點交互的ip地址(真實IP),如果不設置它會自動判斷
network.publish_host: 192.168.0.1
# 這個參數(shù)是用來同時設置bind_host和publish_host上面兩個參數(shù)
network.host: 192.168.0.1
# 設置節(jié)點間交互的tcp端口,默認是9300
transport.tcp.port: 9300
# 設置是否壓縮tcp傳輸時的數(shù)據(jù),默認為false,不壓縮
transport.tcp.compress: true
# 設置對外服務的http端口,默認為9200
http.port: 9200
# 設置內容的最大容量,默認100mb
http.max_content_length: 100mb
# 是否使用http協(xié)議對外提供服務,默認為true,開啟
http.enabled: false
# gateway的類型,默認為local即為本地文件系統(tǒng),可以設置為本地文件系統(tǒng),分布式文件系統(tǒng),hadoop的HDFS,和amazon的s3服務器,其它文件系統(tǒng)的設置方法下次再詳細說
gateway.type: local
# 設置集群中N個節(jié)點啟動時進行數(shù)據(jù)恢復,默認為1
gateway.recover_after_nodes: 1
# 設置初始化數(shù)據(jù)恢復進程的超時時間,默認是5分鐘
gateway.recover_after_time: 5m
# 設置這個集群中節(jié)點的數(shù)量,默認為2,一旦這N個節(jié)點啟動,就會立即進行數(shù)據(jù)恢復
gateway.expected_nodes: 2
# 初始化數(shù)據(jù)恢復時,并發(fā)恢復線程的個數(shù),默認為4
cluster.routing.allocation.node_initial_primaries_recoveries: 4
# 添加刪除節(jié)點或負載均衡時并發(fā)恢復線程的個數(shù),默認為4
cluster.routing.allocation.node_concurrent_recoveries: 2
# 設置數(shù)據(jù)恢復時限制的帶寬,如入100mb,默認為0,即無限制
indices.recovery.max_size_per_sec: 0
# 來限制從其它分片恢復數(shù)據(jù)時最大同時打開并發(fā)流的個數(shù),默認為5
indices.recovery.concurrent_streams: 5
# 設置這個參數(shù)來保證集群中的節(jié)點可以知道其它N個有master資格的節(jié)點。默認為1,對于大的集群來說,可以設置大一點的值(2-4)
discovery.zen.minimum_master_nodes: 1
# 設置集群中自動發(fā)現(xiàn)其它節(jié)點時ping連接超時時間,默認為3秒,對于比較差的網(wǎng)絡環(huán)境可以高點的值來防止自動發(fā)現(xiàn)時出錯
discovery.zen.ping.timeout: 3s
# 設置是否打開多播發(fā)現(xiàn)節(jié)點,默認是true
discovery.zen.ping.multicast.enabled: false
# 設置集群中master節(jié)點的初始列表,可以通過這些節(jié)點來自動發(fā)現(xiàn)新加入集群的節(jié)點
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
5.3 ES的JVM配置
ES的java虛擬機設置,很少需要手動配置,如果需要改動,絕大部分是改動堆的大小,設置JVM首選方式是配置jvm.options文件,這個配置文件包含了一系列分隔線分隔的JVM參數(shù),使用的是一種特殊的語法,具體規(guī)則如下:
僅包含空格的行將被忽略;
以#開頭的行被視作注釋;
以-開頭的行被視作JVM選項,這個選項獨立于JVM而應用,如-Xmx2g;
以數(shù)字開頭后面接-:符號的,也被視作JVM選項,但僅在JVM的版本大于等于這個數(shù)字時才使用,如8-:-Xmx2g(大于等于JDK8版本才適用);
以數(shù)字開頭后面接:-符號的,也被視作JVM選項,但僅在JVM版本和數(shù)字相同時才適用,如8:-Xmx2g(僅適用于JDK8);
以數(shù)字開頭后接-數(shù)字:的,也被視作JVM想象,但僅在JVM版本在這兩個數(shù)字區(qū)間內,如8-9:-Xmx2g;
除此之外的所有行都不生效;
5.4 ES的安全配置
ES中有些配置是敏感的,僅通過系統(tǒng)文件權限來保護是不夠的,為此,Elasticsearch提供了一個密鑰庫和elasticsearch-keystore工具來管理密鑰庫中的設置。這些設置就像elasticsearch.yml中的常規(guī)配置一樣,需要在集群中的每個節(jié)點進行指定,目前,所有安全設置都是基于特定于節(jié)點的設置,每個節(jié)點上的值必須相同。
5.5 ES的日志配置
ES采用log4j 2作日志管理,log4j 2可以使用log4j2.properties文件進行配置,ES就暴露出三個屬性:{sys:es.logs.cluster_name}(解析為集群名,在默認配置中用作日志文件名的前綴)和${sys:es.logs.node_name}(如果通過node.name顯式的設置了節(jié)點名稱,將解析為節(jié)點名),可以在配置文件中引用來確定日志文件的位置。
加設置ES的根目錄是/var/log/elasticsearch,集群名為production,下面是ES中l(wèi)og4j 2的部分配置:
# 配置RollingFile的附加器
appender.rolling.type = RollingFile
appender.rolling.name = rolling
# %ES_Home%/節(jié)點名.log就是日志文件的路徑和名字,即/var/log/elasticsearch/production.log
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
# 滾動日志到/var/log/elasticsearch/production-yyyy-MM-dd-i.log,日志將在每個卷上壓縮,i遞增
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.policies.type = Policies
# 使用基于時間的滾動策略
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 每1天滾動日志
appender.rolling.policies.time.interval = 1
# 在日界上對齊卷(而不是每隔二十四小時滾動)
appender.rolling.policies.time.modulate = true
# 使用基于大小的滾動策略
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
# 256 MB后滾動日志
appender.rolling.policies.size.size = 256MB
# 滾動日志時使用刪除操作
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.fileIndex = nomax
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
# 僅刪除與文件模式匹配的日志
appender.rolling.strategy.action.condition.type = IfFileName
# 該模式僅刪除主日志
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
# 僅在我們累積了太多壓縮日志時才刪除
appender.rolling.strategy.action.condition.nested_condition.type = IfAccumulatedFileSize
# 壓縮日志的大小條件為2 GB
appender.rolling.strategy.action.condition.nested_condition.exceeds = 2GB
【注意】可以使用.gz替換appender.rolling.filePattern屬性中的.zip(使用zip格式壓縮滾動日志),如果刪除.gz擴展名,則日志將不會在滾動時進行壓縮。
如果想指定時間段內保留日志文件,可以使用帶有刪除操作的翻轉策略。
# 配置DefaultRolloverStrategy
appender.rolling.strategy.type = DefaultRolloverStrategy
# 配置刪除操作以處理翻轉
appender.rolling.strategy.action.type = Delete
# Elasticsearch日志的基本路徑
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
# 處理翻轉時應用的條件
appender.rolling.strategy.action.condition.type = IfFileName
# 從基本路徑中刪除文件(和全局${sys:es.logs.cluster_name}-*匹配的),這只需要刪除已滾動的Elasticsearch日志,但不能刪除已棄用和慢速日志
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
# 應用于與glob匹配的文件的嵌套條件
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
# 保留日志七天
appender.rolling.strategy.action.condition.nested_condition.age = 7D
六. ElasticSearch的基本CRUD和postman調用一些常用的api
- ES是面向文檔的,文檔中存儲的數(shù)據(jù)結構,與面向對象的數(shù)據(jù)結構是一樣的,基于這種文檔數(shù)據(jù)結構,es可以提供復雜的索引,全文檢索,分析聚合等功能
- es的document用json數(shù)據(jù)格式來表達.
es提供了一套api,叫做cat api,可以查看es中各種各樣的數(shù)據(jù):
1.查看集群的健康狀態(tài):get請求: http://localhost:9200/_cat/health?v
2.快速查看有那些索引;get請求:http://localhost:9200/_cat/indices
-
3.簡單的索引操作:
添加:PUT請求: http://localhost:9200/cyytest/

- 4.刪除索引:DELETE: http://localhost:9200/cyytest/

- 5.創(chuàng)建文檔: POST,article:就是文檔name


_id是由系統(tǒng)自動生成的,在添加的時候可以加在請求路徑的后面
- 6.查詢文檔 GET方式: http://localhost:9200/cyytest/article/2

-
7.替換文檔內容-POST(修改body中的內容即可) :http://localhost:9200/cyytest/article/2
1571565010556.png
- 8.修改文檔內容 -POST: http://localhost:9200/cyytest/article/2/_update
1571565256031.png
七. SpringBoot 整合 es
創(chuàng)建 springboot 項目
首先創(chuàng)建一個 springboot 項目,然后引入high level client的依賴,pom 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cyy.es</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.0</elasticsearch.version>
</properties>
<!--注意:如果使用了parent那么需要在此定義es版本號,因為spring-boot-start-parent中已經(jīng)定義了es相關依賴的版本號
,high-level-client中的部分依賴會被覆蓋成低版本的,導出出現(xiàn)莫名其妙的錯誤-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
<!--<!– https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-client –>-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意:這里有一個依賴的大坑,要注意!
如果定義了,就必須在中指定部分依賴的版本,否則會因為依賴版本不對出現(xiàn)各種莫名其妙的錯誤,上面注釋中已經(jīng)指出。
創(chuàng)建 util/EsUtil.java 工具類
主要功能函數(shù)如下:
預創(chuàng)建 index
雖然 es 在插入數(shù)據(jù)時會自動根據(jù)字段類型來創(chuàng)建字段定義,但是自動創(chuàng)建并不總是和需要相符的,比如想讓某個字段不分詞,或者使用其他的分詞器。所以在代碼中先判斷 index(es7 中已經(jīng)廢棄了 mapping,也就是一個 index 相當于一個表)是否存在,如果不存在就創(chuàng)建 index.
主要代碼如下:
//被@PostConstruct注釋的方法將會在對應類注入到Spring后調用,確保index的生成
@PostConstruct
public void init() {
try {
if (client != null) {
client.close();
}
client = new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, scheme)));
if (this.indexExist(INDEX_NAME)) {
return;
}
CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);
request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2));
request.mapping(CREATE_INDEX, XContentType.JSON);
CreateIndexResponse res = client.indices().create(request, RequestOptions.DEFAULT);
if (!res.isAcknowledged()) {
throw new RuntimeException("初始化失敗");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
插入或者更新一個對象
通過指定 id,如果此 id 存在那么就是更新,否則是插入。
public void insertOrUpdateOne(String index, EsEntity entity) {
IndexRequest request = new IndexRequest(index);
request.id(entity.getId());
request.source(JSON.toJSONString(entity.getData()), XContentType.JSON);
try {
client.index(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
批量插入
high level client 提供了方便的批量操作接口,如下所示:
public void insertBatch(String index, List<EsEntity> list) {
BulkRequest request = new BulkRequest();
list.forEach(item -> request.add(new IndexRequest(index).id(item.getId())
.source(JSON.toJSONString(item.getData()), XContentType.JSON)));
try {
client.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
批量刪除
和上面一樣同樣用到了BulkRequest
public <T> void deleteBatch(String index, Collection<T> idList) {
BulkRequest request = new BulkRequest();
idList.forEach(item -> request.add(new DeleteRequest(index, item.toString())));
try {
client.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
搜索
通過構建SearchSourceBuilder查詢參數(shù)
public <T> List<T> search(String index, SearchSourceBuilder builder, Class<T> c) {
SearchRequest request = new SearchRequest(index);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
List<T> res = new ArrayList<>(hits.length);
for (SearchHit hit : hits) {
res.add(JSON.parseObject(hit.getSourceAsString(), c));
}
return res;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
delete by query
es 插入數(shù)據(jù)容易,刪除就比較麻煩了,特別是根據(jù)條件刪除。
public void deleteByQuery(String index, QueryBuilder builder) {
DeleteByQueryRequest request = new DeleteByQueryRequest(index);
request.setQuery(builder);
//設置批量操作數(shù)量,最大為10000
request.setBatchSize(10000);
request.setConflicts("proceed");
try {
client.deleteByQuery(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
可通過測試類com.fanxb.esdemo.service.BookServiceTest查看運行結果。
八. Elasticsearch Top5典型應用場景
8.1 記錄和日志分析
對于熟悉Elasticsearch的人來說,這個應該不足為奇。圍繞Elasticsearch構建的生態(tài)系統(tǒng)使其成為最容易實施和擴展日志記錄解決方案之一。我們平臺上的許多用戶都沒有什么不同,他們利用這一點來將日志記錄添加到他們的主要用例中,或者將我們純粹用于日志記錄。
從Beats,Logstash到Ingest Nodes,Elasticsearch為您提供了大量的選項,可以在任何地方獲取數(shù)據(jù)并將其索引化。然后,使用Kibana工具使您能夠創(chuàng)建豐富的儀表板和分析,而Curator使得您自動化管理索引的生命周期。
8.2 采集和組合公共數(shù)據(jù)
與日志數(shù)據(jù)一樣,Elastic Stack擁有大量工具,可以輕松抓取和索引遠程數(shù)據(jù)。此外,與大多數(shù)文檔存儲一樣,非嚴格的模式使Elasticsearch可以靈活地接收多個不同的數(shù)據(jù)源,并能使得這些數(shù)據(jù)可以管理和搜索。
您可以查看的一個很酷的例子是我們的Twitter連接器(如下圖所示),它允許您設置在Twitter上看到的主題標簽,然后采集這些主題標簽的相關推文并在Kibana中進行分析。我們在核心Elastic Stack組件上構建了該產(chǎn)品,并添加了一些額外的部件以幫助它擴展。
8.3 全文搜索
毫無疑問,作為Elasticsearch的核心功能,全文搜索在此列表中占據(jù)重要位置。令人驚訝的是,我們的客戶群中的全文檢索的應用遠遠超出了傳統(tǒng)的企業(yè)搜索或電子商務。
從欺詐檢測/安全到協(xié)作等,我們的用戶已經(jīng)證明Elasticsearch的搜索功能強大,靈活,并且包含大量工具以使搜索更容易; Elasticsearch有自己的查詢DSL、內置的自動補全功能等等。
8.4 事件數(shù)據(jù)和指標
Elasticsearch還可以很好地處理時間序列數(shù)據(jù),如指標(metrics )和應用程序事件。這是另一個巨大的Beats生態(tài)系統(tǒng)允許您輕松獲取常見應用程序數(shù)據(jù)的區(qū)域。無論您使用何種技術,Elasticsearch都有很好的機會獲取開箱即用的指標和事件…,添加該功能非常簡單
8.5 數(shù)據(jù)可視化
憑借大量的圖表選項,地理數(shù)據(jù)的平鋪服務和時間序列數(shù)據(jù)的TimeLion,Kibana是一款功能強大且易于使用的可視化工具。對于上面的每個用例,Kibana都會處理一些可視化組件。
一旦您對各種數(shù)據(jù)提取工具感到滿意,您就會發(fā)現(xiàn)Elasticsearch + Kibana將成為您可視化數(shù)據(jù)的首選工具。
雖然并非每個用例都是如此,但這Top5是我們服務中統(tǒng)計出的最典型應用。 Elasticsearch和Elastic Stack的其他部分已被證明是非常通用的,正如您在上面所看到的,有多種方法可以將Elasticsearch集成到您今天所做的事情中并獲得額外的洞察力。對我而言,這是Elasticsearch最酷的部分,它能夠增強您已經(jīng)使用的技術,而不僅僅是另一個數(shù)據(jù)庫來存儲您的數(shù)據(jù)。

