请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

一个分片问题

看了一下我们现在用的索引,发现某个primary shard数据量10g, 5个replica其中一个replica是14g,另外4个是10g,为什么会出现这种情况老师能帮忙解释一下吗

正在回答 回答被采纳积分+3

1回答

少林码僧 2022-08-04 18:08:25

根据您的描述,分片大小不一致的问题我们分几种情况来看(前提是同一个索引的主副本分片):
1. 同一个索引的各个主分片大小不一致
2.同一个索引的主分片,其副本跟它对应的主分片的大小不一致

首先通过GET _cat/shards/index_name?v 查看各个分片上的文档数量(查看docs列的数据就是文档数量)
如果分片上的文档数量差距比较大,说明数据在这两个分片上的分布不均衡.
什么决定了数据最终落到哪个分片呢?课程中有讲到,ES是通过路由策略来将数据路由到不同分片的,所以需要看业务中有没有使用routing策略,使用的routing策略是否能确保hash算法均匀,如果没有使用自定义routing,ES默认使用doc的_id作为routing,如果使用了自定义id,也需要考虑自定义的id的hash是否能够均匀。

所以针对上面第一种情况,同一个索引的各个主分片大小不一致的情况,如果是各个分片上的文档数量差距比较大,一般是自定义id或者routing导致hash失衡造成的。即使文档数量差距不大也可能导致分片大小不一致的情况,这种情况和上面第二种情况原因相同,我们具体针对第二种情况来讨论。
针对第二种情况,同一个索引的主分片,其副本跟它对应的主分片的大小不一致的情况,主要跟segment段的数量有关,我们知道ES索引的文档数据是不支持动态更新和删除的,更新的本质是将原文档标记为删除状态,再新建新的文档,所以文档更新和删除后空间并不会立马释放,需要根据ES段合并策略来回收空间。同一个分片的主副本并不是同时进行段合并调度的,所以同一个分片的主副本和两个文档数量大小相似的主分片,他们的的segment段的数量都可能不同,segment段的数量不同,执行merge的次数也不一样,分片大小不同也就很好理解了。
查询指定索引的各个分片中段的数量可以使用下面的api:

GET _cat/segments?v&index=index-name

当然,其他一些极端情况也可能造成各分片文档数差不多但大小不同,不过一般情况下可以忽略
比如文档中一些长文本大小不同,比如博客文章中,某些分片上只有几个字的博客比较多,而另一些分片上长文章的博客比较多也可能造成分片存储上失衡

1 回复 有任何疑惑可以回复我~
  • 谢谢老师,解释的非常详细,我们现在是第二种情况,看了segments确实发现很多segments上面的docs.deleted比其他node上面的要大很多,加起来确实会多比其他节点很多。
    另外在这里还想在多问一个问题,我们集群现在机器有两种类型,master节点和data节点(每台机器还额外有一个ingest的role),对于我们这样的集群来说,哪些节点充当协调节点的角色?是每个数据节点都是协调节点吗。另外我们现在搜索的性能瓶颈在于query and fetch阶段的fetch阶段,因为索引每个document比较大,获取数据的时候需要反序列化(指es内部),性能比较差(尽管我们对一些用了store_field的方式),这种情况是否可以通过使某些机器只作为协调节点来优化呢?
    回复 有任何疑惑可以回复我~ 2022-08-04 18:30:03
  • 很多同学容易将协调节点和ingest 节点混淆,认为ingest 节点就是协调节点,其实它们是2中不同的节点角色。ingest 节点是预处理节点,主要负责一些pipeline任务的处理,一般业务都没使用到pipeline任务。
    而所谓的协调节点叫做Coordinating node
    
    首先我们来理解下这个协调节点(Coordinating node)
    协调节点在ES中属于一种比较特殊的节点角色,其他节点角色我们都可以在配置中通过配置去指定节点角色,但是协调节点其实只是一种概念上的节点角色,ES中的任意一个节点都可以充当协调节点的角色,当查询或写入请求发送到这个节点上,这个节点就被称为协调节点,所以设置独立的协调节点就是不给这个节点任何节点角色,课程中我们有讲解6.x版本和7.x版本的设置方式。一旦设置独立的协调节点,我们应该将ES的连接地址改为我们设置的这几个独立的协调节点,使用go sdk链接的时候需要注意关闭sniff,课程中我们也讲到过,开启sniff会自动嗅探集群中其他节点来发起查询或者写入请求这样就达不到设置独立协调节点的目的。如果使用java 或者其他SDK也需要注意下这个问题。
    是否需要使用独立的协调节点,主要看下面这些情况:
    1. 有深度分页或者聚合查询,会占用大量内存的情况(因为一旦这些请求打到主节点或者数据节点会影响集群稳定性)
    2. 查询和写入请求量很大,导致连接ES的几个节负载明显高于其他节点
    独立的协调节点对于集群稳定性有一定的帮助,对于读写性能帮助不大
    
    对于大文本,查询效率的优化可以从写入入手,一旦写入带来的负载变低,查性能也会有明显提升
    首先对于refresh_interval的设置就是十分关键的,在我遇到的大文本场景中,设置5s以上的刷新时间会有十分显著的提升,然后是硬盘,使用固态配合refresh_interval设置加上合理的routing策略(如果能一定要考虑使用routing,性能优化十分显著),大文本高亮也是特别耗时的一环,我们直接放弃了官方的高亮,自己开发了更高性能的高亮插件。
    
    为了减少写带来的压力,也可以考虑课程中提到的读写分离架构,或者直接将一些实时性不高的写请求放在夜间来做。
    
    如果是频繁修改的文档还可以考虑在业务上进行合并,同一个文档的修改经过一段时间的合并再写入ES,也能减少写操作。
    
    最后是查询语句,避免正则前缀等匹配方式,以及一些复杂的查询条件,查询语句尽可能精简。
    回复 有任何疑惑可以回复我~ 2022-08-04 19:36:14
  • 干货满满
    回复 有任何疑惑可以回复我~ 2022-08-08 11:37:35
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信