(六)ES 分布式特性及分布式搜索机制

2020-08-13  本文已影响0人  木人呆呆

一、Master节点职责

  1. 处理创建、删除索引请求,索引的创建及删除;
  2. 决定分片被分配到那个节点;
  3. 维护及更新cluster status状态。
既然master节点这么重要,生产中考虑设置多个master节点,每个节点只承担master的单一角色。
索引构建完成后,主分片数量是不能再更改,除非reindex,根本的原因是在构建索引的时候,文档分片的路由算法会用到配置的主分片数量,索引一旦建好,路由就已经固定,所以后期不能修改主分片数量。
更新文档
删除文档

二、分片的内部原理

Lucene index
ES refresh
Transaction Log
ES Flush
merge(合并)

通过上文的介绍,会发现有好多segment产生,ES会定期对这个segment进行merge(合并),删除已经删除的文档(暂存进.del文件中的数据),也可以调用API进行强制合并

POST  my_index/_forcemerge

分片为ES最小的工作单元

  1. ES的搜索是近实时的(1秒后被搜到)

  2. ES如何保证断电数据不丢失
    在refresh(默认1秒发生一次) 的时候,index buffer会被清空,会同时写transaction log文件,保证了数据不丢失(1秒以内的可能会丢失)

  3. 删除文档,并不会立即释放空间
    因为删除的文件信息会被暂时存放在一个.del文件中

排序,Doc values,Fielddata
ES排序过程
Doc values和Fielddata对比
由上图可以看见,doc values默认是开启的,可以通过_mapping设置进行关闭,带来的好处就是可以增加索引速度和减少磁盘占用。关闭之后就不能再打开,除非reindex,这个功能一般用在 很明确不需要做排序和聚合分析的情况

三、ES的分页及遍历

一般使用From ,Size进行分页,背后的逻辑是:从每个分片中取from+size条文档,然后通过coordition node做聚合,最后通过排序取from+size条文档,最后呈现给用户的是size条文档。也就是说,from+size的值越大,占用的内存及计算资源就越多,效率也会越低,这就是分布式系统常见的\color{red}{深度分页问题}ES有个默认限制,限制到10000个文档,如果超过查询就会报错

  1. 使用search after避免深度分页问题
    • 不支持指定页数
    • 只能往下翻
      看示例代码及注释
//导入测试数据
POST users/_doc
{"name":"user1","age":10}

POST users/_doc
{"name":"user2","age":11}


POST users/_doc
{"name":"user2","age":12}

POST users/_doc
{"name":"user2","age":13}

//查询文档条数
POST users/_count

POST users/_search
{
    "size": 1,
    "query": {
        "match_all": {}
    },
    "sort": [
        {"age": "desc"} ,      //指定sort,需要保证值的唯一性,一般使用_id来指定sort
        {"_id": "asc"}    
    ]
}

//查询出来的结果
"hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "dJJW4HMBvlP2ZiwLvYAX",
        "_score" : null,
        "_source" : {
          "name" : "user2",
          "age" : 13
        },
        "sort" : [
          13,
          "dJJW4HMBvlP2ZiwLvYAX"
        ]
      }
    ]

POST users/_search
{
    "size": 1,
    "query": {
        "match_all": {}
    },
    "search_after":
        [
          13,
          "dJJW4HMBvlP2ZiwLvYAX"              //使用上一步查询出来的结果,作为输入参数,进行查询
        ],
    "sort": [
        {"age": "desc"} ,
        {"_id": "asc"}    
    ]
}

search after通过排序及From,每次在分片中只取size条文档,然后通过coordication node进行汇聚排序,然后给查询请求返回size条文档,避免了深度排序的问题

不同搜索类型及场景

四、并发控制(ES采用的是乐观锁)

  1. 悲观并发控制
    • 假定有并发冲突,会对资源加锁,防止冲突,例如数据库行锁
  2. 乐观并发控制
    • 假定冲突时不会发生,不会阻塞正在尝试的操作,如果数据在读写中被修改,更新将会失败,应用程序决定如何处理冲突(使用新的数据或者直接爆出错误)
ES乐观锁控制方法

这里分两种情况

DELETE products
PUT products
//写入一篇文档
PUT products/_doc/1
{
  "title":"iphone",
  "count":100
}
//内部版本 使用if_seq_no&if_primary_term的方式来做乐观并发控制
PUT products/_doc/1?if_seq_no=1&if_primary_term=1
{
  "title":"iphone",
  "count":100
}
//外部版本使用version和version_type的方式来做乐观锁并发控制
PUT products/_doc/1?version=30000&version_type=external
{
  "title":"iphone",
  "count":100
}
上一篇下一篇

猜你喜欢

热点阅读