ElasticSearch学习笔记四(路由+版本控制)

一、路由

上一篇文章,我们练习文档删除的时候提到,如果新增文档的时候指定了路由,那么查询、更新、删除文档的时候也要使用指定的路由才能查得到。这篇文章就来讲一讲es的路由(routing)。

1.1、什么是路由

首先,es是一个分布式系统,当我们存储一个文档到es上,实际是保存到某一个主分片中,这个主分片可能是master节点也可能是slave节点,然后再保存到对应的副本分片中。而具体保存在哪个主分片,是通过下面这个公式来决定的:

shard = hash(routing) % number_of_primary_shards

这里routing就是路由,默认是文档的_id,通过hash函数生成一个数字,再除以number_of_primary_shards(主分片的数量)取余数,就能得到具体某一个分片。

这也解释了为什么我们要在创建索引的时候就确定好主分片的数量,并且不允许修改。因为一旦主分片的数量改变了,之前的所有路由都会无效,之前的数据也都找不回来了。

1.2、默认路由

前面说到es使用_id作为默认路由,我们来演示看看,首先新建一个索引,执行主分片数量为3,副本数量为0:

然后往routing中新增文档,文档_id定义为a:

PUT routing/_doc/a 
{
  "content":"routing-a"
}

新增文档之后,我们可以使用下面查询语句,查看文档具体是存放在哪个主分片上:

GET _cat/shards/routing?v

可以看到,slave01节点的分片0上文档数量变成1了,表示文档是被存到这里了。我们继续新增几个文档,也都会路由到不同的主分片上。

使用默认路由最大的优势是负载均衡,所有数据都会平均得分配到不同的主分片上,尽量避免产生热点数据。与此同时带来的问题是:查询时无法确认文档的具体位置,每次都要将请求广播到所有的分片上执行查询,将所有查询结果合并之后返回。如果分片数量过多(例如100个),且系统数据量过大时,就会带来性能问题。这时我们可以考虑使用自定义路由的方式进行优化。

1.3、自定义路由

自定义路由需要在新增文档的时候就进行指定,最简单的方式就是直接在URL上使用?routing=指定参数:

PUT routing/_doc/f?routing=amby

例如上面指定了routing参数为amby,那么查询、更新、删除文档的时候,也要指定routing,否则可能会查询不到结果报404。为什么说是可能呢,因为如果不指定routing,es默认是使用_id来查询,有可能出现默认_id计算出来的分片恰好等于指定routing计算出来的分片,就能查询到对应的数据。这种情况一般只有主分片数比较少时才有概率出现。

自定义路由后,后续的CRUD操作都应该加上路由,否则可能导致一份文档会被保存到多个分片上。我们可以通过设置来强制所有CRUD操作都带上路由参数,设置之后,不带路由参数的操作将会报错。注意,只能在新建索引的时候设置强制路由参数。

// 6.5.4版本
PUT routing
{
  "mappings": {
    "_doc": {
      "_routing": {
        "required": true
      }
    }
  }
}

// 7.0版本
PUT routing
{
  "mappings": {
    "_routing": {
      "required": true
    }
  }
}

1.4、优化路由的单点查询问题

自定义路由可能会导致索引分配不均,大量的索引路由到一个分片上,导致这个分片的索引和查询性能降低。为了解决这个问题,可以设置 routing_partition_size 参数。注意,这个参数同样只能在创建索引的时候设置。

PUT routing
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 0,
    "routing_partition_size": 1
  },
  "mappings": {
    "_routing": {
      "required": true
    }
  }
}

这样routing将路由到一组分片,然后_id字段在决定文档保存到那一个分片上。由于这个原因,routing_partition_size的值必须是一个大于1但是小于number_of_shards设置的分片数量的一个整数。设置参数后具体公式如下:

shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards

索引一旦设置了routing_partition_size 后,join field将不能被创建了,同时索引中的所有mapping必须设置_routing为required的。

1.5、总结

当主分片数量不多,系统数据量不大时,使用默认路由就可以满足绝大多数业务场景。但如果主分片数量很大(例如100个)时,或数据量在PB级别以上时,可以考虑自定义路由的方式,加快查询检索的效率。具体的自定义规则应该由业务场景来决定,慎重考虑路由的字段,且进行必要的测试。

参考文档:

二、并发与版本控制

ElasticSearch是分布式系统,允许异步和并发,所以必须要保证并发执行时旧数据不会覆盖新数据。这里用到了乐观锁机制,es主要通过版本控制来实现。

2.1、什么是版本

还记得上一篇文章中,操作文档时返回的响应json中,都有如下三个版本属性:

  • _version 可以理解成文档的版本号,更新文档时,版本会自动加 1,属于单个文档。

  • _seq_no 可以理解成索引的版本号,也可以用来做版本控制,当索引中的任何文档新增、更新、删除时,都会自动加1,属于整个索引。

  • _primary_term 表示文档所在主分片的编号。

2.2、如何进行版本控制

2.2.1、内部版本

es自己维护的就是内部版本,维护操作不需要用户指定,底层自动进行操作:每份文档创建时版本号_version都赋值为1,之后每次更新操作,都会讲版本号自增1。在并发操作中,es要求version参数值必须等于当前文档的版本号_version,否则将返回409报错。

es6.7之前,我们可以手动指定内部版本号:

// 使用version指定内部版本号。注意:在es6.7之前的版本有效,6.7之后不支持此方法
PUT version/_doc/1?version=1
{
  "content": "version-1"
}

注意:es6.7之后,已经不支持指定内部版本号的方式,执行上面语句会报错返回400,并提示使用if_seq_noif_primary_term进行版本控制(后面有讲)。

2.2.2、外部版本

es还支持外部版本,通过version_type=external来指定使用外部版本号。版本号必须是大于0的整数, 且小于9.2E+18(Java中long类型的正值)。外部版本的处理方式和内部版本有些不同:

  • version_type=external 检查当前_version是否小于<外部版本号,如果是使用外部版本号更新文档,否则返回409报错。

  • version_type=external_gte 检查当前_version是否小于或等于≤外部版本号,如果是则使用外部版本号更新文档,否则返回409报错。

// 使用version和version_type指定外部版本号
PUT version/_doc/1?version=2&version_type=external
{
  "content": "version-2"
}

2.2.3、最新版本

es6.7之后的版本,推荐使用if_seq_noif_primary_term进行版本控制。要注意参数值必须等于所要更新文档的seq_no和primary_term。

// 使用if_seq_no和if_primary_term进行版本控制
PUT version/_doc/1?if_seq_no=5&if_primary_term=1
{
  "content": "version-3"
}

参考官方文档(旧版本): https://www.elastic.co/guide/cn/elasticsearch/guide/current/optimistic-concurrency-control.html

版权声明:

本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:
微信公众号:江南一点雨  æ±åä¸ç¹é¨
B站:https://space.bilibili.com/49484631?from=search&seid=6136072956000981995

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
elasticsearch 学习笔记包括以下内容: 一、Elasticsearch概述: - Elasticsearch是一种开源的分布式搜索和分析引擎,可以用于快速搜索、分析和存储大量的结构化和非结构化数据。 - Elasticsearch与Solr相比有一些区别,包括用户、开发和贡献者社区的规模和成熟度等方面。 二、Elasticsearch安装: 1. 下载Elasticsearch,可以从官方网站或华为云镜像下载。 2. 安装Elasticsearch。 三、安装head插件: - head插件是一个可视化的管理界面,可以方便地管理和监控Elasticsearch集群。 、安装Kibana: 1. Kibana是一个开源的数据可视化工具,用于展示和分析Elasticsearch中的数据。 2. 下载Kibana并安装。 3. 启动Kibana并进行访问测试。 4. 可选的汉化操作。 五、ES核心概念理解: - 学习ES的核心概念,包括索引、文档、映射、查询等。 以上是elasticsearch学习笔记的主要内容,希望对你有帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Elasticsearch 学习笔记(上)](https://blog.csdn.net/m0_52691962/article/details/127064350)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值