在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支持

参考资料:


ES Route的更多相关文章

  1. ES Terms 聚合数据不确定性

    Elasticsearch是一个分布式的搜索引擎,每个索引都可以有多个分片,用来将一份大索引的数据切分成多个小的物理索引,解决单个索引数据量过大导致的性能问题,另外每个shard还可以配置多个副本,来 ...

  2. route按需加载的3种方式:vue异步组件、es提案的import()、webpack的require.ensure()

    1. vue异步组件技术 vue-router配置路由,使用vue的异步组件技术,可以实现按需加载. 但是,这种情况下一个组件生成一个js文件.举例如下: { path: '/promisedemo' ...

  3. ES 父子文档查询

    父子文档的特点 1. 父/子文档是完全独立的. 2. 父文档更新不会影响子文档. 3. 子文档更新不会影响父文档或者其它子文档. 父子文档的映射与索引 1. 父子关系 type 的建立必须在索引新建或 ...

  4. UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)

    UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

  5. php 极简框架ES发布(代码总和不到 400 行)

    ES 框架简介 ES 是一款 极简,灵活, 高性能,扩建性强 的php 框架. 未开源之前在商业公司 经历数年,数个高并发网站 实践使用! 框架结构 整个框架核心四个文件,所有文件加起来放在一起总行数 ...

  6. 最新的ES 5.0路由算法底层实现

    http://www.cnblogs.com/bonelee/p/6078947.html 里分析了ES bulk实现,其中路由代码: ShardId shardId = clusterService ...

  7. 第3章 ES文档和故障处理

    第3章 ES文档和故障处理 一.ES网络配置表 ES网络配置表是ES的硬件和软件组成的列表.ES网络配置常包括以下项目: 分级 项目 杂项信息 系统名.系统厂商/型号.CPU速率.RAM.存储器.系统 ...

  8. ES分布式原理

    参考:https://blog.csdn.net/chang384915878/article/details/86747419 一.准备知识 这里只是简单的介绍,详情可以看我的另一篇博客:https ...

  9. 你一定看得懂的 DDD+CQRS+EDA+ES 核心思想与极简可运行代码示例

    前言 随着分布式架构微服务的兴起,DDD(领域驱动设计).CQRS(命令查询职责分离).EDA(事件驱动架构).ES(事件溯源)等概念也一并成为时下的火热概念,我也在早些时候阅读了一些大佬的分析文,学 ...

随机推荐

  1. nwjs 解决手指可滑动问题

    package.json 中添加: "chromium-args": "--touch-events --enable-touch-drag-drop",

  2. table标签总结

    一.table标签:定义一个表格简单表格由table元素以及一个或多个tr(行标签).th(表头单元格标签).td(普通单元格标签) <table border=1><tr>& ...

  3. 处理tcp里的粘包问题

    typedef struct _CONN_BUFFER { uint8_t buffer[CONN_BUFFER_LENGTH]; uint32_t tail; uint64_t id; time_t ...

  4. 百练-16年9月推免-C题-图像旋转

    C:图像旋转 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 输入一个n行m列的黑白图像,将它顺时针旋转90度后输出. 输入 第一行包含两个整数n和m,表示图 ...

  5. nginx 重定向与反向代理

    server{    listen       80;    server_name  dianxi.test.net; #将地址重定向为新的ip地址    #rewrite  "^/env ...

  6. python---map 用法 [转载]

    map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 1.当seq只 ...

  7. 《DSP using MATLAB》Problem 6.5

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  8. 《DSP using MATLAB》Problem5.23

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% O ...

  9. Python--函数对象@命名空间与作用域@包函数@装饰器@迭代器@内置函数

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

  10. 【BZOJ1202】【HNOI2005】狡猾的商人

    查分约束好,好写好调好AC! 原题: 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1, ...