3 - 基於ELK的ElasticSearch 7.8.x技術整理 - 高階篇( 偏理論 )

語言: CN / TW / HK

4、ES高階篇

4.1、叢集部署

  • 叢集的意思:就是將多個節點歸為一體罷了( 這個整體就有一個指定的名字了 )

4.1.1、window中部署叢集 - 瞭解即可

  • 把下載好的window版的ES中的data資料夾、logs資料夾下的所有的檔案刪掉,然後拷貝成三份,對檔案重新命名

  • 修改node-1001節點的config/elasticsearch.yml配置檔案

  • 這個配置檔案裡面有原生的配置資訊,感興趣的可以檢視,因為現在要做的配置資訊都在原生的配置資訊裡,只是被註釋掉了而已,當然:沒興趣的,直接全選刪掉,然後做如下配置

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 叢集名稱  注意:是把多個節點歸為一個整體,所以這個叢集名字就是各節點歸為一體之後的名字
# 因此:各個節點中這個叢集名字也就要一樣了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 節點名稱  在一個叢集中,這個名字要全域性唯一
node.name: node-1001
# 是否有資格成為主機節點
node.master: true
# 是否是資料節點
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 當前節點的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 當前節點的埠號
http.port: 1001
# 當前節點的通訊埠( 監聽埠 )
transport.tcp.port: 9301
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
  • 修改node-1002節點的config/elasticsearch.yml配置檔案

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 叢集名稱  注意:是把多個節點歸為一個整體,所以這個叢集名字就是各節點歸為一體之後的名字
# 因此:各個節點中這個叢集名字也就要一樣了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 節點名稱  在一個叢集中,這個名字要全域性唯一
node.name: node-1002
# 是否是主機節點
node.master: true
# 是否是資料節點
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 當前節點的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 當前節點的埠號
http.port: 1002
# 當前節點的通訊埠( 監聽埠 )
transport.tcp.port: 9302
# 當前節點不知道叢集中另外節點是哪些澀,所以配置,讓當前節點能夠找到其他節點
discovery.seed_hosts: ["127.0.0.1:9301"]
# ping請求呼叫超時時間,但同時也是選主節點的delay time
discovery.zen.fd.ping_timeout: 1m
# 重試次數,防止GC[ 垃圾回收 ]節點不響應被剔除
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"

修改node-1003節點的config/elasticsearch.yml配置檔案

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
# 叢集名稱  注意:是把多個節點歸為一個整體,所以這個叢集名字就是各節點歸為一體之後的名字
# 因此:各個節點中這個叢集名字也就要一樣了
cluster.name: es-colony
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
# 節點名稱  在一個叢集中,這個名字要全域性唯一
node.name: node-1003
# 是否是主機節點
node.master: true
# 是否是資料節點
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 當前節點的ip地址
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
# 當前節點的埠號
http.port: 1003
# 當前節點的通訊埠( 監聽埠 )
transport.tcp.port: 9303
# 當前節點不知道叢集中另外節點是哪些澀,所以配置,讓當前節點能夠找到其他節點
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302"]
# ping請求呼叫超時時間,但同時也是選主節點的delay time
discovery.zen.fd.ping_timeout: 1m
# 重試次數,防止GC[ 垃圾回收 ]節點不響應被剔除
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"

依次啟動1、2、3節點的bin/elasticsearch.bat即可啟動叢集

用postman測試叢集

http://localhost:1001/_cluster/health  # 請求方式:get

# 相應內容
{
    "cluster_name": "es-colony",
    "status": "green",  # 重點檢視位置 狀態顏色
    "timed_out": false,
    "number_of_nodes": 3,	# 重點檢視位置	叢集中的節點數量
    "number_of_data_nodes": 3,		# 重點檢視位置	叢集中的資料節點數量
    "active_primary_shards": 0,
    "active_shards": 0,
    "relocating_shards": 0,
    "initializing_shards": 0,
    "unassigned_shards": 0,
    "delayed_unassigned_shards": 0,
    "number_of_pending_tasks": 0,
    "number_of_in_flight_fetch": 0,
    "task_max_waiting_in_queue_millis": 0,
    "active_shards_percent_as_number": 100.0
}

status欄位顏色表示:當前叢集在總體上是否工作正常。它的三種顏色含義如下:

  1. green:所有的主分片和副本分片都正常執行。
  2. yellow:所有的主分片都正常執行,但不是所有的副本分片都正常執行。
  3. red:有主分片沒能正常執行

附加內容:一些配置說明,下面的一些配置目前有些人可能並沒有遇到,但是在這裡留個印象吧,知道個大概和怎麼去找就行了

官網地址: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules.html

1、主節點 [ host區域 ]:

cluster.name: elastics   #定義叢集名稱所有節點統一配置
node.name: es-0   # 節點名稱自定義
node.master: true  # 主節點,資料節點設定為 false
node.data: false   # 資料節點設定為true
path.data: /home/es/data   
path.logs: /home/es/logs   
bootstrap.mlockall: true        #啟動時鎖定記憶體
network.publish_host: es-0
network.bind_host: es-0
http.port: 9200
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping_timeout: 120s
discovery.zen.minimum_master_nodes: 2 #至少要發現叢集可做master的節點數,
client.transport.ping_timeout: 60s
discovery.zen.ping.unicast.hosts: ["es-0","es-1", "es-2","es-7","es-8","es-4","es-5","es-6"] 
discovery.zen.fd.ping_timeout: 120s
discovery.zen.fd.ping_retries: 6
discovery.zen.fd.ping_interval: 30s
cluster.routing.allocation.disk.watermark.low: 100GB
cluster.routing.allocation.disk.watermark.high: 50GB
node.zone: hot                     #磁碟區域,分為hot和stale,做冷熱分離
script.inline: true
script.indexed: true 
cluster.routing.allocation.same_shard.host: true
threadpool.bulk.type: fixed  
threadpool.bulk.size: 32 
threadpool.bulk.queue_size: 100
threadpool.search.type: fixed  
threadpool.search.size: 49 
threadpool.search.queue_size: 10000
script.engine.groovy.inline.aggs: on
index.search.slowlog.threshold.query.warn: 20s
index.search.slowlog.threshold.query.info: 10s
index.search.slowlog.threshold.query.debug: 4s
index.search.slowlog.threshold.query.trace: 1s
index.search.slowlog.threshold.fetch.warn: 2s
index.search.slowlog.threshold.fetch.info: 1600ms
index.search.slowlog.threshold.fetch.debug: 500ms
index.search.slowlog.threshold.fetch.trace: 200ms
index.indexing.slowlog.threshold.index.warn: 20s
index.indexing.slowlog.threshold.index.info: 10s
index.indexing.slowlog.threshold.index.debug: 4s
index.indexing.slowlog.threshold.index.trace: 1s
indices.fielddata.cache.size: 20%
indices.fielddata.cache.expire: "48h"
indices.cache.filter.size: 10%
index.search.slowlog.level: WARN

資料節點 [ stale區域 ]

cluster.name: elastics  # 叢集名字
node.name: es-1     #節點名稱
node.master: false      # 不作為主節點,只儲存資料
node.data: true         # 做為資料節點
path.data: /data1/es-data,/data2/es-data,/data3/es-data  # 儲存目錄,可配置多個磁碟
path.logs: /opt/es/logs     # 日誌目錄
bootstrap.mlockall: true    # 啟動時鎖定記憶體
network.publish_host: es-1  # 繫結網絡卡
network.bind_host: es-1     # 繫結網絡卡
http.port: 9200             # http埠
discovery.zen.ping.multicast.enabled: false       # 禁用多播,誇網段不能用多播
discovery.zen.ping_timeout: 120s                  
discovery.zen.minimum_master_nodes: 2             # 至少要發現叢集可做master的節點數
client.transport.ping_timeout: 60s
discovery.zen.ping.unicast.hosts: ["es-0","es-1", "es-2","es-7","es-8","es-4","es-5","es-6"]     # 叢集自動發現

# fd 是 fault detection 
# discovery.zen.ping_timeout 僅在加入或者選舉 master 主節點的時候才起作用;
# discovery.zen.fd.ping_timeout 在穩定執行的叢集中,master檢測所有節點,以及節點檢測 master是否暢通時長期有用
discovery.zen.fd.ping_timeout: 120s                # 超時時間(根據實際情況調整)
discovery.zen.fd.ping_retries: 6                   # 重試次數,防止GC[垃圾回收]節點不響應被剔除
discovery.zen.fd.ping_interval: 30s                # 執行間隔

# 控制磁碟使用的低水位。預設為85%,意味著如果節點磁碟使用超過85%,則ES不允許在分配新的分片。當配置具體的大小如100MB時,表示如果磁碟空間小於100MB不允許分配分片
cluster.routing.allocation.disk.watermark.low: 100GB      #磁碟限額

# 控制磁碟使用的高水位。預設為90%,意味著如果磁碟空間使用高於90%時,ES將嘗試分配分片到其他節點。上述兩個配置可以使用API動態更新,ES每隔30s獲取一次磁碟的使用資訊,該值可以通過cluster.info.update.interval來設定
cluster.routing.allocation.disk.watermark.high: 50GB      # 磁碟最低限額

node.zone: stale                      # 磁碟區域,分為hot和stale,做冷熱分離
script.inline: true                   # 支援指令碼
script.indexed: true 
cluster.routing.allocation.same_shard.host: true    #一臺機器部署多個節點時防止一個分配到一臺機器上,宕機導致丟失資料
threadpool.bulk.type: fixed    # 以下6行為設定thread_pool
threadpool.bulk.size: 32 
threadpool.bulk.queue_size: 100
threadpool.search.type: fixed  
threadpool.search.size: 49 
threadpool.search.queue_size: 10000
script.engine.groovy.inline.aggs: on
index.search.slowlog.threshold.query.warn: 20s    # 以下為配置慢查詢和慢索引的時間
index.search.slowlog.threshold.query.info: 10s
index.search.slowlog.threshold.query.debug: 4s
index.search.slowlog.threshold.query.trace: 1s
index.search.slowlog.threshold.fetch.warn: 2s
index.search.slowlog.threshold.fetch.info: 1600ms
index.search.slowlog.threshold.fetch.debug: 500ms
index.search.slowlog.threshold.fetch.trace: 200ms
index.indexing.slowlog.threshold.index.warn: 20s
index.indexing.slowlog.threshold.index.info: 10s
index.indexing.slowlog.threshold.index.debug: 4s
index.indexing.slowlog.threshold.index.trace: 1s

4.1.2、linux中部署ES

4.1.2.1、部署單機ES

  • 準備工作
    • 1、下載linux版的ES,自行百度進行下載,老規矩,我的版本是:7.8.0
    • 2、將下載好的linux版ES放到自己的伺服器中去

  • 解壓檔案:命令 tar zxvf elasticsearch-7.8.0-linux-x86_64.tar.gz

  • 對檔案重新命名: 命令 mv elasticsearch-7.8.0 es

  • 建立使用者

  • 因為安全問題, Elasticsearch 不允許 root 使用者直接執行,所以要建立新使用者,在 root 使用者中建立新使用者

點選檢視程式碼
useradd es		# 新增 es 使用者
passwd es		# 為 es 使用者設定密碼,輸入此命令後,輸入自己想設定的ES密碼即可
userdel -r es	# 如果錯了,可以把使用者刪除了再重新加
chown -R es:es /opt/install/es		# 檔案授權		注意:/opt/install/es 改成自己的ES存放路徑即可
  • 修改 config/elasticsearch.yml 配置檔案
點選檢視程式碼
# 在elasticsearch.yml檔案末尾加入如下配置
cluster.name: elasticsearch
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1"]

最後:儲存 怕你是個大哥不會linux 操作方式 ——— 先按ESC 然後按shift+;分號 最後輸入wq即可

  • 後面懶得說操作方式,linux都不會的話,開什麼玩笑

  • 修改 /etc/security/limits.conf 檔案 命令 vim /etc/security/limits.conf

點選檢視程式碼
# 在檔案末尾中增加下面內容
# 這個配置是:每個程序可以開啟的檔案數的限制
es soft nofile 65536
es hard nofile 65536
  • 修改 /etc/security/limits.d/20-nproc.conf 檔案 命令 vim /etc/security/limits.d/20-nproc.conf
點選檢視程式碼
# 在檔案末尾中增加下面內容
# 每個程序可以開啟的檔案數的限制
es soft nofile 65536
es hard nofile 65536
# 作業系統級別對每個使用者建立的程序數的限制
* hard nproc 4096
# 注: * 表示 Linux 所有使用者名稱稱

  • 修改 /etc/sysctl.conf 檔案
點選檢視程式碼
# 在檔案中增加下面內容
# 一個程序可以擁有的 VMA(虛擬記憶體區域)的數量,預設值為 65536
vm.max_map_count=655360
  • 重新載入檔案
點選檢視程式碼
# 命令
sysctl -p
  • 啟動程式 : 準備進入坑中

點選檢視程式碼
cd /opt/install/es/
# 啟動
bin/elasticsearch
# 後臺啟動
bin/elasticsearch -d

  • 這個錯誤告知:不能用root使用者,所以: 切換到剛剛建立的es使用者 命令 su es
  • 然後再次啟動程式, 進入下一個坑

  • 這個錯誤是因為:啟動程式的時候會動態生成一些檔案,這和ES沒得關係,所以:需要切回到root使用者,然後把檔案許可權再次重新整理一下
點選檢視程式碼
# 切換到root使用者
su root

# 切換到root使用者之後,執行此命令即可
chown -R es:es /opt/install/es

# 再切換到es使用者
su es

  • 再次啟動程式

  • 吃雞,這樣linux中單機ES就部署成功了

不過啊,前面這種方式都是low的方式,有更簡單的方式,就是使用docker容器來進行配置,簡直不要太簡單,雖然:使用docker容器來啟動程式有弊端,如:MySQL就不建議放在docker容器中,因為:MySQL是不斷地進行io操作,放到docker容器中,就會讓io操作效率降低,而ES放到docker中也是同樣的道理,但是:可以玩,因為:有些公司其實並沒有在意docker的弊端,管他三七二十一扔到docker中

  • 如果想要用docker容器進行ES配置,編寫如下的docker-compose.yml檔案
點選檢視程式碼
version: "3.1"
services:
  elasticsearch:
    image: daocloud.io/library/elasticsearch:7.9.0  # 注:此網站版本不全,可以直接用管我elasticsearch:7.8.0
    restart: always
    container_name: elasticsearch
    ports:
      - 9200:9200
    environment:
      - JAVA_OPTS=--Xms256m -Xmx1024m
# 在瀏覽器和postman中輸入以下指令均可
 http://ip:9200/		# 注:ip是自己伺服器的ip    如果是用postman,則:請求方式為 get
  • 瀏覽器效果

    • 注:瀏覽器訪問不了,看看自己伺服器開放9200埠沒有,別搞這種扯犢子事啊
  • postman的效果

4.1.2.2、部署叢集ES

  • 最簡單易懂但複雜的方式:對照windows版的叢集就可以了

    • 解壓ES、重新命名
    • 複製幾份ES資料夾
    • 修改對應配置
  • 更簡單的方式

    • 解壓linux版的ES,重新命名
    • 分發節點
xsync  es-colony		# es-colony就是重新命名之後的es資料夾
  • 注:要是沒有配置xsync,則:需要單獨配置好,面向百度吧,很簡單的,就使用yum命令安裝rsync、新增hosts資訊、編輯xsync指令碼、給檔案授權,然後就搞定了

4.2、鞏固核心概念

4.2.1、索引 index

  • 所謂索引:類似於關係型資料庫中的資料庫

  • 但是索引這個東西在ES中又有點東西,它的作用和關係型資料庫中的索引是一樣的,相當於門牌號,一個標識,旨在:提高查詢效率,當然,不是說只針對查詢,CRUD都可以弄索引,所以這麼一說ES中的索引和關係型資料庫中的索引是一樣的,就不太類似於關係型中的資料庫了,此言差矣!在關係型中有了資料庫,才有表結構( 行、列、型別...... ),而在ES中就是有了索引,才有doc、field.....,因此:這就類似於關係型中的資料庫,只是作用和關係型中的索引一樣罷了

  • 因此:ES中索引類似於關係型中的資料庫,作用:類似於關係型中的索引,旨在:提高查詢效率,當然:在一個叢集中可以定義N多個索引,同時:索引名字必須採用全小寫字母

  • 當然:也別忘了有一個倒排索引

    • 關係型資料庫通過增加一個 B+樹索引 到指定的列上,以便提升資料檢索速度。索引ElasticSearch 使用了一個叫做 倒排索引 的結構來達到相同的目的

4.2.2、型別 type

  • 這玩意兒就相當於關係型資料庫中的表,注意啊:關係型中表是在資料庫下,那麼ES中也相應的 型別是在索引之下建立的

  • 表是個什麼玩意呢?行和列嘛,這行和列有多少N多行和N多列嘛,所以:ES中的型別也一樣,可以定義N種類型。同時:每張表要儲存的資料都不一樣吧,所以表是用來幹嘛的?分類 / 分割槽嘛,所以ES中的型別的作用也來了:就是為了分類嘛。另外:關係型中可以定義N張表,那麼在ES中,也可以定義N種類型

  • 因此:ES中的型別類似於關係型中的表,作用:為了分類 / 分割槽,同時:可以定義N種類型,但是:型別必須是在索引之下建立的( 是索引的邏輯體現嘛 )

  • 但是:不同版本的ES,型別也發生了變化,上面的解讀不是全通用的

4.2.3、文件 document

  • 這玩意兒類似管關係型中的行。 一個文件是一個可被索引的基礎資訊單元,也就是一條資料嘛

4.2.4、欄位field

  • 這也就類似於關係型中的列。 對文件資料根據不同屬性( 列欄位 )進行的分類標識

4.2.5、對映 mapping

  • 指的就是:結構資訊 / 限制條件
  • 還是對照關係型來看,在關係型中表有哪些欄位、該欄位是否為null、預設值是什麼........諸如此的限制條件,所以 ES中的對映就是:資料的使用規則設定

4.2.6、分片 shards - 重要

  • 這玩意兒就類似於關係型中的分表

  • 在關係型中如果一個表的資料太大了,查詢效率很低、響應很慢,所以就會採用大表拆小表,如:使用者表,不可能和使用者相關的啥子東西都放在一張表吧,這不是找事嗎?因此:需要分表

  • 相應的在ES中,也需要像上面這麼幹,如:儲存100億文件資料的索引,在單節點中沒辦法儲存這麼多的文件資料,所以需要進行切割,就是將這整個100億文件資料切幾刀,然後每一刀切分出來的每份資料就是一個分片 ( 索引 ),然後在切開的每份資料單獨放在一個節點中,這樣切開的所有文件資料合在一起就是一份完整的100億資料,因此:這個的作用也是為了提高效率

  • 建立一個索引的時候,可以指定想要的分片的數量。每個分片本身也是一個功能完善並且獨立的“索引”,這個“索引”可以被放置到叢集中的任何節點上

  • 分片有兩方面的原因:

    • 允許水平分割 / 擴充套件內容容量,水平擴充,負載均衡嘛
    • 允許在分片之上進行分散式的、並行的操作,進而提高效能 / 吞吐量
  • 注意啊: 當 Elasticsearch 在索引中搜索的時候, 它傳送查詢到每一個屬於索引的分片,然後合併每個分片的結果到一個全域性的結果集中

4.2.7、副本 Replicas - 重要

  • 這不是遊戲中的刷副本的那個副本啊。是指:分片的複製品

  • 失敗是常有的事嘛,所以:在ES中也會失敗呀,可能因為網路、也可能因此其他鬼原因就導致失敗了,此時不就需要一種故障轉移機制嗎,也就是 建立分片的一份或多份拷貝,這些拷貝就叫做複製分片( 副本 )

  • 副本( 複製分片 )之所以重要,有兩個原因:

    • 在分片 / 節點失敗的情況下, 提供了高可用性。因為這個原因,複製分片不與原 / 主要( original / primary )分片置於同一節點上是非常重要的
    • 擴充套件搜尋量 / 吞吐量,因為搜尋可以在所有的副本上並行執行
  • 多說一嘴啊,分片和副本這兩個不就是配套了嗎,分片是切割資料,放在不同的節點中( 服務中 );副本是以防服務宕掉了,從而丟失資料,進而把分片拷貝了任意份。這個像什麼?不就是Redis中的主備機制嗎( 我說的是主備機制,不是主從複製啊 ,這兩個有區別的,主從是一臺主機、一臺從機,主、從機都具有讀寫操作;而主備是一臺主機、一臺從機,主機具有讀寫操作,而從機只有讀操作 ,不一樣的啊 )

  • 不過,有個細節一定需要注意啊,在Redis中是主備放在一臺伺服器中,而在ES中,分片和副本不是在同一臺伺服器中,是分開的,如:分片P1在節點1中,那麼副本R1就不能在節點1中,而是其他服務中,不然服務宕掉了,那資料不就全丟了嗎

4.2.8、分配 Allocation

  • 前面講到了分片和副本,對照Redis中的主備來看了,那麼對照Redis的主從來看呢?主機宕掉了怎麼重新選一個主機?Redis中是加了一個哨兵模式,從而達到的。那麼在ES中哪個是主節點、哪個是從節點、分片怎麼去分的?就是利用了分配

  • 所謂的分配是指: 將分片分配給某個節點的過程,包括分配主分片或者副本。如果是副本,還包含從主分片複製資料的過程。注意:這個過程是由 master 節點完成的,和Redis還是有點不一樣的啊

  • 既然都說了這麼多,那就再來一個ES的系統架構吧

  • 其中,P表示分片、R表示副本

  • 預設情況下,分片和副本都是1,根據需要可以改變

4.3、單節點叢集

這裡為了方便就使用window版做演示,就不再linux中演示了

  • 開啟前面玩的window版叢集的1節點

  • 建立索引 把這個索引切成3份( 切片 )、每份拷貝1份副本
http://127.0.0.1:1001/users		# 請求方式:put

# 請求體內容
{
    "settings" : {
        "number_of_shards" : 3,
        "number_of_replicas" : 1
    }
}

  • 開始安裝head外掛,這就是一個視覺化介面而已,後續還會用Kibana

    • 自行到官網下載elasticsearch-head-master,這是用Vue寫的

    • 這個外掛有兩種安裝方式,chrome瀏覽器直接把這個壓縮包解壓之後,然後把解壓的資料夾拖到擴充套件程式中去,這就成為一個外掛,整合到Chrome中去了,也就可以直接用了

    • 還有一種是通過Vue的方式,這種需要保證自己的電腦安裝了Node.js,我想都是玩過前後端分離的,也就玩過Vue了,所以這些Vue的配套安裝也就有了的 —— 安裝Node.js也不難,就官網下載、解壓、配置環境變數、然後進到解壓的elasticsearch-head-master目錄,使用npm install拉取模組,最後使用npm run start就完了。當然npm是國外的,很慢,而使用淘寶的cnpm更快,cnpm安裝方式更簡單,直接 npm install -g cnpm --registry=https://registry.npm.taobao.org 拉取映象即可,然後就可以使用cnpm來代替npm,從而執行命令了

    • 由於我用的是Edge瀏覽器,所以我是採用的Vue方式啟動的elasticsearch-head-master,啟動效果如下:

      • 訪問上圖中的地址即可, 但是:這個埠是9100,而我們的ES事9200埠,所以9100訪問9200事跨越的,因此:需要對ES設定跨越問題,而這個問題在第一次玩ES叢集時就配置了的

  • head開啟之後就是下圖中的樣子

  • head連結ES之後就是下圖的樣子

  • 三種顏色再鞏固一下:

    • green:所有的主分片和副本分片都正常執行
    • yellow:所有的主分片都正常執行,但不是所有的副本分片都正常執行
    • red:有主分片沒能正常執行
  • 但是:上述的單節點叢集有問題,就是將分片和副本都放在一個節點( node-1001 )中了,這樣會導致前面說的服務宕掉,資料就沒了,做的副本就是無用功

  • 當然:在head中測試時,可能會報master_not_discovered_exception,但是再啟動一個節點node-1002之後,發現又可以得吃了,而head介面中的顏色從yellow變成green了,這種情況是因為:原有資料導致的,即前面玩windows版ES叢集時有另外的資料在裡面,只需要把目錄下的data資料夾和logs資料夾“下”,把它的東西刪了再啟動就可以了

  • 但是啊,這裡一是玩的windows版,二是為了玩ES才這麼幹的,這種方式別輕易幹啊,學習階段還是多上網查一下,有很多解決方案的,這裡是玩才搞的

  • 回到正題,怎麼解決這個叢集問題?

4.4、故障轉移

  • 這個東西其實已經見到了,就是前面說的報master_not_discovered_exception的情況,此時再啟動一個節點即可實現故障轉移

  • 啟動node-1002節點

  • 一樣的,可能由於玩windows版時的一些資料導致node-1002節點啟動不了,所以刪掉data資料夾和logs資料夾下的東西即可

  • 重新整理head視覺化頁面

  • 恢復正常

4.5、水平擴容 / 負載均衡

  • 啟動node-1003節點

  • 重新整理head頁面

  • 對照前面單節點叢集來看,資料就被很好的分開了,這樣效能不就提上來了嗎?試問是去一個節點上訪問資料快還是把資料分開之後,減少壓力從而效率快呢?肯定後者嘛

  • 但是:如果相應繼續擴容呢?即:超過6份資料( 6個節點,前面講到過索引切分之後,每一份又是單獨的索引、副本也算節點 ),那怎麼辦?

    • 首先知道一個點:主分片的數目在索引建立時就已經確定下來了的,這個我們沒法改變,這個數目定義了這個索引能夠儲存的最大資料量( 實際大小取決於你的資料、硬體和使用場景 )
    • 但是,讀操作——搜尋和返回資料——可以同時被主分片 或 副本分片所處理, 所以當你擁有越多的副本分片時,也將擁有越高的吞吐量
    • 因此:增加副本分片的數量即可
http://127.0.0.1:1001/users/_settings		# 請求方式:put

	# 請求體內容
	{
		"number_of_replicas": 2
	}

  • 重新整理head頁面

    重新整理head頁面

4.6、應對故障

  • 應對的是什麼故障?前面一直在說:服務宕掉了嘛

  • 關掉node-1001節點( 主節點 )

  • 重新整理head頁面

  • 但是注意啊:yellow雖然不正常,但是不影響操作啊,就像你看了這個yellow之後,影響你正常發揮嗎?只是可能有點虛脫而已,所以對於ES來說也是可以正常查詢資料的,只是:效率降低了而已嘛( 主節點和3個分片都在的嘛 )

  • 解決這種問題

    • 開啟新節點( 把node-1001節點啟動 ———— 此時它就不是主節點了 ,當初新節點了嘛
        • 這就會報錯: unless existing master is discovered 找不到主節點( 對於啟動的叢集來說,它現在是新節點澀 ),因此:需要做一下配置修改( node-1001的config/ElasticSearch.yml )
discovery.seed_hosts: ["127.0.0.1:9302","127.0.0.1:9303"]
  • 儲存開啟node-1001節點即可

    • 重新整理head頁面

    • 故障恢復了,所以:這也告知一個問題,配置叢集時,最好在每個節點的配置檔案中都加上上述的配置,從而節點宕掉之後,重啟節點即可( 不然每次改不得煩死 ),注意:ES版本不一樣,這個配置方法不一樣的,6.x的版本是用cluster.initial_master_nodes: 來進行配置的

4.7、路由計算和分片控制理論

4.7.1、路由計算

  • 路由、路由,這個東西太熟悉了,在Vue中就見過路由router了( 用來轉發和重定向的嘛 )
  • 那在ES中的路由計算又是怎麼回事? 這個主要針對的是ES叢集中的存資料,試想:你知道你存的資料是在哪個節點 / 哪個主分片中嗎( 副本是拷貝的主分片,所以主分片才是核心 )?
    • 當然知道啊,就是那幾個節點中的任意一個嘛。娘希匹~這樣的騷回答好嗎?其實這是由一個公式來決定的
shard = hash( routing ) % number_of_primary_shards

其中

  • routing是一個任意值,預設是文件的_id,也可以自定義
  • number_of_primary_shards 表示主分片的數量( 如前面切分為了3份 )
  • hash()是一個hash函式嘛

這就解釋了為什麼我們要在建立索引的時候就確定好主分片的數量並且永遠不會改變這個數量:因為如果數量變化了,那麼之前所有路由的值都會無效,文件也再也找不到了

4.7.2、分片控制

  • 既然有了存資料的問題,那當然就有取資料的問題了。 請問:在ES叢集中,取資料時,ES怎麼知道去哪個節點中取資料( 假如在3節點中,你去1節點中,可以取到嗎?),因此:來了分片控制

  • 其實ES不知道資料在哪個節點中,但是:你自己卻可以取到資料,為什麼?

    • 負載均衡澀,輪詢嘛。所以這裡有個小知識點,就是:協調節點 coordinating node 我們可以傳送請求到叢集中的任一節點, 每個節點都有能力處理任意請求,每個節點都知道叢集中任一文件位置 ,這就是分片控制,而我們傳送請求的哪個節點就是:協調節點,它會去幫我們找到我們要的資料在哪裡
  • 因此:當傳送請求的時候, 為了擴充套件負載,更好的做法是輪詢叢集中所有的節點( 先知道這樣做即可 )

4.8、資料寫流程

  • 新建、索引和刪除請求都是寫操作, 必須在主分片上面完成之後才能被複制到相關的副本分片

  • 整個流程也很簡單

    • 客戶端請求任意節點( 協調節點 )
    • 通過路由計算,協調節點把請求轉向指定的節點
    • 轉向的節點的主分片儲存資料
    • 主節點再將資料轉發給副本儲存
    • 副本給主節點反饋儲存結果
    • 主節點給客戶端反饋儲存結果
    • 客戶端收到反饋結果

  • 但是:從圖中就可以看出來,這套流程完了,才可以做其他事( 如:才可以去查詢資料 ),那我為什麼不可以非同步呢?就是我只要保證到了哪一個步驟之後,就可以進行資料查詢,所以:這裡有兩個小東西需要了解

  • 在進行寫資料時,我們做個小小的配置

4.8.1、一致性 consistency

  • 這玩意就是為了和讀資料搭配起來嘛,寫入和讀取保證資料的一致性唄

  • 這玩意可以設定的值如下:

    • one :只要主分片狀態 ok 就允許執行讀操作,這種寫入速度快,但不能保證讀到最新的更改
    • all:這是強一致性,必須要主分片和所有副本分片的狀態沒問題才允許執行寫操作
    • quorum: 這是ES的預設值啊 , 即大多數的分片副本狀態沒問題就允許執行寫操作。這是折中的方法,write的時候,W>N/2,即參與寫入操作的節點數W,必須超過副本節點數N的一半,在這個預設情況下,ES是怎麼判定你的分片數量的,就一個公式: int( primary + number_of_replicas) / 2 ) + 1
      • 注意:primary指的是建立的索引數量;number_of_replicas是指的在索引設定中設定的副本分片數,如果你的索引設定中指定了當前索引擁有3個副本分片,那規定數量的計算結果為:int( 1 primary + 3 replicas) / 2 ) + 1 = 3,如果此時你只啟動兩個節點,那麼處於活躍狀態的分片副本數量就達不到規定數量,也因此你將無法索引和刪除任何文件
    • realtime request:就是從translog裡頭讀,可以保證是最新的。 但是注意啊:get是最新的,但是檢索等其他方法不是( 如果需要搜尋出來也是最新的,需要refresh,這個會重新整理該shard但不是整個index,因此如果read請求分發到repliac shard,那麼可能讀到的不是最新的資料,這個時候就需要指定preference=_primar y)

4.8.2、超時 timeout

  • 如果沒有足夠的副本分片會發生什麼?Elasticsearch 會等待,希望更多的分片出現。預設情況下,它最多等待 1 分鐘。 如果你需要,你可以使用timeout引數使它更早終止,單位是毫秒,如:100就是100毫秒

  • 新索引預設有1個副本分片,這意味著為滿足規定數量應該需要兩個活動的分片副本。 但是,這些預設的設定會阻止我們在單一節點上做任何事情。為了避免這個問題,要求只有當number_of_replicas 大於1的時候,規定數量才會執行

上面的理論不理解、或者感覺枯燥也沒事兒,後面慢慢的就理解了,這裡只是打個預防針、瞭解理論罷了

4.9、資料讀流程

  • 有寫流程,那肯定也要說一下讀流程嘛,其實和寫流程很像,只是變了那麼一丟丟而已

  • 流程如下:

    • 客戶端傳送請求到任意節點( 協調節點 )
    • 這裡不同,此時協調節點會做兩件事:1、通過路由計算得到分片位置,2、還會把當前查詢的資料所在的另外節點也找到( 如:副本 )
    • 為了負載均衡( 可能某個節點中的訪問量很大嘛,減少一下壓力咯 ),所以就會對查出來的所有節點做輪詢操作,從而找到想要的資料( 因此:你想要的資料在主節點中有、副本中也有,但是:給你的資料可能是主節點中的,也可能是副本中的 ———— 看輪詢到的是哪個節點中的 )
    • 節點反饋結果
    • 客戶端收到反饋結果

當然:這裡有個注意點啊( 需要結合前面說的一致性理論 )

  • 在文件( 資料 )被檢索時,已經被索引的文件可能已經存在於主分片上但是還沒有複製到副本分片。 在這種情況下,副本分片可能會報文件不存在,但是主分片可能成功返回文件。 一旦索引請求成功返回給使用者,文件在主分片和副本分片都是可用的

4.10、更新操作流程和批量更新操作流程

4.10.1、更新操作流程

  • 1、客戶端向node 1傳送更新請求。

  • 2、它將請求轉發到主分片所在的node 3 。

  • 3、node 3從主分片檢索文件,修改_source欄位中的JSON,並且嘗試重新索引主分片的文件。如果文件已經被另一個程序修改,它會重試步驟3 ,超過retry_on_conflict次後放棄。

  • 4、如果 node 3成功地更新文件,它將新版本的文件並行轉發到node 1和 node 2上的副本分片,重新建立索引。一旦所有副本分片都返回成功,node 3向協調節點也返回成功,協調節點向客戶端返回成功

  • 當然:上面有個漏洞,就是萬一在另一個程序修改之後,當前修改程序又去修改了,那要是把原有的資料修改了呢?這不就成關係型資料庫中的“不可重複讀”了嗎?

    • 不會的。因為當主分片把更改轉發到副本分片時, 它不會轉發更新請求。 相反,它轉發完整文件的新版本。注意點:這些更改將會“非同步轉發”到副本分片,並且不能保證它們以相同的順序到達。 如果 ES 僅轉發更改請求,則可能以錯誤的順序應用更改,導致得到的是損壞的文件

4.10.2、批量更新操作流程

  • 這個其實更容易理解,單文件更新懂了,那多文件更新就懂了嘛,多文件就請求拆分唄

  • 所謂的多文件更新就是:將整個多文件請求分解成每個分片的文件請求,並且將這些請求並行轉發到每個參與節點。協調節點一旦收到來自每個節點的應答,就將每個節點的響應收集整理成單個響應,返回給客戶端

  • 原理圖的話:我就在網上偷一張了

  • 其實mget 和 bulk API的模式就類似於單文件模式。區別在於協調節點知道每個文件存在於哪個分片中

4.11、再次回顧分片和倒排索引

4.11.1、分片

  • 所謂的分片就是:將索引切分成任意份嘛,然後得到的每一份資料都是一個單獨的索引

  • 分片完成後,我們存資料時,存到哪個節點上,就是通過 shard = hash( routing ) % number_of_primary_shards 得到的

  • 而我們查詢資料時,ES怎麼知道我們要找的資料在哪個節點上,就是通過 協調節點 做到的,它會去找到和資料相關的所有節點,從而輪詢( 所以最後的結果可能是從主分片上得到的,也可能是從副本上得到的,就看最後輪詢到的是哪個節點罷了

4.11.2、倒排索引

  • 圖中這裡,是將內容( 關鍵字 )拆分了,然後來對應ID,所以:這裡還有一種東西: 分詞 ,後面會接觸Kibana,再做詳細介紹

  • 但是,那只是簡單提了一下而已,其實還有三個東西沒說明

4.11.2.1、詞條

  • 它是指:索引中的最小儲存或查詢單元 。這個其實很好理解,白話文來講就是:字或者片語,英文就是一個單詞,中文就是字或片語嘛,比如:你要查詢的是某一個字或片語,這就是詞條唄

4.11.2.2、詞典

  • 這個就更簡單了,就是詞條的集合嘛。 字或者片語組成的內容唄

4.11.2.3、倒排表

  • 就是指:關鍵字 / 關鍵詞在索引中的位置 / 概率,有點類似於陣列,你查詢陣列中某個元素的位置,但是區別很大啊,我只是為了好理解,所以才這麼舉例子的

4.12、後面的安排