Elasticsearch 前傳
介紹搜索技術發展史和基本知識以及搜索引擎基本原理
搜索技術發展史
💠搜索引擎的5個階段
- FTP文件檢索階段
- 分類目錄導航階段
- 文本相關信檢索階段
- 網頁鏈接分析和用戶意圖識別階段
Elasticsearch簡介
💨Elasticsearch就是一個用於數據搜索、分析和存儲的框架
基於Java編寫,內部使用Lucene做索引與搜索,屏蔽Lucene復雜性只需要了解簡單一致的RESTful API即可。
相關功能: 檢索相關數據、返回統計結構、響應速度、分布式下實時文檔存儲和實時分析搜索。
Lucene簡介
💨Lucene是一個支持全文檢索的工具包
Lucene僅僅是一個工具包並非完整的全文檢索引擎
Lucene的索引文件格式獨立於應用平台,定義一套以8Byte為基礎的索引文件格式,兼容不同平台
Lucene默認實現布爾操作、模糊查詢、分組查詢等
主要模塊: Analysis模塊、Index模塊、Store模塊、QueryParser模塊、Search模塊和Similarity模塊。
模塊名稱 | 模塊功能 |
---|---|
Analysis | 詞法分析與語言處理,形成存儲或搜索的最小單元Term |
Index模塊 | 負責索引的構建工作 |
Store模塊 | 負責索引的讀和寫,主要對文件的一些操作 |
QueryParser模塊 | 負責語法分析,把查詢語句生成Lucene底層可以識別的條件 |
Search模塊 | 負責對索引的搜索工作 |
Similarity模塊 | 負責相關性打分和排序 |
相關術語
術語 | 術語描述 |
---|---|
Term | 索引中最小存儲和查詢單元。在英語環境中一個term指的是一個單詞;在中文環境中一個term指的是要給分詞后的詞 |
Term Dictionary | 排序數組、HashMap、FST(Finite-State Transducer) |
倒排表 | 一篇文檔由多個詞組成,倒排表記錄某個詞在哪些文章中出現過 |
正向信息 | 原始的文檔信息,可以用來做排序、聚合、展示等 |
段 | 索引中最小的獨立存儲單元。一個索引文件由一個或多個段組成。 |
知識點關聯
REST(resource - Representation State Transfer)協議
🌐Web技術架構四個基石: URI、HTTP、HyperText、MIME(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展類型)。這四個基石支撐
💮Web開發技術經歷5個階段: 靜態內容(靜態HTML) -> CGI(Common Gateway Interface -> ASP、PHP、JSP) -> 腳本語言階段(JS、Java Applet) -> 瘦客戶端應用階段(Web MVC) -> RIA(Rich Internet Application -> DHTML + Ajax)階段和移動應用階段
REST關鍵性原則: Resource、Hypertext Driven、Uniform Interface、Representation、State Transfer
Keyword | DESC |
---|---|
Resource(資源) | 表示事物定義ID |
Hypertext Driven(超文本驅動) | 將所有事物鏈接在一起 |
Uniform Interface(統一接口) | 使用標准方法 |
Representation(資源的表述) | 資源多重表述的方式 |
State Transfer(狀態轉移) | 無狀態的通信 |
🔺Resource 有一個或多個URI表示(URI是資源的名稱也是資源在Web上的地址)
將服務器中很多離散的資源組合,每個資源是服務器上一個可命名的抽象概念。資源可是服務器文件系統中的一個文件也可以是數據庫中的一張表。
每個事物都是可被標志的,都會擁有一個ID標識符。在Web開發中,代表ID的統一概念 ===》 URI(全局命名空間)URI、URL和URN的區別 URI(資源名稱+資源路徑) = URL + URN
🌡URI(Uniform Resource Identifier: 統一資源標識符包括URL和URN
🌡URL(Uniform Resource Locater: 統一資源定位符
🌡URN(Uniform Resource Name: 統一資源名稱
🔺URI的4個設計原則
- 名詞
- 區分單復數
- URI有長度限制, <= 1KB
- URI不顯示未加密信息
🔺URI中幾個符號的解釋
符號 | 描述 | 舉例 |
---|---|---|
/ | 層次關系 | https://www.xxx.cn/products/elasticsearch 【%2F】 |
; | 並列關系 | https://www.xxx.com/axis;x=0,y=9 sip:user@domain.com; foo=bar; x=y |
- | 提高可讀性,最好小寫 | https://www.xxx-fan.-com/ |
+ | + 表示空格(在URL中不能使用空格) | 【%2B】 |
? | 分割實際的URL和參數 | 【%3F】 |
# | 表示書簽🔖 | 【%23】 |
& | URL中指定的參數間的分隔符 | 【%26】 |
= | URL中指定的參數的值 | 【%3D】 |
🔺超文本驅動 所有事物鏈接在一起。超媒體被當作應用狀態引擎
資源之間通過超鏈接相互關聯,超鏈接既代表資源之間的關系也代表可以執行的狀態轉移
URI命名規范是全球標准,構成Web的所有資源都是可以互聯互通的超媒體原則: 服務器端為客戶端提供一組鏈接🔗,使客戶端能夠通過鏈接將應用從一個狀態改變為另一個狀態
🔺統一接口 必須通過統一接口對資源執行各種操作
在HTTP 1.1中定義操作資源的統一接口: GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS
🔺資源表述 一段對資源在某個特定時刻的狀態描述
資源表述格式: HTML、XML、JSON、文本、圖片、視頻、音頻等
資源的表述方式通過協商機制來確定,請求響應的表述通常使用不同的格式。
🔺狀態轉移 無狀態通信
狀態轉移是在客戶端和服務端之間轉移。通過轉移和操作的資源表述,間接實現操作資源的目的
無狀態意味着服務器的變化對客戶端是不可見的。主要是為了保證架構設計的可伸縮性和可擴展性, 減少耦合
REST架構設計是否優秀的標准: 面向資源、可尋址、連通性、無狀態、統一接口和超文本驅動
騏驥一躍,不能十步。 駑馬十駕,功在不舍。
數據搜索🔍方式
🔰 搜索引擎是對數據進行檢索,數據存在兩種類型 結構化數據和非結構化數據
✋所謂的結構化數據
例如存儲在關系型數據庫中的數據, 它們具有指定的數據類型和個數。通過二維化表結構來承載。
✋所謂的非結構化數據
例如存儲在非關型數據庫中的數據,它們的數據長度不定且無固定數據格式。
🚀結構化數據搜索
結構化數據基於關系型數據庫來存儲,關系數據庫支持索引,結構化數據通過DB來完成搜索和查找。
常用查找方式: 順序掃描、關鍵詞精確匹配、關鍵詞部分匹配等
復雜匹配: 借助
LIKE
關鍵詞
左匹配: xxx%
右匹配: %xxx
完全匹配: %xxx%
🛸非結構化數據搜索
數據的搜索: 順序掃描(效率低)和全文檢索(效率高)兩種方法
在實現全文檢索的過程中,要提取非結構化數據中的有效信息,重新組織數據的承載結構形式。
全文檢索是一種空間換時間的做法(前期構建索引后期提高搜索效率)
用戶 -> 輸入內容預處理 -> 搜索關鍵詞查詢 -> 索引庫 <- 數據索引 <- 數據預處理 <- 網頁庫 <- 網絡爬蟲 <- 互聯網
搜索引擎的工作原理分為兩個階段:
- 網頁數據爬取: 爬蟲、數據預處理、數據索引三個主要動作(搜索關鍵詞、輸入內容、預處理、搜索關鍵詞查詢)
網頁被爬蟲爬取后,存儲網頁庫,以備下一姐u但進行數據預處理。
預處理操作: 去除噪聲內容、關鍵詞處理(中文分詞、去除停止詞)、網頁間鏈接關系計算
- 索引階段、搜索階段
在創建索引之前都需要對內容進行分詞。分詞不僅僅是關鍵詞提取的前提,也是后續文本挖掘的基礎。
在倒排索引中,詞匯在網頁或文章中出現的位置、頻率和權重等,在查詢階段會用到。
在倒排索引中,有詞條(Term)、詞典(Term Dictionary)、倒排表(Post List)三個名詞
🐷詞條(Term): 索引中最小的存儲和查詢單元。
🐸詞典(Term Dictionary): 又稱字典,是詞條的集合。單詞詞典是由網頁或文章中出現所有詞構成的字符串集合
🐼倒排表: 詞出現在哪些文檔里、出現的位置和頻率
在Lucene中詞典中詞典和倒排表是實現快速檢索的重要基石。
詞典: 存儲在內存中
倒排表: 存儲在磁盤上
Elasticsearch 實戰
Elasticsearch是一個分布式、可擴展、近實時的高性能搜索於數據分析引擎。
🔵 Elasticsearch基於Apache Lucene構建,采用Java編寫其特點:
🔹分布式實時文件存儲。Elasticsearch可以將索引文檔中的每個字段存入索引,以便字段可以被檢索到。
🔹實時分析的分布式搜索引擎。Elasticsearch的索引分拆成多個分片,每個分片有0或多個副本。集群中的每個數據結點都可承載一個或多個分片,並協調和處理各種操作。
🔹高擴展性。處理PB級別的結構化或非結構化數據。
如果需要將Elasticsearch作為守護進程運行則執行bin/elasticsearch -d -p pid
Elasticsearch配置
“約定大於配置”的思想,配置文件包含特定的節點設置eg: node.name和paths路徑等信息還會包含節點為了能夠加入Elasticsearch集群需要添加cluster.name和network.host等
配置文件位置信息: elasticsearch.yml、jvm.options和log4j2.properties
安全設置
在ES中設置信息是敏感且需要保密的,此時單純依賴文件系統權限保護不夠需要提供密鑰庫和密鑰庫工具來管理密鑰庫中的設置。所有命令均適用於ES用戶
對密鑰庫所有修改需要在重新啟動ES之后生效
➰創建密鑰庫
bin/elasticsearch-keystore create
將會創建2個文件分為 elasticsearch.keystore和elasticsearch.yml
➰查看密鑰庫中的設置列表
bin/elasticsearch-keystore list
➰添加字符串設置
需要設置敏感的字符串則需要使用add命令添加
bin/elasticsearch-keystore add the.setting.name.to.set
命令執行后將提示輸入設置。用戶可以使用--stdin標志在窗口stdin中輸出待設置的目標值eg:
cat /file/containing/setting/value | bin/elasticsearch-keystore add --stdin this.setting.name.to.set
➰添加文件設置
用戶可以通過添加文件命令添加敏感信息文件,eg: 雲插件的身份驗證密鑰文件。確保文件路徑作為參數在設置名稱之后
bin/elasticsearch-keystore add-file the.setting.name.to.set /path/example-file.json
➰刪除密鑰設置
從密鑰庫中刪除設置則使用remove命令
bin/elasticsearch-keystore remove the.setting.name.to.remove
➰重新加載的安全設置
密鑰庫內容的更改不會對正在運行的ES節點起任何作用,必須重新啟動節點才能重新讀取設置。
對於某些安全設置可以設置為可重新加載,設置后可以在正在運行的節點上重新讀取和應用
日志記錄設置
ES可以通過log4j2進行日志記錄。
ES公開三個屬性
- $sys:es.logs.base_path -> 日志文件目錄地址
- $sys:es.logs.cluster_name -> 群集名稱(在默認配置中,用做日志文件名的前綴)
- $sys:es.logs.node_name -> 解析為節點名稱(顯式設置了節點名稱)
用戶在配置文件中引用這些屬性來確定日志文件的位置。
ES核心概念
學好、用好ES首先要了解其核心概念、名詞和屬性。eg:懂地圖就要知道地圖里面常用的標記符號一樣
核心概念: Node、Cluster、Shards、Replicas、Index(數據庫)、Type(數據表)、Document(記錄)、Settings、Mapping和Analyzer
術語 | 描述 |
---|---|
Node(節點) | 節點是組成ES集群的基本服務單元,集群中每個運行中的ES服務器都可稱之為節點 |
Cluster(集群) | ES的集群是由具有相同cluster.name(默認為elasticsearch)的一個或多個ES節點組成,各個節點協同工作,共享數據。同一個集群內節點的名字不能重復,但集群的名稱一定要相同 |
Shards(分片) | 當索引的數據量太大時候,受限於單個節點的內存、磁盤處理能力等,節點無法足夠塊響應客戶端的請求,需要將一個索引上的數據進行水平拆分。拆分出來的數據部分稱之為一個分片。每個分片都會放在不同的服務器上 |
Replicas(副本\備份) | 副本對主分片的備份,是精確復制模式,每個主分片均有*個副本 |
Index(索引) | Index相當於數據庫,索引被水平切分成多個分片,需要通過索引名稱在集群內做唯一標識 |
Type(類別) | Type相當於數據表,類別指的是索引內部的邏輯分區,通過Type的名字在索引內進行唯一標識 |
Document(文檔) | Document相當於記錄,每一條數據就是一個文檔 |
Settings | Settings是對集群中索引的定義信息,比如一個索引默認的分片數 |
副本數等 | |
Mapping(索引自身元信息) | 相當於表結構信息,Mapping標識保存了索引中字段(Field)的存儲類型、分詞方式、是否存儲等信息 |
Analyzer(字段分詞方式的定義) | 一個Analyzer通常由一個Tokenizer和零到多個Filter組成。在ES中,默認的標准Analyzer包含一個標注的Tokenizer和三個Filter -> Standard Token Filter、Lower Case Token Filter 和 Stop Token Filter |
Mapping可以動態識別的。如果沒有特殊需求,則不需要手動創建Mapping,ES會根據數據格式自動識別其類型。
當需要對某些字段添加特殊屬性時。eg: 定義使用分詞器、是否分詞、是否存儲等需要手動配置Mapping、
😱關於分片
進行分片操作之后,索引的規模擴大,性能也隨之水漲船高。
ES依賴Lucene,ES中的每個分片都是Lucene的一個索引文件,因此每個分片必須有一個主分片和0-多個副本分片
當開發人員在要給設置有多分片的索引中寫入數據時,是通過路由來去頂具體寫入哪個分片中的,因此在創建索引時需要指定分片的數量,並且分片的數量一旦確定就不能更改。
開發人員在查詢索引時,需要哦在索引對應的多個分片上進行查詢。ES會把查詢發送給每個相關的分片,並匯總各個分片的查詢結果。對上層應用程序,分片是透明的。
在ES中,默認一個索引創建5個主分片,並分別為每個主分片創建一個副本。
主分片和備份分片共同向外提供服務減輕負載,同時備份分片也可以作為主分片的候選,以防主分片失效。
備份分片可以提升ES系統的高可用性能,可以提升搜索時並發性能
🍱ES集群中,節點的狀態有Green、Yellow和Red三種
1.💚Green: 節點運行狀態為健康狀態。所有的主分片和副本分片均能正常工作,集群100%健康
2.💛Yello: 節點運行狀態為預警狀態。所有的主分片都可以正常工作,但至少有一個副本分片無法正常工作。
3.💔Red: 集群無法使用。此時,集群中至少有一個分片的主分片及其全部副本均不能工作|
ES的架構設計
核心層(Lucene) =》 數據處理層(Index、Search、Mapping) =》 發現與腳本層 =》 協議和應用層
Discovery是ES自動發現節點的機制。
協議層默認是HTTP
應用層是RESTful的API
ES節點自動發現機制
4種可供選擇的發現機制
【Azure Discovery】、【EC2 Discovery】、【Google Compute Engine(GCE) Discovery】、【Zen Discovery】
Zen Discovery是ES內置的默認發現模塊。發現模塊用於發現集群中的節點以及選擇主節點(master節點)。
Zen Discovery提供單播模式和基於文件的發現,並且可以擴展為通過插件支持其他形式的發現機制。
主要參數配置
discovery.zen.ping.multicast.enabled: true
discovery.zen.fd.ping_timeout: 100s
discovery.zen.ping.timeout: 100s
discovery.zen.minimum_master_nodes: 2
discovery.zen.ping.unicast.hosts: ["172.31.X.Y"]
discovery.zen.ping.multicast.enabled
參數 | 描述 |
---|---|
discovery.zen.ping.multicast.enabled: true | 關閉多播模式的自動發現機制,主要為了防止其他機器上的節點自動連入 |
discovery.zen.fd.ping_timeout: 100s和discovery.zen.ping.timeout: 100s | 設置節點與節點之間連接ping命令執行的超時過長 |
discovery.zen.minimum_master_nodes: 2 | 集群中選舉主節點時至少需要有多少個節點參與 |
discovery.zen.ping.unicast.hosts: ["172.31.X.Y"] | 在單薄模式下,節點應該自動發現哪些節點列表。action.auto_create_index:false表示關閉自動創建索引 |
ES支持多播模式和單播模式自動兩種節點發現機制。(❗不推薦多播模式,多播模式大多數系統不支持且安全性低)
🥖單播模式
🚫關閉多播模式: discovery.zen.ping.multicast.enabled:false #關閉多播
在ES中發現機制默認采用單播模式以防止節點無意中加入集群。
ES支持同一個主機🖥啟動多個節點◼。只有在同一台機器上運行的節點才會自動組成集群。
集群的節點不再統一服務器上時需要進行節點的IP配置
# 填寫集群中的IP地址列表
discovery.zen.ping.unicast.hosts: ["192.168.X1.Y1:9300","192.168.X2.Y2:9300"]
◼節點類型
ES中,每個節點既可以作為候選主節點也可以是數據節點
節點的角色配置在配置文件/config/elasticsearch.yml
中設置即可。在ES中默認均為true
node.master: true //true 為候選主節點 false反之
node.data: true // 是否為數據節點
數據節點負責數據的存儲相關操作。eg: 數據的C、R、U、D和聚合等
數據節點📕對服務器配置要求高
一旦候選主節點被選舉為主節點(管家),則主節點就要負責創建索引、刪除索引、追蹤集群中節點的狀態,以及跟蹤哪些節點是群集的一部分,並決定將哪些分片分配給相關節點
分片和路由
在創建索引的時候就應該指定分片的數量(一旦確定無法修改)
分片的數量和副本數量可以通過創建索引時的Settings來配置
默認參數
index.number_of_shards: 5 # 主分片數5
index.number_of_replicas: 1 # 副分片數1
對文檔的新建、索引和刪除請求等寫✍操作,必須先在主分片上完成之后才會復制到相關的副本分片。
ES為提高速度,並發執行寫的過程為解決並發沖突💥使用樂觀鎖進行控制,每個文檔都存在一個Verion(版本號),當文檔被修改時版本號遞增。
ES通過文檔標識符ID將文檔分配到多個分片上。當查詢數據時,ES會查詢所有的分片並匯總結果
數據寫過程
數據寫入操作在ES的內容中執行,數據分配到特定的分片和副本上,最終數據需要持久化到磁盤上
🌅ES的數據存儲路徑配置:../config/elasticsearch.yml
進行設置
path.data: /path/to/data # 索引數據
path.logs: /path/to/logs # 日志記錄
🌅分段存儲
索引數據以分段的形式存儲在磁盤上。
索引文件拆分成多個子文件(段),每個段是倒排索引的最小單元
段具有不變性一旦持久化則無法更改。
分段的存儲模式為了避免在讀寫操作時使用“鎖🔒”,提升ES的讀寫性能。
索引文件存儲后無法修改則如何進行數據的更新、刪除、新增?
🤡新增
數據是新的只需要在當前文檔新增一個段即可
🤡刪除
刪除數據時,分段由於存在不可逆(無法更改)特性,不會講文檔從舊的段中移除。而是新增一個🔅*.del
文件。
.del文件中會記錄這些被刪除文檔的段信息。被標記刪除的文檔仍然可以被查詢匹配到,但最終結果被返回前通過🔅*.del
文件在其結果集中移除*
🤡更新
分段不可逆特性,ES無法修改原有的段來更新。故而 📛更新操作 = 先刪除 + 后新增
。
ES先將舊的文檔從*.del文件中標記刪除,然后將文檔的新版本索引到一個新的段中。
🐷在查詢數據時,兩個版本的文檔都會被一個查詢匹配到,但被刪除的舊版本文檔在結果集返回前會被移除。
段的優勢
段不需要鎖🔒,提升了ES的讀寫性能。分段不變性的主要缺點是存儲空間占用量大---> 當刪除舊數據時,舊數據不會馬上被刪除而是在*.del文件中標記刪除,舊數據只有等到段更新的時才會被刪除,
延遲寫策略
在ES中,索引寫入磁盤的過程是異步的。
ES不會每次更新一條數據就會增加一個段到磁盤上而是采用延遲寫策略。
每當有新的數據寫入時,就將其寫入JVM的內存中。在內存和磁盤之間時文件系統緩存。文件緩存空間使用的是OS的空間。當達到默認的時間或內存的數據達到一定量時,就會觸發一次刷新(refresh)操作,將內存中的數據生成一個新的分段並緩存到文件緩存系統,之后刷新到磁盤💽並生成提交點🔴
新數據寫入內存時,內存中的數據不是以段的形式存儲只有當數據經由內存刷新到文件緩存系統,並生成新的段后,才供搜索使用,而不需要等到刷新到磁盤中才可以搜索。
ES中,寫入和打開一個新段的過程稱為刷新。(默認情況,每個分片會每秒自動刷新一次 ---> 這就是ES實現實時搜索🔍的原因)
settings中通過配置refresh_interval的值,調整索引的刷新頻率。在設置值的時候要注意后面的時間單位,否則默認是 ms
當refresh_interval = -1時,表示關閉索引的自動刷新
延遲策略會減少數據持久化的次數,提升ES整體寫入效率。當文件緩存系統來帶來數據丟失的風險eg: 機房斷電等不可控因素
解決此問題 ===》 引入事務日志(Translog)機制。事務日志用於記錄所有還沒有持久化到磁盤的數據。
段合並
ES自動刷新流程中,每秒都會創建一個新的段,導致短時間內段的數量猛增,當段數量太多時會帶來較大資源消耗,eg:文件句柄、內存和CPU的消耗。
在內容搜索階段,由於搜索請求要檢查到每個段,然后合並並查詢結果。因此段越多,檢索速度越慢。
段合並: 將每次產生的小段合並成更大的段。在段合並過程中ES會將舊段從文件系統中清除。合並結束后,old段被刪除,new段被Flush到磁盤中,同時寫入
一個包含new段且排除old和較小的段的新提交點。打開新的段之后,可以用來搜索。
知識點互聯
🐷 YAML(Yet Another Markup Language 一種置標語言),強盜YAML以數據作為中心,而不是以置標語言作為重點。
配置文件格式的歷史
ini => JSON => XML => Properties => HOCON
HOCON(Human-Optimized Config Object Notation) 文件以
.conf
后綴
🐷ES和關系型數據庫對比
ElasticSearch | 關系型數據庫 |
---|---|
Indices(索引) | Databases(庫) |
Types(類型) | Tables(表) |
Documents(文檔) | Rows(行) |
Fields(字段) | Columns(列) |
Mapping(映射) | schema |
GET/POST/UPDATE/PUT/DELETE | 增刪改查 |
學問勤中得,螢窗萬卷書