在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. OpenID

    OpenId是一个以用户为中心的数字身份识别框架,它具有开放.分散.自由等特性.OpenId的创建是基于这样一个概念:我们可以通过URI(或者URL网址)来识别一个网站.同样,我们也可以通过这样的方式 ...

  2. python list和numpy互换

    http://blog.csdn.net/baiyu9821179/article/details/53365476

  3. 九度OJ1108-堆栈的使用

    题目1108:堆栈的使用 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:11620 解决:3372 题目描述: 堆栈是一种基本的数据结构.堆栈具有两种基本操作方式,push 和 pop.P ...

  4. parson json解析

    最近交互数据中用到JSON数据,很多年以前用过CJSON解析和生成JSON数据,貌似CJSON已经发展成为了libjson,本打算用libjson库,不过其提供的解析JSON方式采用了回调,是测试过程 ...

  5. C语言--第二周作业评分和总结(5班)

    作业链接:https://edu.cnblogs.com/campus/hljkj/CS2017-5/homework/1026 一.评分要求 要求1 阅读指定博客+阅读收获+例子.(5分) 要求2 ...

  6. JAVA的初始化顺序:

    JAVA的初始化顺序: 父类的静态成员初始化>父类的静态代码块>子类的静态成员初始化>子类的静态代码块>父类的代码块>父类的构造方法>子类的代码块>子类的构造 ...

  7. POJ1417 True Liars

    题意 Language:Default True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6392 Accep ...

  8. React Native使用 DeviceEventEmitter发送通知emit和监听接收addListener的用法

    js 向 js 发送数据 DeviceEventEmitter.emit('自定义名称',发送数据);   例:边看边买退出登录之后,我的淘宝和详情页的钱包数据应该改变.这时,我们可以在退出登录请求返 ...

  9. Eclipse无法编译,提示错误“找不到或者无法加载主类”解决方法

    jar包问题: 1.项目的Java Build Path中的Libraries中有个jar包的Source attachment指为了一个不可用的jar包, 解决办法是:将这个不可用的jar包remo ...

  10. GPIO引脚操作

    Kernel: 4.4 Soc: msm8996 1.用户空间通过sysfs操作GPIO (1)启用GPIO sysfs interface 首先看系统中有没有“/sys/class/gpio”这个文 ...