#Elasticsearch学习笔记(三)Elasticsearch集群分片的读写操作流程
在上篇文章中详细介绍了Elasticsearch基于Lucene的单节点的准实时索引的实现,那么Elasticsearch是如何解决分布式下面的CRUD操作的呢?
## 1、路由计算(routing)和副本一致性(replica)
**routing**
Elasticsearch针对路由计算选择了一个很简单的方法,计算如下:
routing = hash(routing) % number_of_primary_shards
每个数据都有一个routing参数,默认情况下,就使用其_id值,将其_id值计算hash后,对索引的主分片数取余,
就是数据实际应该存储到的分片ID
由于取余这个计算,完全依赖于分母,所以导致Elasticsearch索引有一个限制,索引的主分片数,不可以随意修改。因为一旦主分片数不一样,索引数据不可读。
副本一致性(replica)
作为分布式系统,数据副本可算是一个标配。Elasticsearch数据写入流程。自然涉及副本,在有副本配置的情况下,数据从发向Elasticsearch节点,到接到Elasticsearch节点响应返回,流向如下
![](https://box.kancloud.cn/2016-03-10_56e11d2527f66.jpg)
1)客户端请求发送给Node1节点,这里也可以发送给气他节点
2)Node1节点用数据的_id计算出数据应该存储在shard0上,通过cluster state信息发现shard0的主分片在Node3节点上,Node1转发请求数据给Node3,Node3完成数据的索引,索引过程在上篇博客中详细介绍了。
3)Node3并行转发数据给分配有shard0的副本分片Node1和Node2上。当收到任一节点汇报副本分片数据写入成功以后,Node3即返回给初始的接受节点Node1,宣布数据写入成功。Node1成功返回给客户端。
新建、索引和删除都是写(write)操作,他们必须在主分片上成功完成才能赋值到相关的复制分片上。
replication:通过在客户端发送请求的URL中加入?replication=async,可以控制Node3在完成本机主分片写入后,就返回给Node1宣布写入成功。这个参数在2.0版本中已经被废弃
consistency:默认主分片在尝试写入时需要规定数量(quorum)或过半的分片(可以使主分片或复制分片)写入成功,就返回给客户端。consistency允许为one(只有一个主分片,与上面的replication等同)
`int((primary+number_of_replica) / 2) +1`
默认只有一个分片,那么就必须要两个活动分片,当然,这个默认设置将阻止我们在单一节点集群中进行操作。为了避开这个问题,规定数量只有在number_of_replicas大于1时才生效,也就是默认分片情况下不生效。
timeout:如果集群出现异常,有些分片当前不可用,Elasticsearch默认会等待1分钟,看分片能否恢复,
副本设置和分片设置不一样,是可以随时调整的,有些较大的索引,甚至可以做optimize之前,先把副本全部取消掉,等optimize完成后,再重新打开开启副本,节约单个segment的重复归并消耗。
## 2、shard的allocate配置
上文介绍了分片的索引过程,通过路由计算可以确定文本所在的分片id,那么分片在集群中的分配策略是如何确定的?
一般来说,某个shard分配在哪个节点上,是由Elasticsearch自动决定的。以下几种情况会触发分配动作。
- 新索引生成。
- 索引的删除
- 新增副本分片
- 节点增减引发的数据均衡
Elasticsearch还提供了一系列参数详细控制这部分逻辑:
cluster.routing.allocation.enable参数用来允许分配哪种分片。默认是All,可选项还包括primaries和new_primaries。none则彻底拒绝分片。
cluster.routing.allocation.allow_rebalance参数用来控制什么时候允许数据均衡。默认是indices_all_active,即要求所有分片都正常启动成功以后,才可以进行数据均衡操作,否则的话,在集群重启阶段,会浪费太多流量了。
cluster.routing.allocation.cluster_concurrent_rebalance参数用来控制集群内同时启动的数据均衡任务个数。默认是2个。