目录
一、简介
Elasticsearch 是一个实时的分布式搜索分析引擎,它能让你以前所未有的速度和规模,去探索你的数据。 它被用作全文检索、结构化搜索、分析以及这三个功能的组合。
二、主要功能(搜索&聚合)
-
海量数据的分布式存储以及集群管理
服务于数据的高可用,水平扩展
-
近实时搜索,性能卓越
结构化/全文/地理位置/自动完成
-
海量数据的近实时分析
聚合功能
三、基本概念
1.文档
(1)ES是面向文档的,文档是左右可搜索数据的最小单位
(2)文档会被序列化成JSON格式,保存在ES中
(3)每个文档都有一个Unique ID
(4)一个文档不仅仅包含它的数据 ,也包含 元数据 —— 有关 文档的信息。 三个必须的元数据元素如下:
_index 文档在哪存放
_type 文档表示的对象类别
_id 文档唯一标识:创建一个新的文档,要么提供自己的 _id ,要么让 Elasticsearch 帮你生成。
例子:
{
"_index" : "website", // 索引
"_type" : "blog", // 类型
"_id" : "123", // id
"_version" : 1, // 更新版本
"found" : true,
"_source" : { // 索引数据时发送给Elasticsearch的原始JSON文档
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
2. 索引(名词)
索引是文档的容器,是一类文档的结合
在 Elasticsearch 中,我们的数据是被存储和索引在 分片 中,而一个索引仅仅是逻辑上的命名空间, 这个命名空间由一个或者多个分片组合在一起。 然而,这是一个内部细节,我们的应用程序根本不应该关心分片,对于应用程序而言,只需知道文档位于一个 索引 内,Elasticsearch 会处理所有的细节。(理解,类似于OS的逻辑地址和物理地址)
3. 索引(动词)
倒排索引:
关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。
+ 默认的,一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。我们将在 倒排索引 讨论倒排索引的更多细节。
理解:一个索引对应Mysql中的一个表,一个文档对应Mysql表中的一行数据
4. 分布式特性
Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:
-
分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
-
按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
-
复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
-
将集群中任一节点的请求路由到存有相关数据的节点
-
集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复
四、集群内的原理
1.节点扩容
ElasticSearch 的主旨是随时可用和按需扩容。 而扩容可以通过购买性能更强大( 垂直扩容 ,或 纵向扩容 ) 或者数量更多的服务器( 水平扩容 ,或 横向扩容 )来实现。
虽然 Elasticsearch 可以获益于更强大的硬件设备,但是垂直扩容是有极限的。 真正的扩容能力是来自于水平扩容—为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中。
2. 集群
一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。
3. 主节点
当一个节点被选举成为主节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。
作为用户,我们可以将请求发送到集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的
4. 集群健康
Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是集群健康 。status 字段指示着当前集群在总体上是否工作正常:
green //所有的主分片和副本分片都正常运行。
yellow //所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red //有主分片没能正常运行。
5. 添加索引
我们往 Elasticsearch 添加数据时需要用到 索引 —— 保存相关数据的地方。 索引实际上是指向一个或者多个物理分片的逻辑命名空间 。
【分片】一个分片是一个底层的工作单元 ,它仅保存了全部数据中的一部分。 一个分片是一个 Lucene 的实例,它本身就是一个完整的搜索引擎。
文档被存储和索引到分片内,但是应用程序是直接与索引而不是与分片进行交互。
Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。
一个分片可以是主分片或者副本分片。 在索引建立的时候就已经确定了主分片数,但是副本分片数可以随时修改。
【主分片】索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。
【主分片容量】技术上来说,一个主分片最大能够存储 Integer.MAX_VALUE - 128 个文档,但是实际最大值还需要参考你的使用场景:包括你使用的硬件, 文档的大小和复杂程度,索引和查询文档的方式以及你期望的响应时长。
【副分片】一个副本分片只是一个主分片的拷贝。副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。
6. 添加故障转移
当集群中只有一个节点在运行时,意味着会有一个单点故障问题——硬件故障时有丢失数据的风险。
把副本分配到别节点上存储,保证了我们既可以从主分片又可以从副本分片上获得文档。使得集群现在不仅仅是正常运行的,并且还处于始终可用的状态。
7. 水平扩容
根据节点和容量和主分片的容量及个数,可以增多副本分片(比如每个主分片两个副本)。
注意:如果只是在相同节点数目的集群上增加更多的副本分片并不能提高性能,因为每个分片从节点上获得的资源会变少。 你需要增加更多的硬件资源来提升吞吐量。
但是更多的副本分片数提高了数据冗余量:按照上面的节点配置,我们可以在失去2个节点的情况下不丢失任何数据。
8. 应对故障
当一个节点出现故障时:
if(其为主节点): 为剩余的节点重新选举主节点;
if(其他节点保有完整副本) :则集群可正常运行,status = yellow;
else :不能正常运行;
当故障节点恢复时:
集群可以将缺失的副本分片再次进行分配。如果故障节点依然拥有着之前的分片,它将尝试去重用它们,同时仅从主分片复制发生了修改的数据文件。
五、冲突处理
Q:在同时读写ES是可能因为冲突出现操作遗失的问题的,怎么解决?
A:乐观并发控制
Elasticsearch 是分布式的。当文档创建、更新或删除时, 新版本的文档必须复制到集群中的其他节点。
Elasticsearch 也是异步和并发的,这意味着这些复制请求被并行发送,并且到达目的地时也许顺序是乱的 。
Elasticsearch 需要一种方法确保文档的旧版本不会覆盖新的版本。
当我们之前讨论 index , GET 和 delete 请求时,我们指出每个文档都有一个 _version (版本)号,当文档被修改时版本号递增。 Elasticsearch 使用这个 _version 号来确保变更以正确顺序得到执行。如果旧版本的文档在新版本之后到达,它可以被简单的忽略。
我们可以利用 _version 号来确保 应用中相互冲突的变更不会导致数据丢失。我们通过指定想要修改文档的 version 号来达到这个目的。 如果该版本不是当前版本号,我们的请求将会失败。
六、文档操作的常见错误返回
问题 | 原因 |
---|---|
无法连接 | 网络故障或集群挂了 |
连接无法关闭 | 网络故障或节点出错 |
429 | 集群过于繁忙 |
4XX | 请求体格式有错 |
500 | 集群内部错误 |
七、分布式文档存储
Q: 如何决定文档被存储在哪个分片中?
A: 路由一个文档到分片中,设置routing。
我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。注意,相同分片的副本不会放在同一节点。
当发送请求的时候, 为了扩展负载,更好的做法是轮询集群中所有的节点。
八、映射和分析
1.倒排索引
倒排索引包含两个部分:
-
单词词典:记录所有文档的单词,记录单词到倒排列表的关联关系 (单词词典一般比较大,可以通过B+树或哈希拉链法实现,已满足高性能的插入和查询)
-
倒排列表:记录了单词对应的文档结合,由倒排索引项组成
2. 分析与分析器