Elastic search 分片原理
es具有丰富的扩容机制,能够实现文档的分布式存储。
路由
当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?
首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。
分片
- 一个分片的底层即为一个 Lucene 索引,会消耗一定文件句柄、内存、以及 CPU 运转。
- 每一个搜索请求都需要命中索引中的每一个分片,如果每一个分片都处于不同的节点还好,但如果多个分片都需要在同一个节点上竞争使用相同的资源就有些糟糕了。
- 用于计算相关度的词项统计信息是基于分片的。如果有许多分片,每一个都只有很少的数据会导致很低的相关度。
分片预分配:
一个分片存在于单个节点, 但一个节点可以持有多个分片。
PUT /my_index
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
}
}
假设只有一个节点node1,设置分片数为2。两个分片均位于node1上,如果增加一个node2,此时Elasticsearch 会自动将其中一个分片移动至第二个节点
副本分片
- 如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。
- 在索引写入时,副本分片做着与主分片相同的工作。新文档首先被索引进主分片然后再同步到其它所有的副本分片。增加副本数并不会增加索引容量。
- 搜索性能取决于最慢的节点的响应时间,所以尝试均衡所有节点的负载是一个好想法。 如果我们只是增加一个节点而不是两个,最终我们会有两个节点各持有一个分片,而另一个持有两个分片做着两倍的工作。
扩容
通过reroute api 重新分配replica到指定的节点
##解决unassigned shards
POST _cluster/reroute?retry_failed=true
{
"commands": [
{
"allocate_replica": {
"index": "topic_v1",
"shard": 2,
"node": "ACN-backend-elasticsearch-online017-bdwg.qiyi.virtual:9300"
}
}
]
}