跨集群搜索

早期版本实现- Tribe Node

  • Tribe Node 会以Client Node的方式加入每个集群。集群中的Master节点的任务变更需要Tribe Node的回应才能继续
  • Tribe Node不保存Cluster State的信息,一旦重启,初始化很慢
  • 当多个集群存在索引重名的情况,只能设置一种Prefer规则

    Cross Cluster Search

    推荐使用的跨集群搜索方式

  • 允许任何节点扮演federated节点,以轻量的方式,将搜索请求进行代理

  • 不需要以Client Node的形式加入其他集群

    节点

  • 节点是一个Elasticsearch实例,本质是一个Java进程

  • 每个节点都有名字,通过配置文件配置,或者启动时候-E node.name=dn指定
  • Coordinating Node
    • 处理请求的节点,路由请求到正确的节点,例如创建索引的请求,需要路由到Master节点
    • 所有节点默认都是Coordinating Node
  • Data Node
    • 可以保存数据的节点。节点启动后,默认就是数据节点。可以设置node.data:false禁止
    • Data Node职责:保存分片数据。在数据扩展上启动了至关重要的作用(由master Node决定如何把分片分发到数据节点上)
    • 通过增加数据节点,可以解决数据水平扩展和解决数据单点问题
  • Master Node
    • 职责:处理创建、删除索引等请求;决定分片分配到哪个节点;维护更新Cluster State
  • Master Eligible Node & 选主流程
    • 一个集群,支持配置多个Master Eligible节点。这些节点可以在必要时(如Master节点出现故障)参与选主流程,成为Master节点
    • 每个节点启动后,默认就是一个Master Eligible节点,可以设置node.master:false禁止
    • 当集群内第一个Master Eligible节点启动时,默认将自己选举为Master节点
    • 选主流程:
      • 互相ping对方,Node Id低的会成为被选举的节点
      • 被选举的节点丢失后,会重新选
      • 脑裂问题:分布式系统的经典网络问题,当网络出现问题,一个节点和其他节点无法链接
        • 设定quorum(仲裁),,只有Master Eligible节点数大于quorum时,才进行选举
        • 当3有个Master Eligible,设置discovery.zen.minium_master_nodes=2,即可避免脑裂
  • image.png

集群状态

  • 维护集群中的所有节点信息、所有的索引和其他相关的Mapping和Setting信息;分片的路由信息
  • 每个节点都会保存集群状态信息,但只有Master节点才能修改集群状态信息并同步给其他节点

分片:

  • 数据可用性:主分片丢失,副本分片可以promote成主分片;
  • 提升读取性能:副本分片由主分片同步。通过增加replica个数,一定程度上可以提高读取的吞吐量
  • 分片数设定
    • 主分片过小,如果索引增长很快,集群无法通过增加节点实现对这个索引的数据扩展
    • 主分片设置过大:导致单个shard容量很小,引发一个节点上有过多的分片,影响性能
    • 副本分片数设置过多,会降低集群整体的写入性能
  • 文档的分布式存储
    • 文档会存储在具体的某个主分片和副本分片上
    • 文档到分片得到映射算法
      • 确保文档能均匀分布在所有分片上,充分利用硬件资源
      • 潜在算法:
        • 随机/Round Robin
        • 维护文档到分片的映射关系
        • 实时计算,通过文档自动计算需要存储到哪个分片
      • es路由算法:shard = hash(_routing) % number_of_primary_shards
        • Hash算法确保文档均匀分散到分片
        • 默认的_routing值是文档id
        • 可以自行定制routing数值,例如相同国家的商品都分配到指定的shard
        • 索引创建后,primary shard数不能修改的原因
    • 更新一个文档

image.png

  • 删除一个文档

image.png

分布式搜索

两阶段

  1. Query
    1. 搜索请求到es节点后,节点以Coordinating Node的身份,向索引分片发送查询请求
    2. 被选中的分片进行查询排序,返回From+Size个排序后的文档ID和排序值给Coordinating Node
  2. Fetch
    1. Coordinating Node会将Query阶段每个分片返回得到排好序的文档ID列表,进行重新排序。选取From+Size个文档的ID
    2. 以multi get请求的方式,到相应的分片获取详细文档数据
  • 性能问题
    • 每个分片上都需要查找from+size
    • 最终协调节点处理 number_of_shard*(from+ size)
    • 深度分页
      • ES有一条限定,默认限定到10000个文档
      • 解决:Search After
        • 实时获取下一页文档信息
        • 不支持指定页数
        • 只能往下翻页
  • 相关性算分
    • 问题:每个分片都是基于自己的分片上的数据进行相关度计算。这会导致打分偏离的情况,特别是数据量很少时。相关性算分在分片之间是互相独立
    • 解决:
      • 数据量不大时,将主分片数设置为1;当数据量足够大时,只要保证文档均匀分散在各个分片上,结果一般就不会出现骗偏差
      • 使用dfs_query_then_fetch
        • 在搜索的URL中指定参数“_search?search_type=dfs_query_then_fetch”
        • 会把每个分片的词频和文档频率进行搜集,然后完整的进行一次相关性算分。耗费更多的CPU和内存