ES-分片路由

  • ES分片
  • 为什么要使用分片路由
  • 使用前的思考
  • 具体方案实践
    • 需求分析与分片设计
    • 上代码

ES分片

    ElaticSearch 分片路由是个比较高级的功能了,一般情况下,我们可能会给es做个分片,这样可以把数据按照默认文档_id来分到各个分片上。这样es每次查询会分别去各个分片上查数据,然后聚合到一起返回给客户端。
    配置也很简单,只需要在配置mapping的时候设置下number_of_shards参数。如下:

{"settings": { "number_of_shards": 6, "number_of_replicas": 2 },
"mapping":{....}
}

需要注意的是,一旦创建了分片,后续想要直接修改可就不行了,解决方案是:重新创建新索引mapping,然后把数据迁移进去,删掉原有的索引,重命名新索引,数据量比较多的情况下还是比较麻烦的。

    es分片路由的规则是这样的:
            shard_num = hash(_routing) % num_primary_shards

  • _routing字段的取值,默认是_id字段。
  • num_primary_shards表示索引有多少个分片。

为什么要使用分片路由

    实际上上线的业务由于扩张较快,数据量上去了,很容易让es查询速度变慢,这时候我们就想提高点效率啊。 往往我们会发现,我实际需求的数据在每个分片中只是离散的一小部分,而es每次需要查找所有的分片,扫描所有数据。如果我找到某个规则去把数据分配到对于的分片上,然后查询的时候只查对应分片,这样应该可以节省不少资源。

使用前的思考

    对于分配规则不同业务不太一致,比如:有些使用es统计的数据每次只需要查询一天的数据,我们就可以把每一天的数据放在一个分片上,而路由分片的功能就可以使用routing参数。亦或是根据某个字段如用户id(uuid)的前缀来划分,手机号的尾号来划分等等。当然也不要钻牛角尖,对于查询频率很少的业务,让他扫描下全分片也没啥。

那么需要考虑的问题是:

  • 应该按照什么规则分片?要保正分片比较均匀。
  • 业务代码需要根据自定义routing查询。

具体方案实践

下面给出个例子具体描述下:

需求分析与分片设计

    一较大数据量的业务,es中仅存储约90天数据,过期删除。现在需要查询这些数据,业务方支持每次查询最多查询一天。

    那么我们决定按日期分片,也就是把同一个日期的数据放在一个分片中。(当然你也可以把两天的数据放一个分片里)。先来个90个分片。路由字段选择为日期createDate。
那么,我该怎么通过日期找到对应的分片呢?我们必须选择一个基准日期(
比如unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数)我们选择2021年7月16号作为初始日期,这样就可以得到数据创建时间到基准时间 天数差 .

上代码
/**
* 从2021年7月16号到查询日期的天数差
* @param curDate
* @return
*/
public static int getDateDiff(Date curDate) {long curTime = curDate.getTime();//  Constants.UNIX_TIME_STAMP_MILLISECONDS是2021年7月16号的时间戳int值return (int)((curTime - Constants.UNIX_TIME_STAMP_MILLISECONDS) / (1000 * 60 * 60 * 24));
}
public static int getRouting(Date curDate) {return getDateDiff(curDate) % 90;
}

注意:这里getRouting方法也可以不做%90操作。这里为了保证routing值在0-90范围内方便读写。

  • 由于es内部使用了hash散列函数,那么就会导致我这90天的数据不会一对一的映射到90个分片上,有的分片是空的,有的分片又存了多天的数据。但这个无关紧要,因为我们的目标已经达成了:减少了数据扫描范围。那么如果我们希望数据分布的更均衡点,我们可以扩大分片数。经过测试我把分片数设成200.可以保证我大体上90天数据均匀分开,当然也导致了有120个空分片(空就空着,也无关紧要)。

    查询、插入数据的时候需要指定参数routing即可,总体看开发还是挺简单的。

Search search = builder
.addIndex(EsConstant.INDEX)
.addType("_doc")
.setParameter("routing",String.valueOf(getRouting(new Date())))
.build();

    有时候可能业务代码里忘记加路由或者后来开发人员没有加可以设定下_routing:{"required": true},这样没有根据路由查询的会报错。当然你想放开也没关系。

PUT my_index_name
{"mappings": {"my_type": {"_routing": {"required": true}}}
}

除此之外,一般分片可以跟据某个uuid字段去随机分, 如下:

 public static String getRouting(String str) {int shardCount = 10;BigInteger hashKey = new BigInteger(hash(str.hashCode()) + "").abs();int result = (hashKey.mod(BigInteger.valueOf(shardCount))).intValue() + 1;return result + "";}public static int hash(int key) {// key = (key << 21) - key - 1;key = (~key) + (key << 21);key = key ^ (key >> 24);// key * 265key = (key + (key << 3)) + (key << 8);key = key ^ (key >> 14);// key * 21key = (key + (key << 2)) + (key << 4);key = key ^ (key >> 28);key = key + (key << 31);return key;}

这里我自己做了一次hash和取模,是为了让routing值处于分片数区间。这边比较方便手动根据routing查,如果routing直接放uuid,那么使用kibana跟据routing查的时候就很头疼了。对于我这个处理后的routing,es内部还会去做hash(routing)%shardNums,读者们不要误解成我去实现了分片逻辑哈。routing值和分片也并非一一对应的哈。

没了没了,莫莫绵溜了溜了。


水平有限,如果你觉得上述有任何疑问、不足、错误的地方,欢迎在评论区指正讨论。


ES-分片路由(routing)相关推荐

  1. 【弄nèng - Elasticsearch】运维篇 —— ES分片unassigned解决方案(ALLOCATION_FAILED,REPLICA_ADDED等

    文章目录 1. 情况 2. 继续深究 3. 解决此问题用到的知识 项目推荐 1. 情况 ES分片有一些未分配成功,集群状态处于黄色 我们可以通过以下api查看分片情况 GET _cat/shards? ...

  2. 分库分表之历史表如何选择最佳分片路由规则

    前言 先别急着关闭,我相信这篇文章应该是所有讲分表分库下的人都没有和你们讲过的一种分片模式,外面的文章基本上都是教你如何从零开始分片,现在我将讲解的是如何从1+开始分片 项目地址 github地址 h ...

  3. 【elasticsearch】 elasticsearch document 路由 (routing) 到shard

    文章目录 1.概述 2. 工作原理 2.1.数据路由(routing) 2.2.路由算法 2.3 routing_partition_size参数 3.primary shard数量不可变的谜底 4. ...

  4. mysql 分区 mycat 分片_Mysql系列六:(Mycat分片路由原理、Mycat常用分片规则及对应源码介绍)...

    一.Mycat分片路由原理 我们先来看下面的一个SQL在Mycat里面是如何执行的: select * from travelrecord where id in(5000001, 10000001) ...

  5. ShardingSphere 5.2.1 发布|新增系统库、强制分片路由、一致性校验

    Apache ShardingSphere 本周迎来了 5.2.1 版本的发布,该版本历时一个半月,共合并了来自全球的团队和个人累计 614 个 PR,新版本在功能.性能.测试.文档.示例等方面都进行 ...

  6. es分片多少合理_【ES】ElasticSearch 深入分片

    @[toc] 一.分片介绍 分片是 Elasticsearch 在集群中分发数据的关键. 把分片想象成数据的容器.文档存储在分片中,然后分片分配到集群中的节点上.当集群扩容或缩小,Elasticsea ...

  7. Elasticsearch:路由 - routing

    你是否考虑过 Elasticsearch 如何知道将文档存储在何处? 它如何知道在哪里寻找它们,以及是否检索.更新或删除它们? 这是一个令人兴奋的过程,一切都归结为路由的概念. 路由介绍 路由是确定文 ...

  8. java 路由_RabbitMQ入门:路由(Routing)

    在上一篇博客<RabbitMQ入门:发布/订阅(Publish/Subscribe)>中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exch ...

  9. RabbitMQ入门:路由(Routing)

    在上一篇博客<RabbitMQ入门:发布/订阅(Publish/Subscribe)>中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exch ...

  10. 网址路由Routing组件如何在mvc中生成网址

    一.摘要 本篇文章从基础到深入的介绍ASP.NET MVC中的Routing组件. Routing翻译过来是"路由选择", 负责ASP.NET MVC的第一个工作:识别URL, 将 ...

最新文章

  1. 完整中英文世界国家级联下拉列表插件【前端版】
  2. python dict下标_Python基础教程:python的数据类型
  3. Android网络服务发现(NSD)协议的使用
  4. delete与delete[]
  5. C++ 预编译头文件
  6. win服务器创建文件夹命令,Win10系统如利用命令提示符或WSL创建任意大小空白文件...
  7. 前端读者 | CSS三角形和饼图
  8. 6.2阻碍循环(Cyclic Barriers)
  9. schedule java_Schedule.java
  10. Canon imageRUNNER 2525i打印机驱动通过IP地址进行安装
  11. win10禁用驱动程序强制签名_Win10系统永久禁用驱动数字签名的方法是什么?
  12. 微信公众号 语音转文字api_微信语音快速转文字功能,方便实用
  13. 问学计算机的同学买什么电脑,学生用的笔记本电脑什么样的好
  14. 疫情地图 | EXCEL制作疫情风险地地图
  15. 品优购项目案例(练习)
  16. Linux存储性能观测——vmstat命令详解
  17. 数据类型---C语言变量的定义与初始化
  18. java获取本机IP
  19. python情人节之玫瑰花与表白方式_情人节 我用Python表白
  20. 1035神奇的数字9

热门文章

  1. mac无法验证此app不包含恶意软件
  2. 文件上传 webshell 各类型 一句话木马 图片马 制作 教程
  3. 腾讯云TCP架构高级工程师认证考试大纲、考题下载及说明
  4. 社团部部长工作计划计算机学院,社团部长的工作计划(共9篇).doc
  5. APP服务器与Web服务器的区别是什么?
  6. Absible#Ansible-Playbook的任务控制
  7. 《SpringBoot实战》读书笔记
  8. 记录FinalShell退格键
  9. 计算机网络超文本是什么意思,什么是超文本链接,和超文本有什么区别?
  10. vgs是什么意思有什么用_Linux中vgs命令起什么作用呢?