Elastic Search 分布式索引介绍

一、Cluster:集群

Elastic Search可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,Elastic Search可以运行在许多互相合作的服务器上,这些服务器形成的整体称为集群。

二、Node:节点

形成集群的每个服务器称为节点

三、Shard:分片

分片,类似于数据库的分库操作。当文档的数量过大时,由于内存的限制、磁盘处理能力不足、无法够快的响应客户端的请求等,一个节点已经不能满足需求了,这种情况下,数据可以分为较小的分片,每个分片放到不同的节点上(说句废话,一般情况下,一个节点上应该只有一个主分片,但是一个节点上不仅只有一个分片,还可以有很多副本)。

当索引一个文档的时候,文档会被存储到一个主分片中。 那么,Elasticsearch是 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

当查询的索引分布在多个分片上时,ES会把查询发送给每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。

分片与路由

因为分布式索引会进行类似于数据库分库分表的操作。假如现在有2个分片,有4篇文档id分别为:1,2,3,4,根据取模算法,将他们分配到对应的表中。Elastic Search采取的也是这种思路。数据1和3 对2取模,等于 1,那么就会把1,3两个数据放到第2个分片上。2和4对2取模,等于0,那么就会把2,4两条数据放到第1个分片上。

查询数据的时候同理,查询1,3,根据取模运算结果,会去第2个分片上查找。查询2,4,会去第1个分片上查找。这个时候,修改了分片数目,取模运算结果与之前不一致,比如改成3个分片,那么查询3的时候,取模运算结果变成了0,就会去第1个分片上查找3,那么肯定查不到的。因此分片数不能随意修改,一旦修改,需要全部重建索引。

四、Replica:副本

Elastic Search中可以有许多相同的分片,其中之一可以进行编辑操作(如增删改),这种特殊的分片称为主分片。而副本是一个分片的精确复制,每个分片可以有零个或多个副本。

当主分片丢失时,如:该分片所在的数据不可用时,集群将副本提升为新的主分片。

number_of_replicas 副本数,用于备份分片的,和分片里面的数据保持一致,主要响应读操作,副本越多读取就越快。此外,副本数是可以修改的。但是在集群环境中,副本数应小于等于节点数减1,否则会降低集群的健康值。

我们前面说,一个节点应该只有一个主分片。但是实际中,我们需要预估一下将来的分片数,并且提前做规划。在《Elastic Search权威指南》中,提到了扩容设计。其中指出,在初期,我们可以只有一个节点,并且可以在该节点中建立多个主分片。当访问量增加,节点负荷过大时,我们可以增加新的节点,更加奇妙的是Elasticsearch 会自动将其中部分分片移动至到新的节点。就如下图所示

扩容设计

引自:https://www.elastic.co/guide/cn/elasticsearch/guide/current/overallocation.html

此外,新的版本的副本复制策略同6.6不太一样,具体可以参考https://www.jianshu.com/p/a164b86445b6

五、文档,元数据

1,文档

在大多数应用中,多数实体或对象可以被序列化为包含键值对的 JSON 对象。 一个 可以是一个字段或字段的名称,一个 可以是一个字符串,一个数字,一个布尔值, 另一个对象,一些数组值,或一些其它特殊类型诸如表示日期的字符串,或代表一个地理位置的对象

2,文档元数据

一个文档不仅仅包含它的数据 ,也包含 元数据 —— 有关 文档的信息。 三个必须的元数据元素如下:

  • _index

    文档在哪存放

    一个 索引 应该是因共同的特性被分组到一起的文档集合。 例如,你可能存储所有的产品在索引 products 中,而存储所有销售的交易到索引 sales 中。 虽然也允许存储不相关的数据到一个索引中,但这通常看作是一个反模式的做法。

    实际上,在 Elasticsearch 中,我们的数据是被存储和索引在 分片 中,而一个索引仅仅是逻辑上的命名空间, 这个命名空间由一个或者多个分片组合在一起。 然而,这是一个内部细节,我们的应用程序根本不应该关心分片,对于应用程序而言,只需知道文档位于一个 索引 内。 Elasticsearch 会处理所有的细节。

  • _type

    文档表示的对象类别

    数据可能在索引中只是松散的组合在一起,但是通常明确定义一些数据中的子分区是很有用的。 例如,所有的产品都放在一个索引中,但是你有许多不同的产品类别,比如 "electronics" 、 "kitchen" 和 "lawn-care"。

    需要注意的是,Elastic Search 6之后,_type 只有一个,而到了Elastic Search 7 之后,取消了 _type。

    为什么 _type 被移除了?

    起初,我们说"索引"和关系数据库的“库”是相似的,“类型”和“表”是对等的。这是一个不正确的对比,导致了不正确的假设。在关系型数据库里,"表"是相互独立的,一个“表”里的列和另外一个“表”的同名列没有关系,互不影响。但在类型里字段不是这样的。在一个Elasticsearch索引里,所有不同类型的同名字段内部使用的是同一个lucene字段存储。也就是说,上面例子中,user类型的user_name字段和tweet类型的user_name字段是存储在一个字段里的,两个类型里的user_name必须有一样的字段定义。这可能导致一些问题,例如你希望同一个索引中"deleted"字段在一个类型里是存储日期值,在另外一个类型里存储布尔值。最后,在同一个索引中,存储仅有小部分字段相同或者全部字段都不相同的文档,会导致数据稀疏,影响Lucene有效压缩数据的能力。因为这些原因,我们决定从Elasticsearch中移除类型的概念。

  • _id

    文档唯一标识

    ID 是一个字符串,当它和 _index 以及 _type 组合就可以唯一确定 Elasticsearch 中的一个文档。 当你创建一个新的文档,要么提供自己的 _id ,要么让 Elasticsearch 帮你生成。

    当Elastic Search7 取消 _type 之后,及 _index_id 即可确定唯一的文档。

五、文档,元数据

1,文档

在大多数应用中,多数实体或对象可以被序列化为包含键值对的 JSON 对象。 一个 可以是一个字段或字段的名称,一个 可以是一个字符串,一个数字,一个布尔值, 另一个对象,一些数组值,或一些其它特殊类型诸如表示日期的字符串,或代表一个地理位置的对象

2,文档元数据

一个文档不仅仅包含它的数据 ,也包含 元数据 —— 有关 文档的信息。 三个必须的元数据元素如下:

  • _index

    文档在哪存放

    一个 索引 应该是因共同的特性被分组到一起的文档集合。 例如,你可能存储所有的产品在索引 products 中,而存储所有销售的交易到索引 sales 中。 虽然也允许存储不相关的数据到一个索引中,但这通常看作是一个反模式的做法。

    实际上,在 Elasticsearch 中,我们的数据是被存储和索引在 分片 中,而一个索引仅仅是逻辑上的命名空间, 这个命名空间由一个或者多个分片组合在一起。 然而,这是一个内部细节,我们的应用程序根本不应该关心分片,对于应用程序而言,只需知道文档位于一个 索引 内。 Elasticsearch 会处理所有的细节。

  • _type

    文档表示的对象类别

    数据可能在索引中只是松散的组合在一起,但是通常明确定义一些数据中的子分区是很有用的。 例如,所有的产品都放在一个索引中,但是你有许多不同的产品类别,比如 "electronics" 、 "kitchen" 和 "lawn-care"。

    需要注意的是,Elastic Search 6之后,_type 只有一个,而到了Elastic Search 7 之后,取消了 _type。

    为什么 _type 被移除了?

    起初,我们说"索引"和关系数据库的“库”是相似的,“类型”和“表”是对等的。这是一个不正确的对比,导致了不正确的假设。在关系型数据库里,"表"是相互独立的,一个“表”里的列和另外一个“表”的同名列没有关系,互不影响。但在类型里字段不是这样的。在一个Elasticsearch索引里,所有不同类型的同名字段内部使用的是同一个lucene字段存储。也就是说,上面例子中,user类型的user_name字段和tweet类型的user_name字段是存储在一个字段里的,两个类型里的user_name必须有一样的字段定义。这可能导致一些问题,例如你希望同一个索引中"deleted"字段在一个类型里是存储日期值,在另外一个类型里存储布尔值。最后,在同一个索引中,存储仅有小部分字段相同或者全部字段都不相同的文档,会导致数据稀疏,影响Lucene有效压缩数据的能力。因为这些原因,我们决定从Elasticsearch中移除类型的概念。

  • _id

    文档唯一标识

    ID 是一个字符串,当它和 _index 以及 _type 组合就可以唯一确定 Elasticsearch 中的一个文档。 当你创建一个新的文档,要么提供自己的 _id ,要么让 Elasticsearch 帮你生成。

    当Elastic Search7 取消 _type 之后,及 _index_id 即可确定唯一的文档。

六、新建,索引,删除操作的基本逻辑

集群

假设我们如上面所示,上面每个节点都可以接收写请求,那么新增数据的一个流程如下所示:

步骤顺序如下:

(1) 客户端向Node1发送新建请求(如果客户端向Node2或者Node3等其他节点发送请求,请求会被转发给Master节点,本图中为Node1,更新,删除同理)。

(2) master根据_id确定文档属于分片0,那么请求会被转发到Node3,因为分片 0 的主分片目前被分配在 Node3上。

(3) Node 3在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node3 将向Master节点报告成功,Master节点向客户端报告成功(ES新版本是可用shard写入成功过半,Node3会发送消息给master,并由Master节点转发给请求来源节点)。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

七、查询的基本逻辑

以下是从主分片或者副本分片检索文档的步骤顺序:

1、客户端向 Node 1 发送获取请求。

2、节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2。在处理读取请求时,Master节点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡,因此会转发请求到Node 2

3、Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容