深入分析Elastic Search的写入过程

3,391 阅读5分钟

摘要

之前写过一篇ElasticSearch初识之吐槽,不知觉竟然过去了两年了。哎,时光催人老啊。最近又用到了ES,想找找过去的总结文档,居然只有一篇,搞了半年的ES,遇到那么多的问题,产出只有这么点,真是说不过去啊。只好又重新捡起ES,发现ES槽点依然很多,不兼容的更新太多了,各个版本之间的差异不小,感觉ES就是偏理论算法的人设计出来的,而不是工程学家写的。非常像公司里面,算法工程师吐槽后端应用开发算法能力弱,后端应用开发吐槽算法工程师工程能力太差。作为一个应用开发对ES差不多就是这种感觉。不过要用到搜索,不用他又不行。既然不能拒绝,只能去享受了。

写入分析

为什么要分析写入了,因为好奇呗。比如有如下问题一直困惑着我

  1. 为什么es会丢数据
  2. 什么样的节点可以是coordinate node
  3. refresh index和flush index是什么操作
  4. memory buffer,filesystem cache都存在什么地方。
  5. 集群中的节点如何配合写入的
  6. 数据怎么存放的
  7. 为什么写入到filesystem cache中就可以索引了

写入概览

首先我们从分布式集群的角度分析下写入,采用系统默认的参数来说明

集群有三个节点,都存储数据,indexA 有5个分片,2个复制集。 数据如下分布 Node1: shard1 Node2: shard2,shard3,shard1-R1(shard1的复制集) Node3: shard4,shard5,shard-R2(shard1的复制集)

为了简化问题,shard2,shard5等shard的复制集忽略问题了。 现在以写入shard1为例说明问题。

  1. 首先客户端根据配置的连接节点,通过轮询方式连接到一个coordinate节点。

coordinate节点不是很master/client/data节点一个维度的描述,它就是指处理客户端请求的节点。这个描述和cassandra的coordinate节点是一个概念。集群中所有的节点都可以是coordinate节点。

  1. coodinate节点通过hash算法计算出数据在shard1上shard = hash(document_id) % (num_of_primary_shards),然后根据节点上维护的shard信息,将请求发送到node1上。
  2. node1 对索引数据进行校验,然后写入到shard中。具体细节见下一节写入到shard
  3. 主节点数据写入成功后,将数据并行发送到副本集节点Node2,Node3。
  4. Node2,Node3写入数据成功后,发送ack信号给shard1主节点Node1。
  5. Node1发送ack给coordinate node
  6. coordinate node发送ack给客户端。

整个过程coordinate node部分类似cassandra,主shard节点和副本集受master-slave模式影响,必须有master决定写入成功与否,和mysql类似的。

写入shard

上面第三步骤,shard内写入还需要详细分析下

  1. 数据写入到内存buffer
  2. 同时写入到数据到translog buffer
  3. 每隔1s数据从buffer中refresh到FileSystemCache中,生成segment文件,一旦生成segment文件,就能通过索引查询到了
  4. refresh完,memory buffer就清空了。
  5. 每隔5s中,translog 从buffer flush到磁盘中
  6. 定期/定量从FileSystemCache中,结合translog内容flush index到磁盘中。做增量flush的。

各种数据库的单节点写入过程大同小异,一般都是写内存,记录操作日志(防止节点宕机,内存中的数据丢失)然后flush到磁盘,有个线程不断的merge 数据块。不过是写入的数据格式不同。

另外分布式或者主从式部署结构,又需要将写入的数据复制到不同的节点,这个过程比较复杂,每个数据库处理也有不同的逻辑。

elastic search 写入的中间过程还多了一层buffer,我们知道buffer和cache虽然都是为了提高写入效率,但是工作原理不同,

1、Buffer(缓冲区)是系统两端处理速度平衡(从长时间尺度上看)时使用的。它的引入是为了减小短期内突发I/O的影响,起到流量整形的作用。比如生产者——消费者问题,他们产生和消耗资源的速度大体接近,加一个buffer可以抵消掉资源刚产生/消耗时的突然变化。 2、Cache(缓存)则是系统两端处理速度不匹配时的一种折衷策略。因为CPU和memory之间的速度差异越来越大,所以人们充分利用数据的局部性(locality)特征,通过使用存储系统分级(memory hierarchy)的策略来减小这种差异带来的影响。

所以写入到buffer中的数据,还是原始数据,还没有索引,搜索不到的。只有到Cache中还可以。

和MySQL,Cassandra,Mongo的写入对比

数据库写入过程都需要写入操作日志,复制集日志,不同的数据库不一样的处理方法。 有些数据库是共用的,有些数据库则是分开的。

写操作日志的过程一般是直接写入磁盘的,因为它本身就是防止进程,机器宕机造成内存数据丢失,而用来恢复数据的。写入buffer中又会可能会导致数据的丢失。所以像elastic search mysql innodb这种操作日志写buffer的也会提供配置项,来保证当事务成功后,操作日志会被刷盘的。不过es 的操作日志最小刷盘不能低于100ms.

下面是各个数据库的日志对比,相同的功能,但是每个创建者都有自己的逼格,需要有不同的命名。

数据库 记录日志,刷磁盘 复制日志 备注
cassandra commit log commit log commit log 直接写磁盘的
mongo journal oplog journal log写磁盘的
mysql redo logs bin log redo logs写buffer的,
elastic search translog translog 写buffer的

有兴趣的同学可以之前写过的mongo,cassandra写入分析

mongo写入分析

cassandra写入分析

关注公众号【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

在这里插入图片描述

参考

www.elastic.co/guide/en/el…

www.elastic.co/pdf/archite…

lalitvc.files.wordpress.com/2018/05/mys…

www.infoq.cn/article/ana…

blog.insightdatascience.com/anatomy-of-…