提到非结构化数据的检索,常常用到 ElasticSearch,他是什么呢?
ElasticSearch 是一个基于 Apache Lucene 的分布式搜索引擎,可以作为实时文档存储系统,且文档的每一个内容都可以被检索,能够处理 PB 级别的结构化和非结构化数据。
ElasticSearch 本身具有分布式特性的特点。
Apache Lucene
背景
Lucene 是为了解决大规模文本数据的高效检索问题而设计的。90 年代末,互联网的内容量飞速增加,企业的大量文本数据难以快速检索。虽然传统数据库可以处理这些数据,但是“全文检索”的支持有限,尤其是在复杂搜索(模糊匹配、词组查询、相关性排序)时效率低下。
99 年 Lucene 作为一个开源的全文检索库而问世,专门应对上述问题。Lucene 通过倒排索引结构,极大的提升了文本搜索的速度;并且内置了查询功能和打分机制,可以按相关性排序。
Lucene 的诞生是为了填补大规模文本数据快速、灵活检索的空缺。他在几十年后成为了搜索基础的基础,如分布式搜索引擎 ElasticSearch
优点:
- 倒排索引 → 高性能
- 布尔查询、模糊查询、词组查询 → 复杂信息检索
- 打分排序 → 相关性计算
缺点
- 使用复杂、缺乏分布式支持
1.名词解释
-
索引(Index) → 关系数据库中的 数据库
索引指的是包含一堆具有相似结构的文档数据 (Document) 。
如:商品索引、订单索引。在商品索引中,可以存放成千上万的商品信息;
-
类型(Type) → 关系数据库中的 表
(貌似 es 6.0 之后就不支持了,去除这个概念了)类型是索引内部的逻辑分区(category/partition),每个 Index 里都可以有一个或多个 type,type 是 Index 中的一个逻辑数据分类,一个 type 下的 document 有相同的 field。
如:商品索引中,服务和旅游路线,虽然都是可售卖的商品,但因为有很多属性不同,所以定义了两种 type;此外还可以为类目定义一个Type
服装商品的Type:商品名字、价格、描述
旅游路线商品的Type:商品名字、价格、描述、行程信息
-
文档&属性(Document&Field) → 关系数据库中的 一行记录 和 字段
一个 document 是一条实例数据。
例如一个商品,一个订单,通常使用 JSON 数据格式表示。一个 document 里面有多个 field,每个 field 就是一个数据字段。
{ _Index: "twitter", _type: "_doc", _id: "1", _version: 1, _seq_no: 0, _primary_term: 1, found: true, _source: { user: "kimchy", post_date: "2009-11-15T13:12:00", message: "Trying out Elasticsearch, so far so good?" } }
-
词条(Term)
索引里最小的存储和查询单元。
对于英文来说是一个单词,对于中文来说一般指分词后的一个词。
-
词典(Term Dictionary)
即字典,是词条 term 的集合。
搜索引擎通常的索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。
-
正排数据
搜索引擎的通用叫法,即原始数据,可以理解为一个 doc list。
-
倒排数据
lucenne 索引的通用叫法,即实现了 term 到 doc list 的映射。
倒排索引建立的是 分词(Term) 和 文档(Document) 之间的映射关系,在倒排索引中,数据是面向词(term) 而不是 面向文档的。
-
倒排表(Post list)
一个文档通常由多个词组成,倒排表记录的是某个词在那些文档里出现过以及出现的位置。
每条记录称为一个倒排项(Posting)。
倒排表记录的不单是文档编号,还存储了词频等信息。
-
倒排文件(Inverted File)
所有单词的倒排列表往往顺序的存储在磁盘的某个文件里,这个文件称之为倒排文件,倒排文件是存储倒排索引的物理文件。
2.索引原理
2.1倒排索引的结构
原始文档如下
Doc1: I love China。
Doc2: I love work。
Doc3: I love coding。
为了创建倒排索引,
- 首先通过分词器将每个文档的内容域拆分成单独的词(Term),
- 创建一个包含所有不重复词条的排序列表,
- 然后列出每个词条出现在哪个文档。
如下
Term | Doc1 | Doc2 | Doc3 |
---|---|---|---|
I | Y | Y | Y |
China | Y | ||
coding | Y | ||
love | Y | Y | Y |
work | Y |
这种结构由文档中所有不重复的列表构成,对于其中每个词都有一个 Doc 与之关联。
这种由属性值来确定记录的位置的结构就是倒排索引(Post Index)。
带有倒排索引的文件称之为倒排文件(Inverted file)
2.2 搜索
下面举例说明倒排索引如何高效
-
创建倒排索引
假设有一张学生成绩表
id name gender score 1 Fern female 80 2 Alice female 70 3 Bunny male 90 4 Aimee female 70 5 Amy female 80 6 tracy female 90 数据存到 ES 后,会建立以下倒排索引:
Name
Term Posting List Aimee 4 Alice 2 Amy 5 Bunny 3 Fern 1 tracy 6 Gender
Term Posting List female [1,2,4,5,6] male 3 Score
Term Posting List 70 [2,4] 80 [1,5] 90 [3,6] 以上为词条和倒排索引的关系,即当搜索 score=70 的时候,通过倒排索引能直接找到 [2,4] 记录,然后返回对应的记录。
-
词典
词典是词条的集合,当词条很多的时候,ES 如何高效查询呢?
在 Mysql 数据库中也有类似问题,当记录很多的时候,Mysql 的做法是创建索引,Mysql 的索引是使用 B+ 树实现的,如果查询条件能用上索引,那么就可以直接将查询条件 和索引进行匹配,因为索引是 B+ 树,所以查询效率也非常高。
ES 的做法也类似,即对上述词条排序,然后通过二分查找法将时间复杂度降到 l o g N logN logN
假设 name 取值如下:
Fern, Alice, Bunny, Aimee, Amy, tracy
排序后
Aimee, Alice, Amy, Bunny, Fern, tracy
Mysql 的索引存储在磁盘上,ES 的词典存储在内存中,按照上面的做法,ES 虽然可以解决查询效率问题,但是他会引起另一个问题:当 Term (词条) 很多时,内存必定无法容纳这些词条,那 ES 时如何处理这个问题的呢?
ES 的做法是创建 Term Index。
上面的 Term 都是英文字母,但实际情况是,term 可以任意的 byte 数组;另外,很多时候 term 数量对应的内容未必均衡,如图所示:C 字符开头的 term 一个没有,而 A 开头的 term 特别多。Lucene 内部的 Term Index 用的是变种 trie 树,即 FST(finite-state transducer),trie 树只共享了前缀,而 FST 既共享前缀也共享后缀,更节省空间。
关于 FST 的原理比较复杂,这里了解他在这里的核心作用:高效的查找到词条(Term)。
通过 Term Index 可以快速定位到 Term Dictionary 的某个 offset,然后从这个位置在往后顺序查找。
再加上一些压缩技术(搜索 FST),Term Index 的尺寸可以只有 所有 Term 的尺寸的几十分之一,使得内存缓存整个 Term Index 变成了可能。
如图所示,Term Index 主要解决的是快速定位到 Term,和现实中的字典或通讯录比较类似,例如,可以直接通过字母 W 快速找到 W 开头的姓氏。
3.教程
-
linux上安装
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.15.3-linux-x86_64.tar.gz wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.15.3-linux-x86_64.tar.gz.sha512 shasum -a 512 -c elasticsearch-8.15.3-linux-x86_64.tar.gz.sha512 tar -xzf elasticsearch-8.15.3-linux-x86_64.tar.gz cd elasticsearch-8.15.3/
-
MaxOS 上安装
curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.15.3-darwin-x86_64.tar.gz curl https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.15.3-darwin-x86_64.tar.gz.sha512 | shasum -a 512 -c - tar -xzf elasticsearch-8.15.3-darwin-x86_64.tar.gz cd elasticsearch-8.15.3/
3.运行 ElasticSearch 在命令行
./bin/elasticsearch
- 这里一定要注意密码
首次启动 Elasticsearch 时,默认情况下会启用并配置安全功能。以下安全配置会自动发生:
- 启用认证和授权,并为 elastic 内置超级用户生成密码。
- 为传输层和 HTTP 层生成 TLS 的证书和密钥,并使用这些密钥和证书启用和配置 TLS。
- 为 Kibana 生成注册令牌,有效期为 30 分钟。
Elastic 用户的密码和 Kibana 的注册令牌将输出到您的终端。
我们建议将 elastic 密码存储为 shell 中的环境变量。例如:
export ELASTIC_PASSWORD="your_password"
-
检查 Elasticsearch 是否运行
curl --cacert $ES_HOME/config/certs/http_ca.crt -u elastic:$ELASTIC_PASSWORD https://localhost:9200
转载自阿里云:https://developer.aliyun.com/article/775303