插件学习笔记:搜索引擎ElasticSearch
ElasticSearch介紹
ElasticSearch是一個實時分布式的高拓展全文搜索和分析引擎,是ELK(ElasticSearch, Kibana, Logstach的)技術的核心。
ElasticSearch的優勢在于模糊與全文查詢,雖然關系型數據庫也能夠做到like關鍵字的模糊查詢,但是會遍歷整個表數據,響應很慢,因此需要使用搜索更加快捷的ElasticSearch來進行處理。
主流的搜索引擎
ES與Solr的相同點
ElasticSearch和Solr都屬于應用很廣的搜索引擎,他們的基礎都是Lucene, 一個Apache開源的全文搜索的java核心工具包
ES與Solr對比
- ElasticSearch的安裝比較簡單,即開即用,Solr則相對而言比較復雜
- Solr用Zookeeper進行集群管理,而ElasticSearch有內置的分布式協調管理功能
- Solr指出JSON,XML等多種的數據格式,ES支支持Json
- Solr提供的功能更多,而ES更注重核心功能,其他的依賴第三方差價,比如圖形化的管理分析工具Kibana
- Solr查詢更快,更新索引慢,而ElasticSearch更新索引更快,也就是實時查詢性能更好,因此像商城這種更適合用Solr,而微博這種更新數據量大的更適合用ElasticSearch
Hermes
騰訊的大數據搜索引擎,與ES和Solr相比
- ES和Solr更注重全文的搜索,Hermes更注重數據的分析
- ES和Solr相對數據量更小,而Hermes可以處理更大量的數據
ElasticSearch的數據格式
數據格式的對比,Index相當于一個數據庫,Type相當于一個表,而Document對應了一行數據,Field對應了一個列,不過在后期的ElasticSearch中已經刪除了Type的概念,一個文檔的數據序列化格式為JSON
分片
對于一個索引數據量過大的時候,一個節點可能是存儲不下這個索引里所有的數據的,因此這里引入了分片的概念,也就是將所有的數據分片存儲在不同的節點當中,查詢的時候會查詢整個集群里面所有屬于同一索引的分片。這樣的好處在于不僅可以突破節點的數據存儲量,還可以并行操作提高效率和吞吐量。這部分對于用戶而言是透明的,elasticsearch會自行進行管理。
- 值得注意的是,Lucene的索引對應了elasticsearch中的分片,elasticsearch中的索引是lucene中索引的集合
- 分片的內容的路由計算是由master根據一個路由公式來的
副本
允許創建分片的一個或多個拷貝,這個拷貝叫做復制分片/副本,分片的優勢在于
- 提高了可用性
- 也可以提高搜索量/吞吐量,因為所有的搜索都可以在副本上并行運行
分片的數量可以在創建索引的時候指定,創建索引之后可以動態地改變復制的數量,但是分片數量是不能改變的。默認情況下會有一個主分片和一個復制分片,分片分配給某個節點的過程是由master節點完成的
ElasticSearch的架構
集群Cluster
一個ES集群有一個對應的名字,節點可以通過這個名字加入到集群當中,默認集群名稱為“elasticsearch”
節點Node
一個節點也由一個對應的名字指定,默認是一個漫威漫畫的名字,服務器通過指定節點名字可以對節點進行連接。一個集群內部節點的名稱要唯一
如果沒有指定集群的名稱,同一網絡下的若干節點只要一啟動,就都會加入到“elasticsearch”這個集群當中,他們能夠互相發現彼此。
在節點1中的數據在節點2里面也是能被查詢到的,當一個節點被選為主節點master時,他就會負責集群范圍內所有的變更,包括增加、刪除索引或增加刪除節點等。
ElasticSearch原理
讀寫流程
- 對于寫數據,會首先由協調節點計算主分片所在位置,寫完主分片后寫備份,而后返回成功消息
- 對于讀數據,會選擇輪詢副本的方式來達到負載平衡的目的,當然同步沒完成的時候會報告副本不存咋,這種情況下就需要主分片返回數據了
對于多條數據的操作是可以并行進行的
分片原理
分片是ES最小的工作單元
倒排索引
將文檔中的內容進行分詞,作為索引,索引對應的值是文檔的id,也就是從id對應內容反向成了內容對應id
動態更新索引
ElasticSearch是基于Luence的,Luence引入了按段搜索的概念,每一個段就是一個倒排索引,查詢時會采取輪詢每一個段的方式進行,同時將搜到的內容進行聚合。以保證所有的內容都被正確地計算。
除了所有的段之外,es還會存儲一個提交點,即一個列出了所有已知段的文件。
索引更新流程如下
近實時搜索特性
由于從緩存中向磁盤寫入新的段是十分浪費事件的,因此elasticSearch采用了一個存在緩存中的段的方式,將緩存區的內容寫入一個可以被搜索的段中,這樣緩存區的內容就可以被搜索到了,再將耗費時間長的磁盤寫入過程異步進行提交就可以了。這個過程被成為refresh,每秒(這個事件是可以修改的)執行一次,也就是添加的新段會在一秒內被搜索到,因此是近實時搜索的特性。
持久化變更
進實時搜索的緩存段如果斷電的話就消失了,因此持久化,也就是異步存儲段到磁盤的過程也是必須被執行的。elasticSearch引入了translog日志來進行處理。
在緩存寫入的過程當中,translog也會記錄相應的內容,隔一段時間會進行全量的提交,也就是
也就是說通過translog這一個存儲了所有沒有被持久化操作的日志記錄,完成了可靠的數據持久化工作
分片每30分鐘或translog過長的時候進行一次flush
- 注意:段的持久化是異步的,可以保證數據的可靠性,但是前提是translog的數據能夠被正確地存儲,translog默認每5秒刷新一次,或者在請求之后執行一次,這就使得translog本身的持久化是同步的,雖然會損失一定的性能,但是數據是可靠的,當然在一些數據可靠性要求不高的應用場景也可以采用異步的方式追求極致的性能。
段合并
采用了分段搜索雖然更新索引的開銷較低,但是隨著段的暴增,數據的搜索會變得緩慢,因此在elasticSearch當中引入了段合并的后臺過程,小的段被合并到了大的段當中。段合并的過程如下
refresh的過程中啟用了緩存的段并可以被搜索到
產生一個大的緩存段
選擇大小相似的小段,將其寫入大的緩存段當中(這一步并不影響原先小段被搜索)
新段flush到磁盤,提交點也被刷新
新段打開用于搜索
老段刪除
合并過程占用了大量的CPU資源,因此elasticSearch對合并過程進行了資源的限制,保證搜索過程能被很好地執行
文檔分析
文檔分析器的作用在于將一整塊內容劃分為獨立的詞條并進行一些相關的處理保證“可搜索性”,一次文檔的分析過程被分成了三步
當然分詞器是用在查詢全文域的,當進行精確查詢的時候,比如使用+關鍵字,是不會用分析器進行處理的
內置分析器
有標準分析器,簡單分析器,空格分析器,語言分析器等,它們根據不同的規則進行了詞條的劃分
IK中文分詞器
進行常見的中文分詞并支持進行自定義拓展詞典(遠程的或者本地的都可以)
除了這些之外ES也是支持自定義分詞器的
ElasticSearch文檔沖突
Web1做了-1操作,Web2也做了-1操作,但是二者引發了并發所帶來的沖突,這就是文檔沖突現象,其實就是一個并發問題
文檔沖突現象有兩種處理方式,一是悲觀并發控制,二是樂觀并發控制
- 悲觀并發控制:比如mysql的行級鎖,只允許一個線程進行數據的處理
- 樂觀并發控制:請求會攜帶版本號,舊的版本號不會覆蓋新的版本號,以保證數據不會丟失,ES采用的就是這種方式
ElasticSearch索引庫的操作
HttpUrl操作
采用RESTful風格進行處理,相信的條件封裝在請求體的JSON格式數據當中
RESTful風格簡而言之就是
- URL就代表了資源
- HTTP的操作類型就代表了對資源進行怎樣的處理
- 返回的狀態碼就能知道操作取得的效果如何
支持以下幾種操作:
- 索引
- 文檔
- 映射(相當于關系型數據庫當中的表結構)
DSL語句操作
同樣支持上述的操作,包括排序、過濾、分頁等等相關的操作
SpringData ElasticSearch
SpringDataElasticSearch對ES的相應API進行了封裝,能夠更方便地構建所需的代碼
引入依賴
配置文件
spring:data:elasticsearch:cluster-name: my-applicationcluster-nodes: 192.168.211.132:9300配置說明
connection-timeout:服務連接超時時間 socket-connect:HTTP請求超時時間 ribbon.ReadTimeout: Feign請求讀取數據超時時間 timeoutInMilliseconds:feign連接超時時間 cluster-name:Elasticsearch的集群節點名稱,這里需要和Elasticsearch集群節點名稱保持一致 cluster-nodes:Elasticsearch節點通信地址啟動類
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) @EnableEurekaClient public class SearchApplication {public static void main(String[] args) {/*** Springboot整合Elasticsearch 在項目啟動前設置一下的屬性,防止報錯* 解決netty沖突后初始化client時還會拋出異常* availableProcessors is already set to [12], rejecting [12]***/System.setProperty("es.set.netty.runtime.available.processors", "false");SpringApplication.run(SearchApplication.class,args);} }對于POJO,設置Document和Feild注解設置,需要與elasticSearch中的設置一致
@Document(indexName = "skuinfo",type = "docs") public class SkuInfo implements Serializable {//商品id,同時也是商品編號@Idprivate Long id;//SKU名稱@Field(type = FieldType.Text, analyzer = "ik_smart")private String name;//商品價格,單位為:元@Field(type = FieldType.Double)private Long price; }DAO層的設置也比較簡單,實現相應的類即可
@Repository public interface SkuEsMapper extends ElasticsearchRepository<Sku,Long> { }許多簡單查詢、分頁查詢、聚合查詢、高亮查詢都是可以用類中封裝的方法進行實現的
ElasticSearch面試題
為什么使用ElasticSearch
系統中的數據,隨著業務的發展,時間的推移,將會非常多,而業務中往往采用模糊查詢進行數據的搜索,而模糊查詢會導致查詢引擎放棄索引,導致系統查詢數據時都是全表掃描,在百萬級別的數據庫中,查詢效率是非常低下的,而我們使用 ES 做一個全文索引,將經常查詢的系統功能的某些字段,比如說電商系統的商品表中商品名,描述、價格還有 id 這些字段我們放入 ES 索引庫里,可以提高查詢速度。
- 關鍵字: 模糊查詢效率低,倒排索引,提高速度
master 選舉流程
- 關鍵詞:ping,排序,選取第一個
關于腦裂
概念
簡而言之,因為某些原因出現了多個master,比如兩個機房分別存放了三個節點,機房間的網絡中斷導致機房2中的節點無法訪問機房1中的節點,于是選取了兩個master,就造成了腦裂
腦裂成因
- 網絡延遲原因,集群間的網絡通信出現問題
- 節點負載,master作為data節點訪問壓力過大導致造成大面積延遲
- data上的垃圾回收導致內存占用較大,使得ES進程失去響應
腦裂解決
- 增加響應失效時間的閾值,減少誤判
- 參考zookeeper的過半數選舉,這也是ES官方推薦的模式,即選舉必須超過半數才能成為新的master
- 角色分離:master不擔任data節點(配置文件中是可以進行配置的)
底層流程
索引文檔流程
- 關鍵詞: 分片路由、緩存區與translog、refresh開發臨時段、flush持久化、合并段
更新和刪除文檔流程
其變更;
- 關鍵詞: 提交點邏輯刪除、結果過濾
搜索流程
搜索被執行成一個兩階段過程,我們稱之為 Query Then Fetch;
列中來產生一個全局排序后的結果列表。
- 關鍵詞: : 并行查詢,協調節點合并,評分與過濾
如何實現大數據聚合
通過HLL算法基于概率進行估算所得到的,精度是可控的
如何保證讀寫一致
- 可以通過版本號使用樂觀并發控制,以確保新版本不會被舊版本覆蓋,由應用層來處理具體的沖突;
- 另外對于寫操作,一致性級別支持 quorum/one/all,默認為 quorum,即只有當大多數分片可用時才允許寫操作。但即使大多數可用,也可能存在因為網絡等原因導致寫入副本失敗,這樣該副本被認為故障,分片將會在一個不同的節點上重建。
- 對于讀操作,可以設置 replication 為 sync(默認),這使得操作在主分片和副本分片都完成后才會返回;如果設置 replication 為 async 時,也可以通過設置搜索請求參數_preference 為 primary 來查詢主分片,確保文檔是最新版本。
- 關鍵詞 :樂觀鎖并發控制、多數分片可用才寫,主副分片都完成后才返回
如何監控集群狀態
elasticSearch-Head插件(丑的一批)
Kibana(屬實好看)
字典樹
字典樹又稱單詞查找樹,Trie 樹,是一種樹形結構,是一種哈希樹的變種。典型應用是用于統計,排
序和保存大量的字符串(但不僅限于字符串),所以經常被搜索引擎系統用于文本詞頻統計。它的優點是:利用字符串的公共前綴來減少查詢時間,最大限度地減少無謂的字符串比較,查詢效率比哈希樹高。
Trie 的核心思想是空間換時間,利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。
它有 3 個基本性質:
- 根節點不包含字符,除根節點外每一個節點都只包含一個字符。
- 從根節點到某一節點,路徑上經過的字符連接起來,為該節點對應的字符串。
- 每個節點的所有子節點包含的字符都不相同。
對于中文的字典樹,每個節點的子節點用一個哈希表存儲,這樣就不用浪費太大的空間,而且查詢速度上可以保留哈希的復雜度 O(1)。
名詞解釋
集群
集群是一個或多個節點(服務器)的集合,它們共同保存您的整個數據,并提供跨所有節點的聯合索
引和搜索功能。群集由唯一名稱標識,默認情況下為“elasticsearch”。此名稱很重要,因為如果節點設
置為按名稱加入群集,則該節點只能是群集的一部分。
節點
節點是屬于集群一部分的單個服務器。它存儲數據并參與群集索引和搜索功能。
索引
索引就像關系數據庫中的“數據庫”。它有一個定義多種類型的映射。索引是邏輯名稱空間,映射到一個或多個主分片,并且可以有零個或多個副本分片。 MySQL =>數據庫 Elasticsearch =>索引
文檔
文檔類似于關系數據庫中的一行。不同之處在于索引中的每個文檔可以具有不同的結構(字段),但
是對于通用字段應該具有相同的數據類型。 MySQL => Databases => Tables => Columns / Rows Elasticsearch => Indices => Types =>具有屬性的文檔
類型
類型是索引的邏輯類別/分區,其語義完全取決于用戶。
倒排文檔
倒排索引是搜索引擎的核心。搜索引擎的主要目標是在查找發生搜索條件的文檔時提供快速搜索。ES中的倒排索引其實就是 lucene 的倒排索引,區別于傳統的正向索引,倒排索引會再存儲數據時將關鍵詞和數據進行關聯,保存到倒排表中,然后查詢時,將查詢內容進行分詞后在倒排表中進行查詢,最后匹配數據即可
總結
以上是生活随笔為你收集整理的插件学习笔记:搜索引擎ElasticSearch的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字化项目建设管理难点分析与对策
- 下一篇: 高等数学复盘 | 第七册上册第一章——第