ElasticSearch分片及文档版本锁(第五章)

ElasticSearch 目前也算是非常火了,站内搜索、日志分析都会用到它,而且还可以直接当成 NoSQL 数据库来使用。
接下来,我们就通过下面这个简单介绍,开启 es 之旅吧~

公众号 : 倔强小狮子

在这里插入图片描述


1. 查看文档存储分片

  1. ElasticSearch 是一个分布式系统,当我们存储一个文档到 es 上之后,这个文档则会存储到 master 节点上的 某一个分片中
  2. 例如 新建一个索引
    创建一个 lionet 索引
    put lionet
    
    ES 创建索引 默认 1个分片 一个 副本
    在这里插入图片描述
  3. 可通过 number_of_replicas 修改 副本数
    PUT lionet/_settings
    {
      "number_of_replicas": 2
    }
    
    在这里插入图片描述
  4. 错误, 索引创建完成后, 不可在动态修改索引的 shards(分片数)t, 索引和分片在创建 Index 时指定分片数量、副本数量
    PUT lionet/_settings
    {
      "index":
      {
         "number_of_shards" : 2
      }
    }
    

在这里插入图片描述
5. 创建一个新的 索引有两个分片, 2 个副本,

PUT /my_index
{
    "settings": { ... any settings ... },
    "mappings": {
        "type_one": { ... any mappings ... },
        "type_two": { ... any mappings ... },
        ...
    }
}

案例

PUT /bravelionet
{
  "settings": {
    "number_of_replicas": 1
    , "number_of_shards": 2
  }
}

查询索引
GET _cat/shards/bravelionet?v
在这里插入图片描述

  • shard 0 1 代表存在两个分片
  • node : node -1 node-2 代表两个分片(master 除外)

创建 10 个 文档查询分布
在这里插入图片描述10个文档分布不同节点不分片上, master节点 1号分片存储2 个文档, node-2为存储 1号分片副本( ES 索引 是 0 至 N-1 编号)
在这里插入图片描述

2. 是怎么分配分片的呢?

  1. ES 中路由是通过哈希算法,将具有相同 hash值的文档放置同一个主分片中,分片计算位置 公式 :
    shard=hash(routing) % number_of_primary_shards

  2. routing可以是任意字符串, 如果不一定 routing 默认使用 文档 id 作为 routing值, 通过 hash 算法计算出来一个 数字, 然后将 该 数字 和 分片数量取余, 取余的结果则是存储位置

  3. 默认的这种 routing 模式, 最大的优势是负载均衡, 这种模式是非常友好的存储到不同的分片中(当然不是绝对的), 但是: 这种默认算法有一个很大的劣势, 就是查询时无法确定文档的位置, 此时他会广播到所有分片上执行查询, 另一方便 则是使用默认的路由模式,后期修改分片不方便

  4. 当然开发者是可以进行自定义 routing值得
    PUT index/_doc/id?routing=routing value

    POST bravelionet/_doc/20?routing=lionet
    {
      "title":"倔强的小狮子",
      "content":"学习 Elastic Search "
    }
    

3. 注意 添加 Routing 后问题

  1. 上面文档中提高删除文档时如果添加了 routing 不携带 routing是删除不成功的
  2. 文档添加了 routing后不只是删除时需要添加 routing, 查询和修改时也是需要进行携带的
  • 查询 GET index/_doc/id?routing=routing value
    GET bravelionet/_doc/20?routing=1
    
  • 修改 PUT index/_doc/id?routing=routing value
    PUT  bravelionet/_doc/20?routing=1
    {
      "title":"小狮子"
    }
    
  • 修改时需特别注意 如果在修改 在创建时指定了 routing的 文档时 譬如没 指定 routing 值, 则会进行创建新 文档 (可以理解成 :修改时 ES 会先进行查询, 在进行修改, 如果查询到则直接进行创建操作)
  • 删除 DELETE index/_doc/id?routing=routing value
    delete bravelionet/_doc/20?routing=1
    

4. 案例 :

对于用户数据,我们可以将 userid 作为 routing,这样就能保证同一个用户的数据保存在同一个分片中,检索时,同样使用 userid 作为 routing,这样就可以精准的从某一个分片中获取数据

5. 锁概念

5.1 悲观锁概念

在进行操作都非常悲观,认为别人可能会进行进行操作数据, 所以会屏蔽所有可能破坏数据完整性操作,关系型数据库中悲观锁使用的比较多一些 例如 : 行锁,表锁 等

5.2 乐观锁

在进行操作时很乐观,都会认为不会有人破坏本次操作数据的完整性,只有才提交时才会检查数据的完整性,这种锁的方式可以省去锁的开销,有利于提高系统的 QPS
索引在ES中使用 乐观锁( version 版本锁)

6. 版本控制

6.7 之前

  1. 在 ES 6.7 之前,使用 version + version_type 来进行乐观并发锁的控制,根据上诉文档的案例操作, 发现每次更改文档时 version 都会进行 +1, 所以 ES 是通过 version 来确保每次操作的有序完整性
  2. version 分为内部版本锁和外部版本锁, ES 自己维护的 ES 的版本成为 内部版本锁,当创建一个文档时, ES 会给文档的版本赋值 1, 每当用户修改一次文档, 版本则会 +1
  3. 以后更新的时候,版本要大于已有的版本号
  4. vertion_type=external 或者 vertion_type=external_gt 表示以后更新的时候,版本要大于已有的版本号
  5. vertion_type=external_gte 表示以后更新的时候,版本要大于等于已有的版本号。

最新方案(Es6.7 之后)

  1. 现在使用 if_seq_no 和 if_primary_term 两个参数来做并发控制
  2. seq_no 不属于某一个文档,它是属于整个索引的(version 则是属于某一个文档的,每个文档的 version 互不影响)。现在更新文档时,使用 seq_no 来做并发。由于 seq_no 是属于整个 index 的,所以任何文档的修改或者新增,seq_no 都会自增。
  3. 现在就可以通过 seq_no 和 primary_term 来做乐观并发控制
    在这里插入图片描述

期待你的关注,和我一起学习
转载说明:转载携带原文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值