Elasticsearch写入一条记录流程
2021-10-27 09:37:11 19 举报
详细解析es是如何新增修改一条记录的
作者其他创作
大纲/内容
2. 下面说说elasticsearch如何更新一个文档的
真的没啥好说的吗?不不不,index和delete确实没啥好说的,但是update可以说的东西很多 。。。
translate index | delete
oldVersion == newVersion
到最后了主分片已经写完了数据,把请求再转发到副本执行,那么一次索引就结束了。
ingest pipeline
为了数据一致性,es也有抄袭mysql的事务日志。改了个名字叫translog。。。这个写入的时间就是lucene写完内存后,立刻写translog,这个时间是很快的,不会等那个每秒钟一次的refresh操作。主要起到了两点作用,当写完translog,如果根据id查文档可以直接去translog查,因为只读取一条记录所以不需要分词干啥的,直接给你就完事了,还有一个可以根据translog来校验突然宕机之类导致缓存和磁盘数据不一致的结果。
bulk批量请求的时候,一个bulk请求要新增100条记录,这100条记录全部生成随机id,可能会有50条计算hash后分到了shard-1。此时shard-1的主分片如果不在当前接收bulk请求的节点,那么要路由请求到shard-1的主节点上,这个时候我们不可能一个一个的转发过去,那不low到爆(速度也慢到爆),肯定是打包一起路由过去索引记录。这个步骤就是用来打包分片请求的。
1. elasticsearch是如何处理一个增删改请求的
send request to replia
add
write translog
这一步主要是对请求做一些预处理,可以有多个处理步骤,所以叫pipeline(管道处理)。ingest处理本身是一件很耗费cpu的事情,所以在性能优化部分,可以考虑专门的节点用来做这个处理。配置就是:`node.ingest: true`,默认都是true的,也就是es集群的每个节点都可以用来预处理索引请求。举个最简单的例子:比如我们的索引的数据是一段html文本,我们想过滤掉一些html的字符,就是在ingest pipeline中整一个processor处理器来过滤处理这些数据。
n
set routing
没啥好说的,请求已经分发到了主分片节点,接下来也没啥好 \"预处理\" 的了,直接执行就完事了!
version=1
version++
更新文档的时候,我们可能会插入一个索引mapping 中没有定义过的字段,这个时候es服务器会先检查这个字段有没有定义过,如果没有的话会\"揣测\"新属性的类型,然后替你更新mapping加上新的字段。就是这么贴心,没办法,谁让你乱搞呢。。。
CAS操作,比对版本,如果没人修改过的话(版本相同)那么久执行删除新增操作,如果版本不同的话说明该文档被其他线程修改过,那么就回到初始步骤重新开始读文档,然后加版本号这个流程。这里看上去没啥事,但是有个问题就是:delete和add这两个操作如何保证原子性呢(不会说刚刚delete完,然后就被refresh到filesystem-cache了)。这里es的处理是再加一个refresh锁,锁定状态的doc不会refresh。
update _mapping
bulk shard request
send to primary
没啥说的,因为是要更改文档,所以会将获取到的数据的版本+1,典型的多版本并发控制
delete
大部分时候,我们在索引数据的时候不会设置id,为了提高索引的性能会推荐你让es自己去生成id。而且,我们知道一条记录放到哪个分片,是有hash计算的,当然也可以自己指定放到哪个分片。这里es就是会根据你的请求内容来判断是否要生成id计算hash路由,亦或是根据你指定的路由来存储数据。
es的索引文档是不允许更改的。因为拆解文档建立倒排索引本身步骤多,复杂如果允许更改则增加了复杂度,同时不更改的话就少了并发修改的锁的结构,提升性能。所以我们发送的修改请求会被es的服务器转换成index索引请求和delete删除请求。但是首先会先查出来当前改文档的版本version(想想就知道,可能会有并发的更新请求,用version版本控制)。
有些时候,我们会创建一些索引模板比如:index_log-{yyyyMMdd}。按天存储日志,这样我们在索引日志记录的时候就会将实际转成 `yyyyMMdd` 格式的索引名称,但是这个索引在第一次PUT的时候是不存在的,所以需要检查当前服务器是否存在索引,如果不存在的话需要按照模板先整一个出来才能存数据。
auto create index
上一步已经打包好请求了,如果主分片本身就在当前节点,当然直接就开始处理了。但是如果索引主分片在其他节点上,那就将打包好的请求路由过去,这个步骤就是用来路由批量分片处理请求的。
y
CAS add doc
_id = xxxxxxxx
execute index update delete
0 条评论
下一页