• Elasticsearch搜索优化-自定义路由规划(routing)


    在es的实践学习中,我觉得它的文档是最好的老师,所以先把这部分链接贴出来,本文只是引导,文档全是细节,还是推荐大家事后认真看看文档

    Metadata fields-routing

    在es搜索中,请求是先分发到所有分片,然后聚合结果返回,如果我们将相同业务领域的数据聚集到同一个或者少部分分片,搜索的时候只搜索这几个分片,那么将会减少机器压力,提高搜索性能。

    没有指定路由的情况

    在没有指定路由的情况,所有的数据是依据文档_id(_routing的默认为_id),然后套公式均匀的分发到分片中,公式如下:

    //我这边用的是7.9.3版本,我看7.17的公式多加了一个num_routing_shards参数,分片算法改进但本质结果没有变。
    shard_num = hash(_routing) % num_primary_shards
    

    从公式中我们可以看到id的不同必然导致文档会分散到不同的分片中,这就是没有自定义路由的普遍情况。

    指定路由的情况

    新建索引

    如何指定路由要分析产品需求和数据上的相通性,就拿商品搜索来说,商品分布在不同的门店,而同一门店的商品可能会有列表搜索,有了这么一个需求,那么同一门店的商品是不是放在一个分片里是最好选择?

    分析好需求以后我们确定了针对门店编码做路由,首先我们简单建立一个索引

    PUT ***/routing
    
    {
      "settings": {
        "number_of_shards": "3",
        "number_of_replicas": "3",
        "index.routing_partition_size": "2",
        "index.number_of_routing_shards": "3"
      },
      "mappings": {
        "_routing": {
          "required": true
        }
      }
    }
    

    除了指定了常见的分片数,副本数,还有两个新的参数index.routing_partition_size
    index.number_of_routing_shards,

    index.routing_partition_size

    当使用了路由,可以让路由相同的文档分配到同一个分片上,从而减少查询时需要的分片数,提高查询效率。但是使用该参数容易导致数据不平衡。为此,ES还提供了一个index.routing_partition_size参数,用于将路由相同的文档映射到不止一个分片上,默认值是1,这样一方面可以减少查询的分片数,另一方面又可以在一定程度上防止分片数据不平衡。引入该参数后计算公式如下

    shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards
    

    这个参数只是对上面公式的进一步延申,我在索引参数中设置了2,说明在这个3个分片的索引中,路由相同的文档分配到其中2个分片上,后面我们导入数据时看看效果。

    index.number_of_routing_shards

    当在es中使用自定义路由时,路由分片的数量(number_of_routing_shards)决定了有多少分片用于路由。如果不指定此设置,则无论设置的分区大小(routing_partition_size)是多少,都只使用一个分片进行路由。为了确保正确实现分区大小,请将number_of_routing_shards设置为索引中的主分片数(number_of_shards)。这将确保根据指定的路由分片大小(number_of_routing_shards)使用预期数量的分片(number_of_routing_shards)进行路由。

    在很多资料中,只提了routing_partition_size但是没有提number_of_routing_shards,如果不设置number_of_routing_shards,routing_partition_size的作用就会失效,这里着重强调,我在例子中设置了3,跟主分片数量一样。

    Unique IDs with custom routing

    其次,mappings里_routing的required值为true,会让使用自定义路由时,每当保存、获取、删除或更新文档时,都必须提供路由值,否则报错。我们要明白一点,如果不强制设置这个必填,会导致一条数据在多个分片中出现,没错,连_id都会一模一样,因为在es机制中,不同的路由值下的_id才必须是唯一的。这一条规则(Unique IDs with custom routing)文档也有写清。

    导入数据

    同一个routing随意导入若干条数据,看看数据分片的情况

    插入数据

    POST http://***/routing/_doc?routing=107U
    
    {
      "shopCode": "107U"
    }
    

    检查预期结果

    查询分片情况:

    GET 
    http://***/_cat/shards/routing?v
    

    可以看到在同一个路由的情况下,数据只分布在2个分片中,符合预期。

    index   shard prirep state      docs store ip         node
    routing 1     p      STARTED      13 5.1kb 10.6.11.20 node-2
    routing 1     r      STARTED      13 5.1kb 10.6.11.20 node-1
    routing 1     r      STARTED      13 5.1kb 10.6.11.20 node-3                     
    routing 2     r      STARTED       7 4.8kb 10.6.11.20 node-2
    routing 2     r      STARTED       7 4.8kb 10.6.11.20 node-1
    routing 2     p      STARTED       7 4.8kb 10.6.11.20 node-3        
    routing 0     r      STARTED       0  208b 10.6.11.20 node-2
    routing 0     p      STARTED       0  208b 10.6.11.20 node-1
    routing 0     r      STARTED       0  208b 10.6.11.20 node-3              
    
    

    结语

    自定义路由在用户了解查询需求和业务的基础之上,可以对查询性能进行优化,然而使用不当会导致数据不平衡,重复ID等问题。所以要充分了解其机制再去使用(这里再次推荐看下官方文档),避免反向优化。

  • 相关阅读:
    六、组件的生命周期与组件间之间的数据共享
    关于CSDN右上角的消息数显示
    教程图文详解 - 网络互联与互联网(第六章)
    因为一次bug的教训,我决定手撕Nacos源码(先撕客户端源码)
    Qt开发思想探幽]QObject、模板继承和多继承
    基于R语言地理加权回归、主成份分析、判别分析等空间异质性数据分析
    Codeforces Round 908 (Div. 2)题解
    C#中引用类型的变量做为参数在方法调用时加不加 ref 关键字的不同之处
    Rust函数进阶
    openGauss亮相1024程序员节,深度解读openGauss 5.1.0版本
  • 原文地址:https://blog.csdn.net/lovejj1994/article/details/139437631