elasticsearch核心概念

概述

Elasticsearch是一个分布式文档存储。 Elasticsearch不会将信息存储为列数据的行,而是存储已序列化为JSON文档的复杂数据结构。 当集群中有多个Elasticsearch节点时,存储的文档将分布在集群中,并且可以从任何节点立即访问。
在es中,如何去存储数据,es的数据结构是什么,如何实现搜索的?集群,节点,索引,类型,文档,分片,映射是什么?

es与关系型数据库对比

elasticsearch面向文档的,一个elasticsearch集群可以包含多个索引(数据库),每个索引可以包含多种类型(表),每个类型又可以包含多个文档(行),每个文档又可以包含多个字段(列)
elasticsearch与关系型数据库对比:

RelationalDB

elasticsearch

数据库(database)

索引(indices)

表(tables)

type(7版本以后会抛弃,默认_doc)

行(rows)

documents

字段(columns)

fields

elasticsearch物理设计

elasticsearch在后台把索引划分为多个分片,每个分片可以在集群中的不同服务器之间迁移。实际上,Elasticsearch索引实际上只是一个或多个物理分片的逻辑分组,其中每个分片实际上是一个自包含的索引。通过跨分片将多个文档分布在一个索引中,并将这些分片分布在多个节点上,Elasticsearch可以确保冗余,既可以防止硬件故障,又可以增加集群中节点的查询容量。随着集群的增长(或收缩),Elasticsearch可以自动迁移分片以重新平衡集群。
elasticsearch分片有两种类型:主分片和复制分片。索引中的每个文档都属于一个主分片。复制分片是主分片的副本。副本提供数据的冗余副本,以防止硬件故障,并增加处理读取请求(如搜索或检索文档)的容量。
索引中的主分片数量在创建索引时是固定的,但是复制分片的数量可以在任何时候更改,而不会中断索引或查询操作。

逻辑设计

一个索引文件中,包含多个文档,如文档1,文档2.当我们索引一片文章时,可以通过这样的顺序找到它:索引 >类型 >文档id。通过这个组合我们就能够索引到某个具体文档。该处id可以为字符串。

  • elasticsearch是面向文档的,也就是说为索引和搜索数据的最小单位是文档。
    elasticsearch中文档有几个重要属性:
  • 自我包含:一篇文档中包含字段和对应值,即同时包含key:value
  • 层次性: 一个文档中可以包含文档,适用于复杂的逻辑实体
  • 灵活的结构: 文档不依赖于事先预定义的模式,在关系型数据库中,需要提前定义好字段,才可以对数据进行操作。但在elasticsearch中,对于字段非常灵活,有时,我么可以忽略该字段,或者动态添加一给新的字段

虽然我们可以随意增加或者忽略某个字段,但每个字段的类型非常重要。例如一个年龄字段类型,可以是字符串也可以是整形。elasticsearch会保存字段和类型之间的映射以及其他的设置。映射过程具体到每个映射的每种类型。

类型是elasticsearch中文档的逻辑容器,同关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射。在elasticsearch中新增一个字段,其会自动的将新的字段加入映射。但这个字段不确定它是什么类型的。这是elasticsearch就会猜数据类型,如果这个值是18,那么elasticsearch就会认为他是整型。但elasticsearch也会猜不对,最安全的方式是提前定义好所需要的映射,这一点跟关系型数据库殊途同归,先定义好在使用。
索引对应着关系型数据库中的一个数据库。索引是映射类型的容器,elasticsearch的索引是一个非常大的文档合集,索引存储了映射类型字段和其他设置,然后把所以存到每个分片上。

物理设计 节点和分片

在这里插入图片描述
一个集群至少要有一个节点,一个节点就是elasticsearch进程,节点可以有多个默认索引。一个索引由5个分片(primary shard 主分片)构成的,每个主分片会有一个副本(replica shard 复制分片)
在这里插入图片描述
图中是一个三节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内。这种情况下,如果每个节点挂掉,相应数据不会丢失。事实上,一个分片就是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引结构会使得elasticsearch在不扫描全部文档的情况下,就检索出那些文档包含特定的关键字。

倒排索引

elasticsearch使用的是一种称为倒排索引的数据结构。采用lucene倒排索引作为底层适用于进行快速的全文搜索,一个索引有文档中多有不重复的列表构成。对于每一个词,都有包含它的文档列表。
倒排索引结构图:
在这里插入图片描述
倒排
假设有以下的数据:

docid

年龄

性别

1

18

2

20

3

18

对于这个索引来说,每一行都是一个document,每个document都有一个docid。给docid简历倒排索引:
年龄

18

[1,3]

20

[2]

性别

[1,2]

[3]

由上面表格可以知道,倒排索引是一个字段的,一个字段有一个子的倒排索引。18,20这些叫做term,[1,3]就是posting list就是一个int数组,存储了符合某个term的所有文档id。
term index以及term dictionary
假设我们有很多个term,比如:
Carla,Sara,Elin,Ada,Patty,Kate,Selena
如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍才能找出特定的term。排序之后就变成了:
Ada,Carla,Elin,Kate,Patty,Sara,Selena
这个时候我们可以用二分查找的方式,比全遍历更快地找出目标的term。这个就是 term dictionary。有了term dictionary之后,可以用 logN 次磁盘查找得到目标。但是磁盘的随机读操作仍然是非常昂贵的(一次random access大概需要10ms的时间)。所以尽量少的读磁盘,有必要把一些数据缓存到内存里。但是整个term dictionary本身又太大了,无法完整地放到内存里。于是就有了term index。term index有点像一本字典的大的章节表。比如:

A开头的term ……………. Xxx页

C开头的term ……………. Xxx页

E开头的term ……………. Xxx页

如果所有的term都是英文字符的话,可能这个term index就真的是26个英文字符表构成的了。但是实际的情况是,term未必都是英文字符,term可以是任意的byte数组。而且26个英文字符也未必是每一个字符都有均等的term,比如x字符开头的term可能一个都没有,而s开头的term又特别多。实际的term index是一棵trie 树:
在这里插入图片描述

这是一个包含 “A”, “to”, “tea”, “ted”, “ten”, “i”, “in”, 和 “inn” 的 trie 树。这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。再加上一些压缩技术(搜索 Lucene Finite State Transducers) term index 的尺寸可以只有所有term的尺寸的几十分之一,使得用内存缓存整个term index变成可能。
在这里插入图片描述
Mysql只有term dictionary这一层,是以b-tree排序的方式存储在磁盘上的。检索一个term需要若干次的random access的磁盘操作。而Lucene在term dictionary的基础上添加了term index来加速检索,term index以树的形式缓存在内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘的random access次数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值