Elasticsearch 使用分片路由算法确定文档应该写入哪个主分片。 具体如何实现的

发布于:2025-07-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

Elasticsearch 分片路由算法的实现机制

Elasticsearch 通过 分片路由算法 确定文档应该写入哪个主分片,核心逻辑如下:


1. 路由公式

Elasticsearch 使用以下公式计算目标分片位置:

text

shard_num = hash(_routing) % number_of_primary_shards
  • _routing:路由键(默认等于文档 _id,可自定义)。

  • number_of_primary_shards:主分片数量(索引创建时固定,不可修改)。


2. 关键步骤
(1)路由键选择
  • 默认行为:使用文档的 _id 作为 _routing 值。

    json

    PUT my_index/_doc/1   // _id=1 作为路由键
    { "name": "foo" }
  • 自定义路由:可通过 routing 参数指定(如按用户ID分片)。

    json

    PUT my_index/_doc/2?routing=user123
    { "name": "bar" }
(2)哈希计算
  • 对 _routing 值计算 Murmur3 哈希(一种高性能非加密哈希函数),生成一个整数。

(3)取模定位分片
  • 将哈希值对 number_of_primary_shards 取模,得到目标分片编号(shard_num)。


3. 代码级实现

Elasticsearch 的实际逻辑在 IndexRouting 类中实现:

java

// 伪代码:分片定位逻辑
public int shardId(String routing, int numShards) {
    int hash = Murmur3HashFunction.hash(routing); // 计算哈希
    return Math.floorMod(hash, numShards);       // 取模得分片ID
}

4. 设计特点
特性 说明
确定性 相同 _routing 始终映射到同一分片,保证文档可被正确检索。
均匀分布 Murmur3 哈希确保数据均匀分布在所有分片上。
不可变性 主分片数量(number_of_primary_shards)一旦创建不可更改,否则路由失效。

5. **写入流程示例
  1. 客户端发送文档到协调节点(Coordinating Node)。

  2. 协调节点通过路由公式计算目标主分片(如 shard_num=2)。

  3. 协调节点将请求转发到主分片所在的数据节点(Data Node)。

  4. 主分片写入成功后,并行同步到副本分片。


6. **自定义路由的典型场景
  • 局部性优化:将同一用户的文档存储在同一分片,提升查询效率。

    json

    PUT orders/_doc/1?routing=user_123
    { "user": "user_123", "order_id": 1 }
  • 避免热点:若默认 _id 导致数据倾斜,可通过业务键(如时间戳+ID)分散负载。


7. **注意事项
  • 分片数量不可变:修改 number_of_primary_shards 会导致路由失效,必须重建索引。

  • 哈希冲突:不同 _routing 可能哈希到同一分片(概率极低)。

  • 性能影响:自定义路由需确保均匀性,否则可能导致分片负载不均。


总结

Elasticsearch 的分片路由算法通过 哈希取模 实现简单高效的数据分布,兼具确定性和扩展性。理解其机制有助于优化索引设计和查询性能。


网站公告

今日签到

点亮在社区的每一天
去签到