《ElsticSearch - CURD是如何实现的?》

一:前言

  - 真是好几个月没有在更新博客了,主要是啊.......

  - 这个排版啊,真是不好搞...... 印象笔记真香。

  - 基本

    - Es 的数据是以 Index 区分的。

    - 其架构本身是分布式的(类似kafka),一个 Index(索引) 有多个 share(分片) 部署在 多个 Broker(机器) 上。

 

二:ElastciSearch 是如何完成插入文档的?

  - 流程

    - 当用户向一个节点提交了一个索引新文档的请求

      - 1. 节点会计算新文档应该加入到哪个分片(shard),协调节点会将请求发送给对应的节点

      - 2. 注意这个请求会发送给主分片,等主分片完成索引,会并行将请求发送到其所有副本分片,保证每个分片都持有最新数据。

        - 每次写入新文档时,都会先写入内存中,并将这一操作写入translog文件(transaction log)中,

        - 此时如果执行搜索操作,这个新文档还不能被索引到。

        - ES会每隔1秒时间(这个时间可以修改)进行一次刷新操作(refresh)。

          - 此时写入内存的新文档都会被写入一个文件系统缓存(filesystem cache)中,并构成一个分段(segment)。

        - 此时这个segment里的文档可以被搜索到,但是尚未写入硬盘,即如果此时发生断电,则这些文档可能会丢失

      - 3. 之后不断会有文件写入, 每隔一秒将生成一个新的segment每隔30分/translog文件变得很大,则执行一次fsync操作。

        - 此时所有在文件系统缓存中的segment将被写入磁盘。

        - 而translog将被删除(此后会生成新的translog)。

  - 总结

    - ES 的更新其实是和数据库(Mysql)类型的原理类似

    - 通过translog(Mysql的redolog)提升效率。

    - 符合条件自动合并Segment(Mysql的刷脏页)

    - translog 提供了 crash-safe 的能力。 

 

二: ElasticSearch 是如何完成查询的?

  - 核心

    - 查询的过程大体上分为查询(query)和取回(fetch)两个阶段。

    - 这个节点的任务是广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。

  - 流程

    - Query

      - 应为本身是分布式模型,所以在节点收到请求后,会以Coordinating身份,在分片中随机选择一个(可能是主分片,也可能是副本分片)进行查询。

      - 选中分片进行查询,排序,返回 文档ID+排序值 (From + Size 条数据)

    - Fetch

      - 收到每个分片的数据,在重新排序,选择对应的ID

      - 在以 Multi 方式,去对应分片获取信息

  - 实例

    - _doc 有三个分片 share1,share2,share3 (各有一个副本),部署在 Broker1,Broker2,Broker3 上

    - 执行查询{}

      - Query

        - 请求发送到了 Broker2 上,则 Broker2 为协调节点,向 share1,share3,share2(自己本身)发送查询请求

        - share1 返回了[ID:1, 排序值:3][ID:4, 排序值:8][ID:7, 排序值:200]

        - share2 返回了[ID:2, 排序值:5][ID:5, 排序值:6][ID:8, 排序值:30]

        - share3 返回了[ID:3, 排序值:5][ID:6, 排序值:6][ID:9, 排序值:30]

        - 至此 borker2拿到了所有节点返回的数据

      - Featch

        - 协调节点重新排序(获取Size个数据)

        - 根据排序结果需要获取前两个IDs[1,2]

        - 在根据ID去对应分片获取结果 

  - 分布式查询所带来的问题

    - 每个分片都需要查 From + Size

    - 协调节点需要处理 分片数 * (From + Size) 个数据 

 

三: ElasticSearch 是如何完成更新/删除的?

  - 核心

    - ES的索引是不能修改的,因此更新和删除操作并不是直接在原索引上直接执行。

    - 每一个磁盘上的segment都会维护一个del文件,用来记录被删除的文件。

    - 每当用户提出一个删除请求,文档并没有被真正删除,索引也没有发生改变,而是在del文件中标记该文档已被删除。

    - 因此,被删除的文档依然可以被检索到,只是在返回检索结果时被过滤掉了。

    - 每次在启动segment合并工作时,那些被标记为删除的文档才会被真正删除。

  - 流程

    - 1.更新文档会首先查找原文档,得到该文档的版本号。

    - 2.将修改后的文档写入内存,此过程与写入一个新文档相同。

    - 3.旧版本文档被标记为删除,同理,该文档可以被搜索到,只是最终被过滤掉。 

 

 

posted @ 2020-08-18 17:07  Zzz哈  Views(113)  Comments(0Edit  收藏  举报