一. 接近实时(NRT Near Real Time )
Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒内)。
二. 索引
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。索引类似于关系型数据库中Database 的概念。在一个集群中,如果你想,可以定义任意多的索引。
三. 类型(type)
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数 据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可 以为评论数据定义另一个类型。类型类似于关系型数据库中Table的概念。
NOTE: 在5.x版本以前可以在一个索引中定义多个类型,6.x之后版本也可以使用,但是不推荐,在7~8.x版本中彻底移除一个索引中创建多个类型
四. 映射(Mapping)
Mapping是ES中的一个很重要的内容,它类似于传统关系型数据中table的schema,用于定义一个索引(index)中的类型(type)的数据的结构。 在ES中,我们可以手动创建type(相当于table)和mapping(相关与schema),也可以采用默认创建方式。在默认配置下,ES可以根据插入的数据自动地创建type及其mapping。 mapping中主要包括字段名、字段数据类型和字段索引类型
五. 文档(document)
一个文档是一个可被索引的基础信息单元,类似于表中的一条记录。比如,你可以拥有某一个员工的文档,也可以拥有某个商品的一个文档。文档以采用了轻量级的数据交换格式JSON(Javascript Object Notation)来表示。
六. 概念关系图
image.png七. 倒排索引
7.1 正排索引
与ElasticSearch所使用的倒排索引对应的“正排索引”
正排索引也称为“前向索引”,它是创建倒排索引的基础。
这种组织方法在建立索引的时候结构比较简单,建立比较方便且易于维护;因为索引是基于文档建立的,若是有新的文档加入,直接为该文档建立一个新的索引块,挂接在原来索引文件的后面。若是有文档删除,则直接找到该文档号对应的索引信息,将其直接删除。
他适合根据文档ID来查询对应的内容。但是在查询一个keyword在哪些文档里包含的时候需对所有文档进行扫描以确保没有遗漏,这样就使得检索时间大大延长,检索效率低下。
比如有几个文档及里面的内容,他正排索引构建的结果如下:
image.png
优点:工作原理非常简单。
缺点:检索效率太低,只能在一些简单的场景下使用。
7.2 倒排索引
本次学习的主角“倒排索引”,根据字面意思可以知道他和正序索引是反的。在搜索引擎中每个文件都对应一个文件ID,文件内容被表示为一系列关键词的集合(文档要除去一些无用的词,比如:“的”、”这些“,剩下的都是关键词,每个关键词都有自己的ID)。例如”文档1“经过分词,提取三个关键词,每个关键词都会记录他所在文档中出现的品率及出现的位置。
那么上面文档及内容构建的倒排索引结果会如下表(注:这个图里没有记录该词出现在哪个文档中的具体位置):
image.png
7.3 倒排索引的查询过程
比如我们要查询elasticsearch这个关键词在哪些文档中出现过。首先我们通过倒排索引可以查询到该关键词出现的文档位置是在1和3中;然后再通过正排索引查询到文档1和3的内容返回结果。
7.4 倒排索引的组成
倒排索引主要由单词词典Term Dictionary和倒排索引Posting List及倒排文件Inverted File组成。
关系图如下:
image.png
7.4.1 单词词典(Term Dictionary)
搜索引擎通常索引单位是单词,单词是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向倒排列表的指针。
7.4.2 倒排列表(Posting List)
倒排列表记载了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息及频率做关键性算分,每条记录称为一个倒排项Posting。根据倒排列表,即可获知哪些文档包含某个单词。
7.4.3 倒排文件(Inverted File)
所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件即被称之为倒排文件,倒排文件是存储倒排索引的物理文件。
7.4.4 以查找搜索引擎为例:
文档
image.png
查找过程
image.png
7.4.5 单词词典查询定位问题
对于一些规模很大的文档集合来说,它里面可能包括了上百万关键单词term,能否快速定位到具体单词term,这会直接影响到响应速度。
假设我们有很多个term,比如:
Carla, Sara, Elin, Ada, Patty, Kate, Selena
如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍才能找出特定的term,排序之后就变成了:
Ada, Carla, Klin, Kate, Patty, Sara, Selena
这样我们就可以用二分查找的方式,比全遍历更快的找出目标term,这个就是Term Dictionary。有了Term Dictionary之后,可以用logN次磁盘查找得到目标。但是磁盘的随机读操作仍然是非常昂贵的(一次 random access大概需要10ms的时间)。所以尽量少的读磁盘,有必要把一些数据缓存到内存里,但是整个Term Dictionary本身又太大了,无法完整地放到内存里。于是就有了Term Index。Term Index有点像一本字典的大的章节表。
目前常用的方式是通过hash加链表结构和树型结构(b树或者b+)
-
hash加链表
image.png
这是很常用的一种数据结构。这种方式就可以快速计算单词的hash值,从而定位到他所在的hash 表中,如果该表又是一个链表结构(两个hash值可能会一样),那么就需要遍历这个链表然后再对比返回结果。这种方式最大的缺点就是如果有范围查询的时候就很难做到。
-
树型结构
image.png
B树(或B+树)是另外一种高效查找结构,这是是一个B树结构示意图。B树与哈希方式查找不同,B树需要字典项能够按照大小排序(数字或字符序),而哈希方式则无需数据满足此项要求。
B树形成了层级查找结构,中间点用于指出一定顺序范围的词典项目存储在哪个子树中,起到根据词典项比较大小进行导航的作用,最底层的叶节点存储单词的地址信息,根据这个地址就可以提取出单词字符串。
7.5 分词器介绍以及中文分词器ik的安装与使用
7.5.1 分词的含义
把文本转换成一个个的单词,分词称之为analysis。es默认只对英文语句做分词,中文不支持,每个中文都会被拆分为独立的个体
示例
被分词对象:
返回结果:
image.png
7.5.2 如果想在某个索引下进行分词
POST /my_doc/_analyze
{
"analyzer": "standard",
"field": "name",
"text": "text文本"
}
7.5.3 es内置分词器
- standard:默认分词,单词会被拆分,大小写会转换为小写。
- simple:按照非字母分词,大写转为小写。
- whitespace:按照空格分词,忽略大小写。
- stop:去除无意义单词,比如the/a/an/is…
- keyword:不做分词,把整个文本作为一个单独的关键词
八. Shards
-
一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有10亿文档数据的索引占据1TB的磁盘空间,而任一节点都可能没有这样大的磁盘空间。或者单个节点处理搜索请求,响应太慢。为了解决这个问题ES提供了将索引划分成多份的能力,每一份就称之为分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的"索引",这个"索引"可以被放置到集群中的任何节点上。
-
分片很重要,主要有两方面的原因:
2.1)允许你水平分割/扩展你的内容容量。
2.2)允许你在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量。 -
至于一个分片怎样分布,它的文档怎样聚合和搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的,无需过分关心。
注意:
被混淆的概念是,一个 Lucene 索引 我们在 Elasticsearch 称作 分片 。 一个 Elasticsearch 索引 是分片的集合。 当 Elasticsearch 在索引中搜索的时候, 他发送查询到每一个属于索引的分片(Lucene 索引),然后合并每个分片的结果到一个全局的结果集。
九. Replicas
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片(副本)。
复制分片之所以重要,有两个主要原因:
- 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
- 扩展你的搜索量/吞吐量,因为搜索可以在所有的副本上并行运行。
总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。默认情况下,Elasticsearch中的每个索引被分片1个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有1个主分片和另外1个复制分片(1个完全拷贝),这样的话每个索引总共就有2个分片,我们需要根据索引需要确定分片个数。
Elasticsearch7.x 默认副本和默认分片
number_of_shards
每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。
number_of_replicas
每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。
十. Allocation
将分片分配给某个节点的过程,包括分配主分片或者副本。如果是副本,还包含从主分片复制数据的过程。这个过程是由master节点完成的。
网友评论