• Elasticsearch document深度剖析


    1. 针对Elasticsearch并发冲突问题,ES内部是如何解决的?

    1)ES内部是线程异步并发修改的,是基于_version版本号进行乐观锁并发控制的;

    2)若后修改的先到了,那么修改后版本发生变化,先修改的后到发现版本不一致就扔掉了,保证了数据的正确性;

    3)primary shard与replica shard同步请求是多线程异步的;

    2. 基于版本号的实际操作

    1)PUT  /index/type/id?version=1;

    es中的数据和客户端的数据的版本号必须是一致的,才能修改;

    2)基于external version 进行了乐观锁并发控制;

    不使用es内部的版本号,使用自己维护的版本号进行并发控制

    ?version=2&version.type=external

    此方法保证只要version比ES中version大,就可以完成修改;

    3. partial update

    POST /index/type/id/_update

    {

    "doc":{

    要修改的数据。

    }

    }

    和全量替换相比优点:

    1)所有的查询,修改和写回操作都是发生在es的内部,避免了所在的网络数据传输的开销,大大提升了性能;

    2)减少了查询和修改的时间间隔,可以减少并发冲突的情况;

          partial update的实现原理:

                     和全量替换差不多:内部先获取document,将传过来的field更新到document的json中,将老的document标记为deleted,最后将修改后的新的document创建出来;

          partial update的并发控制原理:

                      内部自动执行并发乐观锁的并发控制策略。

                     POST /index/type/id/_update?retry_on_conflict=5 使用了重试策略,再次去新的版本号在更新;

    4. 批量查询

    优点:减少网络请求的开销

    1) GET /_mget

    GET /_mget
    {
       "docs" : [
          {
             "_index" : "test_index",
             "_type" :  "test_type",
             "_id" :    1
          },
          {
             "_index" : "test_index",
             "_type" :  "test_type",
             "_id" :    2
          }
       ]
    }

    2) 如果查询的document是一个index下的不同type种的话

    GET /test_index/_mget
    {
       "docs" : [
          {
             "_type" :  "test_type",
             "_id" :    1
          },
          {
             "_type" :  "test_type",
             "_id" :    2
          }
       ]
    }

    3) 如果查询的数据都在同一个index下的同一个type下,最简单了

    GET /test_index/test_type/_mget
    {
       "ids": [1, 2]
    }

    5. 批量的增删改 bulk

    POST /_bulk
    { "delete": { "_index": "test_index", "_type": "test_type", "_id": "3" }}
    { "create": { "_index": "test_index", "_type": "test_type", "_id": "12" }}
    { "test_field": "test12" }
    { "index": { "_index": "test_index", "_type": "test_type", "_id": "2" }}
    { "test_field": "replaced test2" }
    { "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }
    { "doc" : {"test_field2" : "bulk test1"} }

    (1)delete:删除一个文档,只要1个json串就可以了
    (2)create:PUT /index/type/id/_create,强制创建
    (3)index:普通的put操作,可以是创建文档,也可以是全量替换文档
    (4)update:执行的partial update操作

    bulk api对json的语法,有严格的要求,每个json串不能换行,只能放一行,同时一个json串和一个json串之间,必须有一个换行;

    bulk操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志;

    bulk size的最佳大小:

    bulk request会加载到内存里,如果太大的话,性能反而会下降,因此需要反复尝试一个最佳的bulk size。一般从1000~5000条数据开始,尝试逐渐增加。

    6. document的数据路由

    路由算法:shard = hash(routing) % number_of_primary_shards

    routing值,默认是_id,也可以手动指定,相同的routing值,每次过来,从hash函数中,产出的hash值一定是相同的;

    可以手动指定put /index/type/id?routing=user_id ;以保证说,某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的

    这也是 primary shard数量不可变的谜底;

    7. 增删改的内部原理

    1)客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点);
    2)coordinating node,对document进行路由,将请求转发给对应的node(primary shard);
    3)实际的node上的primary shard处理请求,然后将数据同步到replica node;
    4)coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端;

    8. 写一致性

    增删改操作 put /index/type/id,都可以带上一个consistency参数 put /index/type/id?consistency=quorum

    一致性策略:

    one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行
    all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作
    quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作

    quorum机制,写之前必须确保大多数shard都可用,int( (primary + number_of_replicas) / 2 ) + 1,当number_of_replicas>1时才生效

    quroum = int( (primary + number_of_replicas) / 2 ) + 1

    如果节点数少于quorum数量,可能导致quorum不齐全,进而导致无法执行任何写操作,es提供了一种特殊的处理场景,就是说当number_of_replicas>1时才生效;

    quorum不齐全时,会进行wait,默认1分钟,自己可以设置timeout的时间;

    (注意:一个primary shard 的多个replica shard也不能在同一个node上)

    9. document 查询的内部原理

    1)客户端发送请求到任意一个node,成为coordinate node;

    2)coordinate node对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡;

    3)接收请求的node返回document给coordinate node;

    4)coordinate node返回document给客户端;

    5)特殊情况:document如果还在建立索引过程中,可能只有primary shard有,任何一个replica shard都没有,此时可能会导致无法读取到document,但是document完成索引建立之后,primary shard和replica shard就都有了。

    10._bulk api 的奇特JSON格式和性能优化的关系

    如果采用比较良好的json数组格式,允许任意的换行,整个可读性非常棒,读起来很爽,es要按照下述流程去进行处理:

    (1)将json数组解析为JSONArray对象,这个时候,整个数据,就会在内存中出现一份一模一样的拷贝,一份数据是json文本,一份数据是JSONArray对象;
    (2)解析json数组里的每个json,对每个请求中的document进行路由;
    (3)为路由到同一个shard上的多个请求,创建一个请求数组;
    (4)将这个请求数组序列化;
    (5)将序列化后的请求数组发送到对应的节点上去;

    耗费更多内存,更多的jvm gc开销;

    奇特的格式:

    {"action": {"meta"}}
    {"data"}

    (1)不用将其转换为json对象,不会出现内存中的相同数据的拷贝,直接按照换行符切割json;
    (2)对每两个一组的json,读取meta,进行document路由;
    (3)直接将对应的json发送到node上去;

    最大的优势在于,不需要将json数组解析为一个JSONArray对象,形成一份大数据的拷贝,浪费内存空间,尽可能地保证性能;

  • 相关阅读:
    神经网络与深度学习(邱锡鹏)编程练习 3 Logistic回归、softmax回归、支持向量机(SVM)
    神经网络与深度学习(邱锡鹏)编程练习 3 Logistic回归 softmax回归 源代码 tf版
    神经网络与深度学习(邱锡鹏)编程练习 3 实验1 Logistic回归 pytorch
    神经网络与深度学习(邱锡鹏)编程练习 2 基函数回归 Jupyter导出版 TensorFlow 2.9
    神经网络与深度学习(邱锡鹏)编程练习4 FNN 简单神经网络 Jupyter导出版 numpy
    神经网络与深度学习(邱锡鹏)编程练习4 FNN 简单神经网络
    神经网络与深度学习(邱锡鹏)编程练习 3 Logistic回归 Jupyter导出版 TensorFlow2.9
    神经网络与深度学习(邱锡鹏)编程练习 2 实验1 线性回归的参数优化 最小二乘法
    05月29日总结
    程序的装入和链接
  • 原文地址:https://www.cnblogs.com/ntbww93/p/9806931.html
Copyright © 2020-2023  润新知