lucene、Solr、Elasticsearch
1、倒排序索引
2、Lucene是類庫
3、solr基於lucene
4、ES基於lucene
一、Elasticsearch 核心術語
特點:
1、es可以支持空格查詢,多個關鍵字
2、空格支持
3、拆詞查詢
4、搜索內容可以高亮
5、海量數據查庫
ES 可以對照着 數據庫 來理解:
- 索引index --------> 表
- 文檔 document --------> 行(記錄)
- 字段 fields --------> 列
Elasticsearch的存儲形式:
stu_index { id: 1001, name: jason, age: 19 }, { id: 1002, name: tom, age: 18 }, { id: 1003, name: rose, age: 22 }
集群相關
- 分片(shard):把索引庫拆分為多份,分別放在不同的節點上,比如有3個節點,3個節點的所有數據內容加在一起是一個完整的索引庫。分別保存到三個節點上,目的為了水平擴展,提高吞吐量。
- 備份(replica):每個shard的備份。
簡稱
shard = primary shard(主分片)
replica = replica shard(備份節點)
二、ES集群架構原理
加入有3TB的數據那么ES向上面的架構模型,每個shard會承擔1TB的數據,當一個ES的shard出現故障,那么它的replica就會成為它的角色。
shard和replica機制
A、index包含多個shard
B、每個shard都是一個最小工作單元,承載部分數據,lucene實例,完整地建立索引和處理請求的能力
C、增加或減少節點時,shard會自動地在node中負載均衡
D、primary shard和replica shard,每個document肯定只存在於某一個primary shard以及其對應的replica shard 中,不可能存在於多個primary shard
E、replica shard是primary shard 的副本,負責容錯以及承擔讀請求負載
F、primary shard的數量在創建索引的時候就固定了,replica shard的數量可以隨時修改
G、primary shard不能和自己的replica shard放在同一節點上,但是可以和其它primary shard放在同一節點上
三、倒排索引
ES為什么這么快?
1、索引方式的區別,es主要是利用倒排索引(inverted index),這個翻譯可能會讓初次接觸的人產生誤解,誤以為是倒着排序?其實不是這樣,一般關系型數據庫索引是把某個字段建立起一張索引表,傳入這個字段的某個值,再去索引中判斷是否有這個值,從而找到這個值所在數據(id)的位置。而倒排索引則是把這個值所在的文檔id記錄下來,當輸入這個值的時候,直接查詢出這個值所匹配的文檔id,再取出id。所以我們在建立es索引的時候,有分詞的概念,相當於可以把filed字段內容拆分,然后索引記錄下來。例如“我愛中國”,可以拆分成“我”,“愛”,“中國”,“我愛中國”這五個詞,同時記錄下來這幾個關鍵詞的對應文檔數據id是1,當我們查詢“我”,“中國”時,都能查出這條數據。而如果使用關系型數據庫去查包含“中國”這個關鍵字的數據的時候,則需要like前后通配全表掃描,無法快速找到關鍵詞所在的數據行。
2、倒排索引是不可更改的,一旦它被建立了,里面的數據就不會再進行更改。這樣做就帶來了以下幾個好處:
- 不用給索引加鎖,因為不允許被更改,只有讀操作,所以就不用考慮多線程導致互斥等問題。
- 索引一旦被加載到了緩存中,大部分訪問操作都是對內存的讀操作,省去了訪問磁盤帶來的io開銷。
- 倒排索引具有不可變性,所有基於該索引而產生的緩存也不需要更改,因為沒有數據變更。
- 倒排索引可以壓縮數據,減少磁盤io及對內存的消耗。
倒排索引結構:
如圖左邊為存儲結構,右邊為倒排索引,將左邊的每條文檔值內容進行分詞並且記錄詞頻和位置,比如我們現在搜索“集群”兩字就會直接按照文檔ids進行搜索,得到文檔1、2、3條記錄,搜索“學習”會得到文檔1、3兩條記錄。
四、Elasticsearch安裝
1.下載Elasticsearch Linux版安裝包
官網下載太慢,直接使用我下載好的安裝包
鏈接:https://pan.baidu.com/s/1Na0K7hIFJbGECD9XCwdR4A
提取碼:9oz6
復制這段內容后打開百度網盤手機App,操作更方便哦
2.安裝
- 解壓
tar -zxvf elasticsearch-7.10.1-linux-x86_64.tar.gz
- 將解壓的文件移動到 /usr/local下面
mv elasticsearch-7.10.1 /usr/local
- 進入目錄查看
cd /usr/local/elasticsearch-7.10.1 ll
- ES 目錄介紹
bin:可執行文件在里面,運行es的命令就在這個里面,包含了一些腳本文件等
config:配置文件目錄
JDK:java環境
lib:依賴的jar,類庫
logs:日志文件
modules:es相關的模塊
plugins:可以自己開發的插件
data:這個目錄沒有,自己新建一下,后面要用 -> mkdir data,這個作為索引目錄
- 修改核心配置文件 elasticearch.yml
- 修改集群名稱,默認是elasticsearch,雖然目前是單機,但是也會有默認的
- 為當前的es節點取個名稱,名稱隨意,如果在集群環境中,都要有相應的名字
- 修改data數據保存地址
- 修改日志數據保存地址
5.綁定es網絡ip,原理同redis
6.默認端口號9200,可以自定義修改
7.集群節點,名字可以先改成之前的那個節點名稱
- 修改JVM參數
默認xms和xmx都是1g,我使用的是虛擬機內存沒這么大,修改一下即可
vim jvm.options
- 添加用戶
ES不允許使用root操作es,需要添加用戶,操作如下:
useradd esuser chown -R esuser:esuser /usr/local/elasticsearch-7.4.2 whoami
- 解決啟動保存問題
- 修改 limits.conf 文件
vim /etc/security/limits.conf
在尾部添加如下內容
* soft nofile 65536 * hard nofile 131072 * soft nproc 2048 * hard nproc 4096
2. 修改 sysctl.conf 文件
vim /etc/sysctl.conf
在下面添加如下內容
vm.max_map_count=262145
- 啟動
- 切換到剛才創建的用戶下
su esuser
2. 到ES的bin目錄下面
cd /usr/local/elasticsearch-7.10.1/bin
3.啟動
./elasticsearch ## 前台啟動
./elasticsearch -d ## 后台啟動
- 測試
在瀏覽器輸入 虛擬器IP + ES端口號
9200:Http協議,用於外部通訊
9300:Tcp協議,ES集群之間是通過9300通訊
http://192.168.2.223:9200/
成功
- 安裝ES可視化工具ES-Header
github地址:https://github.com/mobz/elasticsearch-head
為方便起見我使用Google插件進行安裝,備注:需要能谷歌上網
安裝完成后如下所示為用ES-Header查看我們剛才安裝后的ES節點信息:
- 解決跨域問題
在 elasticearch.yml 中加入如下內容即可:
http.cors.enabled: true
http.cors.allow-origin: "*"
五、ES文檔的基本操作--增刪改查
1、增加操作
- 在可視化工具中建一個索引命名為 my_doc
- 手動添加文檔數據
http://192.168.2.223:9200/my_doc/_doc/1 { "id": 1001, "name": "zhouhong-1", "desc": "zhouhong is my good fridend!", "create_date": "2021-02-19" } http://192.168.2.223:9200/my_doc/_doc/2 { "id": 1002, "name": "zhouhong-2", "desc": "zhouhong 是一個好人", "create_date": "2021-02-18" } http://192.168.2.223:9200/my_doc/_doc/3 { "id": 1003, "name": "zhouhong-3", "desc": "zhouhong 真的是一個好人", "create_date": "2021-02-18" } http://192.168.2.223:9200/my_doc/_doc/4 { "id": 1004, "name": "zhouhong-4", "desc": "zhouhong is her friend", "create_date": "2021-02-18" } http://192.168.2.223:9200/my_doc/_doc/5 { "id": 1005, "name": "zhouhong-5", "desc": "zhouhong is 好人", "create_date": "2021-02-18" } http://192.168.2.223:9200/my_doc/_doc/6 { "id": 1006, "name": "zhouhong-6", "desc": "zhouhong is realy good man", "create_date": "2021-02-18" }
- 檢查是否添加成功
2、刪除
3、修改請求
{ "doc": { "name" "周紅" } }
4、查詢
- 根據文檔id查詢
{ "_index": "my_doc", "_type": "_doc", "_id": "6", "_version": 2, "_seq_no": 17, "_primary_term": 1, "found": true, "_source": { "id": 1006, "name": "zhouhong-6", "desc": "zhouhong is realy good man", "create_date": "2021-02-18" } }
- 查詢所有
- 查詢部分數據
- 判斷當前索引是否存在文檔,以下方式比較規范
六、ES分詞器
ES默認只支持英文分詞,如果是中文它會拆分為一個一個字
1、默認分詞器
a.分詞器(會忽略大小寫):
- 標准分詞器standard(把單詞進行分割)
- 簡單分詞器simple(會去除字符串中非字母的元素)
- 空格分詞器whitespace(根據空格進行分割)
- stop(會去除英文語句中的無意義的單詞:the 、is、a等等)
- keyword(會將整個文本當作一個詞,不會被拆分)
b.標准分詞器演示:
{ "analyzer": "standard", "text": "zhouhong is a good man!" }
{ "tokens": [ { "token": "zhouhong", "start_offset": 0, "end_offset": 8, "type": "<ALPHANUM>", "position": 0 }, { "token": "is", "start_offset": 9, "end_offset": 11, "type": "<ALPHANUM>", "position": 1 }, { "token": "a", "start_offset": 12, "end_offset": 13, "type": "<ALPHANUM>", "position": 2 }, { "token": "good", "start_offset": 14, "end_offset": 18, "type": "<ALPHANUM>", "position": 3 }, { "token": "man", "start_offset": 19, "end_offset": 22, "type": "<ALPHANUM>", "position": 4 } ] }
2、IK中文分詞器
1.安裝
- 將壓縮包解壓到ES下的 plugins 下
unzip elasticsearch-analysis-ik-7.10.1.zip -d /usr/local/elasticsearch-7.10.1/plugins/ik
2.測試
- 使用 ik_max_word(最細粒的拆分) 測試
{ "analyzer": "ik_max_word", "text": "明天早上吃什么呢" }
{ "tokens": [ { "token": "明天", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 0 }, { "token": "早上", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 1 }, { "token": "吃什么", "start_offset": 4, "end_offset": 7, "type": "CN_WORD", "position": 2 }, { "token": "什么", "start_offset": 5, "end_offset": 7, "type": "CN_WORD", "position": 3 }, { "token": "呢", "start_offset": 7, "end_offset": 8, "type": "CN_CHAR", "position": 4 } ] }
- 使用 ik_smart 分詞器測試
{ "analyzer": "ik_smart", "text": "明天早上吃什么呢" }
{ "tokens": [ { "token": "明天", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 0 }, { "token": "早上", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 1 }, { "token": "吃什么", "start_offset": 4, "end_offset": 7, "type": "CN_WORD", "position": 2 }, { "token": "呢", "start_offset": 7, "end_offset": 8, "type": "CN_CHAR", "position": 3 } ] }
3、自定義中文分詞器
{ "analyzer": "ik_max_word", "text": "周紅" } { "tokens": [ { "token": "周", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR", "position": 0 }, { "token": "紅", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR", "position": 1 } ] }
- 在IK分詞器安裝目錄下面的配置文件,增加一個custom.dic的字典文件
vim /usr/local/elasticsearch-7.10.1/plugins/ik/config/IKAnalyzer.cfg.xml
- 在同級目錄下新建一個custom.dic文件里面寫上我們不需要拆分的詞
- 測試
{ "analyzer": "ik_max_word", "text": "周紅" }
{ "tokens": [ { "token": "周紅", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 0 } ] }
后面如果想擴展,只需在自定義的custom.dic里面添加詞匯即可