elasticsearch 路由文档到分片
路由文档到分片
当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?
进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定:
shard = hash(routing) % number_of_primary_shards
routing
值是一个任意字符串,它默认是_id
但也可以自定义。这个routing
字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0
到number_of_primary_shards - 1
,这个数字就是特定文档所在的分片。
这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。
有时用户认为固定数量的主分片会让之后的扩展变得很困难。现实中,有些技术会在你需要的时候让扩展变得容易。
所有的文档API(get
、index
、delete
、bulk
、update
、mget
)都接收一个routing
参数,它用来自定义文档到分片的映射。自定义路由值可以确保所有相关文档——例如属于同一个人的文档——被保存在同一分片上。我们将在《扩展》章节说明你为什么需要这么做。
参考: http://es.xiaoleilu.com/040_Distributed_CRUD/05_Routing.html
而我们为什么会需要自定义的Routing模式呢?首先默认的Routing模式在很多情况下都是能满足我们的需求的——平均的数据分布、对我们来说是透明的、多数时候性能也不是问题。但是在我们更深入地理解我们的数据的特征之后,使用自定义的Routing模式可能会给我们带来更好的性能。
通常情况下,ElasticSearch是如何把数据分发到各个分片中,哪个分片存储哪一类的文档等细节并不重要。因为查询时,将查询命令分发到每个分片 就OK了。唯一的关键点在于算法,将数据均等地分配到各个分片的算法。在删除或者更新文档时,情况就会变得有点复杂了。实际上,这也不是什么大问题。只要 保证分片算法在处理文档时,对于相同的文档标识生成相同的映射值就可以了。如果我们有这样的分片算法,ElasticSearch就知道在处理文档时,如 何定位到正确的分片。但是,在选择文档的存储分片时,采用一个更加智能的办法不就更省事儿了吗?比如,把某一特定类型的书籍存储到特定的分片上去,这样在 搜索这一类书籍的时候就可以避免搜索其它的分片,也就避免了多个分片搜索结果的合并。这就是路由功能(routing)的用武之地。路由功能向 ElasticSearch提供一种信息来决定哪些分片用于存储和查询。同一个路由值将映射到同一个分片。这基本上就是在说:“通过使用用户提供的路由值,就可以做到定向存储,定向搜索。”
假设你有一个100个分片的索引。当一个请求在集群上执行时会发生什么呢?
1. 这个搜索的请求会被发送到一个节点
2. 接收到这个请求的节点,将这个查询广播到这个索引的每个分片上(可能是主分片,也可能是复制分片)
3. 每个分片执行这个搜索查询并返回结果
4. 结果在通道节点上合并、排序并返回给用户
因为默认情况下,Elasticsearch使用文档的ID(类似于关系数据库中的自增ID,当然,如果不指定ID的
话,Elasticsearch使用的是随机值)将文档平均的分布于所有的分片上,这导致了Elasticsearch不能确定文档的位置,所以它必须将
这个请求广播到所有的100个分片上去执行。这同时也解释了为什么主分片的数量在索引创建的时候是固定下来的,并且永远不能改变。因为如果分片的数量改变
了,所有先前的路由值就会变成非法了,文档相当于丢失了。
原来的查询语句:“请告诉我,USER1的文档数量一共有多少”
使用自定义Routing(在USESR ID上)后的查询语句:“请告诉我,USER1的文档数量一共有多少,它就在第三个分片上,其它的分片就不要去扫描了”
指定个性化路由
所有的文档API(get,index,delete,update和mget)都能接收一个routing参数,可以用来形成个性化文档分片映射。一个个性化的routing值可以确保相关的文档存储到同样的分片上——比如,所有属于同一个用户的文档。
第一种方法,也是比较直观的方法就是直接在请求的URL中指定routing参数:
curl -XPOST 'http://localhost:9200/store/order?routing=user123' -d '
{
"productName": "sample",
"customerID": "user123"
}'
这样我们就按照用户的customerID的值将具有相同customerID的文档置于同一分片上了。
第二种方法就是直接从文档中提取到对应的路由值:
curl -XPUT 'http://localhost:9200/store/order/_mapping' -d '
{
"order": {
"_routing": {
"required": true,
"path": "customerID"
}
}
}'
这样的方法和第一种方法在效果上一样的,但是有一点需要注意,相比于第一种方法这种方法的效率稍低,因为第一种方法直接就在请求的参数中确定了路由的值,而第二种方法中,首先需要将文档读入之后,再从中提取到对应的路由值。
利用路由机制的查询
利用路由机制的查询也是非常简单明了的,只需要在查询中指定对应的路由值即可:
curl -XGET 'http://localhost:9200/store/order/_search?routing=user123' -d '
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"term": {
"userID": "user123"
}
}
}
}
}'
通过指定的路由值,我们就可以直接定位到user123的文档所在的分片,而不用一股脑的向索引的所有节点都发送请求。这样的话,会大大减少系统资源的浪费。
当然,也可以同时指定多个路由值,方法也是显而易见的,只需要在查询参数中指定多个路由值即可:
curl -XGET 'http://localhost:9200/forum/posts/?routing=Admin,Moderator' -d '{}'
路由机制的总结
实际上,如果不明确指明使用路由机制,实际上路由机制也是在发挥作用的,只是默认的路由值是文档的id而已。而个性化路由的需求主要是和业务相关 的。默认的路由(如果是自动的生成的id)直观上会把所有的文档随机分配到一个分片上,而个性化的路由值就是和业务相关的了。这也会造成一些潜在的问题, 比如user123本身的文档就非常多,有数十万个,而其他大多数的用户只有几个文档,这样的话就会导致user123所在的分片较大,出现数据偏移的情 况,特别是多个这样的用户处于同一分片的时候,现象会更明显。具体的使用还是要结合实际的应用场景来选择的。
参考:http://blog.csdn.net/cnweike/article/details/38531997
elasticsearch 路由文档到分片的更多相关文章
- elasticsearch——海量文档高性能索引系统
elasticsearch elasticsearch是一个高性能高扩展性的索引系统,底层基于apache lucene. 可结合kibana工具进行可视化. 概念: index 索引: 类似SQL中 ...
- Elasticsearch 分布式文档存储
shard = hash(routing) % number_of_primary_shards决定文档在哪个分片上,routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值. ...
- elasticsearch父子文档处理(join)
elasticsearch父子文档处理 join 一.背景 二.需求 三.前置知识 四.实现步骤 1.创建 mapping 2.添加父文档数据 3.添加子文档 4.查询文档 1.根据父文档id查询它下 ...
- 007-elasticsearch5.4.3【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念
一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 L ...
- 详细描述一下 Elasticsearch 索引文档的过程 ?
面试官:想了解 ES 的底层原理,不再只关注业务层面了. 解答: 这里的索引文档应该理解为文档写入 ES,创建索引的过程. 文档写入包含:单文档写入和批量 bulk 写入,这里只解释一下:单文档写入流 ...
- 详细描述一下 Elasticsearch 索引文档的过程 ?
这里的索引文档应该理解为文档写入 ES,创建索引的过程. 文档写入包含:单文档写入和批量 bulk 写入,这里只解释一下:单文档写入流程. 记住官方文档中的这个图. 第一步:客户写集群某节点写入数据, ...
- ElasticSearch部署文档(Ubuntu 14.04)
ElasticSearch部署文档(Ubuntu 14.04) 参考链接 https://www.elastic.co/guide/en/elasticsearch/guide/current/hea ...
- ElasticSearch——原始文档和倒排索引
一.原始文档 如上图所示, 第二象限是一份原始文档,有title和content2个字段,字段取值分别为”我是中国人”和” 热爱共X产党”,这一点没什么可解释的.我们把原始文档写入Elasticsea ...
- Elasticsearch 删除文档
章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...
随机推荐
- "1130-host ... is not allowed to connect to this MySql server"登录失败
原因: 该用户没有远程连接权限. 解决:授权! mysql>GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'password' ...
- 使用dll,将image库开放出去
这是很经典的想法了,但是如何来做,不经过摸索不知道细节. 最简单: dll处 #include "stdafx.h" #ifdef _DEBUG #define new ...
- 关于cp命令的编写
关于cp命令的编写 娄老师在课上详细的讲了命令who的编写过程~对此,我很有启发!于是想亲自动手试试~ 有什么不足的地方请大家提出来! Learning by doing ~ 做中学,真的只有自己动手 ...
- 在浏览器输入url后并回车发生了哪些过程
1.解析URL ________________________________________________________________________ 关于URL: URL(Universa ...
- Win32 文件拖拽
1.响应系统消息 WM_DROPFILES 2.在响应函数里面获取拖拽文件路径 LRESULT OnDropFiles(UINT uMsg, WPARAM wParam, LPARAM lParam ...
- PHP中namespace和use使用详解
来源于:http://www.jb51.net/article/36389.htm 命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种 ...
- Spring Security配置
更加优雅地配置Spring Securiy(使用Java配置和注解):https://www.cnblogs.com/xxzhuang/p/5960001.html 采用注解方式实现security: ...
- 【第二十八章】 springboot + zipkin(brave定制-AsyncHttpClient)
brave本身没有对AsyncHttpClient提供类似于brave-okhttp的ClientRequestInterceptor和ClientResponseInterceptor,所以需要我们 ...
- org.apache.jasper.JasperException: /WEB-INF/view/../../../common/common1.jsp (line: 7, column: 1) Page directive must not have multiple occurrences of pageencoding
本文为博主原创,未经允许,不得转载: 先还原错误: org.apache.jasper.JasperException: /WEB-INF/view/../../../../common/common ...
- c++ 算法 栅格中两点之间连线
屏幕划线,通过平面坐标系实现,基本组成是一个一个的点,起点为A,终点为B 本文的算法,可以实现平面栅格中,指定的A,B两点之间进行连线(代码中仅打印了两点间需要画出的坐标点) #include < ...