文档由索引(_index),类型(_type),惟一标识(_id) 组成,咱们为 _index(索引) 分配相关逻辑地址分片,该索引下的数据会根据索引以及类型计算哈希来分配数据存储的分片,文档内容为Json格式的文档体,注意文档中的字段名称不能包含英文的句号,实际处理过程当中这里最好不要包含符号,索引名称要用小写网络
规则:分布式
值得注意的是:
咱们要在建立索引的时候就肯定好主分片的数量 而且永远不会改变这个数量:由于若是数量变化了,那么全部以前路由的值都会无效,文档也再也找不到了大数据
以下 定义三个节点,咱们有2个主分片,每一个分片有2个副分片,为了保证数据完整性,ES会进行以下分布,这里咱们用绿色标识主分片,矩形标识副分片,那么会出现以下分布,保证每一个节点上都有完成的分片(主1 和主2 )数据.spa
一、Client 发送写操做到Node13d
问题:为何要发到Node1,好比新加入了一个节点,这节点间的有编排编号吗?,若是是访问带有主节点的,也能够访问Node2也能够,这之间有什么关联吗?code
答:每一个节点都有能力处理任意请求。 每一个节点都知道集群中任一文档位置,因此能够直接将请求转发到须要的节点上,一开始进来都是任意一个节点,这个节点知道位置后,会做为协调节点转发请求到对应的节点上。这里请求Node1是随机节点,知道文档存储在主分片2上转发到Node2,若是一开始就是Node2节点就不需转发了,而后协调数据同步后,返回Node1再返回客户端,写操做都会直接找主分区所在的节点,我有点怀疑直接进入Node3呢?blog
二、根据_id发现数据应该存在存在主分片2上,因而转到Node2,写入数据索引
问题:新建、索引和删除 请求都是 写 操做, 必须在主分片上面完成以后才能被复制到相关的副本分片,ES应该每一个节点上有应该有一个记录主分片分布的节点记录,若是设置的自动生成_id的状况,那么怎么去判断位置?路由
三、数据同步,写入Node2中的主分片2成功后,并行写入2个副分片,等待两个副分片都应答成功后,而后通知客户端,防止网络或者其余问题带来的数据不一致文档
ES会要求有必定的副分片数量才会执行写操做,结合上面的 同步副分区,能够设置
int( (primary + number_of_replicas) / 2 ) + 1 ,consistency 参数也能够设置 one(主分区ok便可写入) 、all(全部主、副分区所有ok才执行写入)、quorum 默认(大多数的主、副分区没问题便可写入,及上面的公式)
出现分布式就须要注意大数据一致性的问题以及,多修改数据丢失的问题?虽然上面的同步能处理数据最终一致性的问题,可是若是出现多我的修改,会致使数据掉丢失的状况。在实际过程咱们又怎么来避免这种状况呢?如又这么一组数据
数据data 在 update data1 update data2 2个同时操做的时候会致使数据丢失,加入先get到数据 都是data 可是在update1 update2不管哪一个先那个后实际上都会存在数据丢失 若是update1先,update2后,最后数据是 update2的 /myindex/mytable/123 { "myname":"liyouming“, "myage":25 } 若是update2先,update1后,最后数据是 update1的 /myindex/mytable/123 { "myname":"zhangsan“, "myage":22 } 可是实际上咱们须要的数据应该是这样 /myindex/mytable/123 { "myname":"zhangsan“, "myage":25 } 其实仔细想一想在咱们的实际业务管理系统中也会有这样的问题,若是两我的同时打开一个编辑界面同时修改,操做1 在不知道 操做2 修改内容的状况下直接修改,其中会覆盖一部分的数据丢失掉了
每一个文档都有一个 _version (版本)号,当文档被修改时版本号递增。 Elasticsearch 使用这个 _version 号来确保变动以正确顺序获得执行。若是旧版本的文档在新版本以后到达,它能够被简单的忽略,咱们能够利用 _version 号来确保 应用中相互冲突的变动不会致使数据丢失。
那么咱们在来看下上面的demo
在咱们查询出来的时候获取到版本号 _version 为1,在进行update1 或update2的时候带上咱们的版本号,那么其中后面执行的那个会出现修改失败,这么就能保证数据丢失的状况了,假定数据update2修改为功了,那么咱们获得的数据会是这样 data2 ,upate1失败后再次获取信息 获得版本为2 再次修改为功获得data1最终修改