• ES Route


    在ElaticSearch里面,路由功能算是一个高级用法,大多数时候我们用的都是系统默认的路由功能,一个es索引可以分多个shard和每个shard又可以有多个replia,默认情况下,elasticsearch是通过hash的方式确定每个文档所属的分片的,公式如下:
    shard_num = hash(_routing) % num_primary_shards
    • _routing字段的取值,默认是_id字段
    • num_primary_shards表示索引有多少个shard

    最终得到这条数据应该在被分配在那个一个shard上,也就是说默认是基于hash的分片保证在每个shard上数据量都近似平均,这样就不会出现负载不均衡的情况,然后在检索的时候,es默认会搜索所有shard上的数据,最后在master节点上汇聚在处理后,返回最终数据

        实际应用中的场景:比如说存储一年的数据,如果按hash去索引,那就是分布非常均匀,这样的话无论查询什么数据都会去所有的shard上查询,如果数据量比较大,那么响应速度就比较慢,但这时,一年12个月的数据本身分布并不均匀,有几个月的数据偏多,有几个月的数据偏少,理想情况下,数据偏少的月,查询性能应该更快,但如果是基于hash分片,那么我们并不能实现这种需求,因为hash分片,查询时候必须要命中所有shard之后,查询的结果才是准的,这样以来,每次查询都要扫描所有shard,比如我已经知道数据本身就是1月份的,那其实最好的情况下,只查询1月的数据就行,而不需要把一年的数据都扫描一遍,导致最终的结果就是慢的更慢,快的也慢,所以我们要针对性的做优化。

        思路也比较明确了,那就是按照月份分区,每一个月的数据都存在指定的分区中,如果是mysql那就是每个月份一张表,然后查询时候,直接查询对应月份的数据即可,在es和solr中原理也大致如此,唯一不同的地方在于es和solr都比较方便的支持了路由字段的设置而如果是数据库,则需要自己通过中间件的方式来搞定。

    在es中使用路由字段,先看一个官网给的简单的例子:

    PUT my_index/my_type/1?routing=user1&refresh=true 
    {
      "title": "This is a document"
    }
    
    GET my_index/my_type/1?routing=user1
    上面的代码中,指定了一个用户属性作为路由进行分区,然后查询的时候也必须指定路由。这一点需要注意 只要在索引时候加入路由字段,那么在以后的get,delete,update操作中都必须使用路由字段,否则会出现问题
    当然,路由字段本身,也是可以被查询的,看下面的代码:
    GET my_index/_search
    {
      "query": {
        "terms": {
          "_routing": [ "user1" ] 
        }
      }
    }

     除此之外,路由字段,也可以指定多个:

    GET my_index/_search?routing=user1,user2 
    {
      "query": {
        "match": {
          "title": "document"
        }
      }
    }
    如果指定多个用户属性,那么es会仅仅查询关联了这两个route属性的shard
    如果加入路由字段之后,其他的操作(indexing,getting,deleting,updating)都必须指定路由字段,为了避免在使用时忘记添加 路由字段,导致同类数据会分布在多个shard上,这就违反了路由的原则,所以我们可以在mapping中 设置路由字段是必须字段,否则会提示错误:
    PUT my_index2
    {
      "mappings": {
        "my_type": {
          "_routing": {
            "required": true 
          }
        }
      }
    }
    
    PUT my_index2/my_type/1 
    {
      "text": "No routing value provided"
    }

     缺失路由字段会抛出异常:

    routing_missing_exception
    注意到是如果使用了路由字段,那么_id字段只能由用户保证唯一性,因为同一个id的数据,如果路由字段不一样 它是可以被存在到多个shard中的,而默认情况下是不会出现这种情况的。
    最后接着说开头的例子,如果某个月数据量偏大,全部路由到一个shard里面依然性能有问题,es也提供了 同一个路由的字段的数据可以被分配到多个shard上,注意这是多个shard,而不是所有shard,当然这里面有一定 限制一般情况下,不建议使用这种模式
     
    solr route

    • elasticsearch直接通过hash值取模然后除以routingFactor来确定所属的shard,而solr中必须要遍历索引下的每个shard才能确定所属shard。从效率看如果有n个shard,那么solr的时间复杂度为O(n),而elasticserach的时间复杂度为O(1)。
    • 对于shard数比较大,索引数据很多的情况下,elasticsearch会快上不少。
    • elasticsearch不支持单个shard split, 而solr支持

    参考资料:


  • 相关阅读:
    字符串实现变量映射
    纯css实现无限嵌套菜单
    flex布局嵌套之高度自适应
    easy ui 零散技巧
    js高级应用
    前端利器
    css高级应用及问题记录(持续更新)
    兼容性验证方案
    原生js判断元素是否可见
    vue-cli webpack躺坑之旅
  • 原文地址:https://www.cnblogs.com/tgzhu/p/9167589.html
Copyright © 2020-2023  润新知