一、ES写流程
- 客户端发起请求,ES计算此数据应存储在P0节点。
- 协调节点,将请求发送到主分片P0,进行数据保存
- P0将数据复制发送给R0负分片
- R0保存数据后,对主分片进行反馈
- 主分片收到副分片反馈后,将结果反馈给客户端
参数值 | value | |
---|---|---|
consistency | one | 主分片数据写成功,就反馈 |
all | 主分片和负分片都写成功,才反馈 | |
quorum | 默认。写之前必须确保大多数 shard 都可用,当 number_of_replicas>1 时才生效。quorum = int( (primary + number_of_replicas) / 2 ) + 1 ,当活跃节点数至少有quorum个,才能执行写操作。参考链接:https://zq99299.github.io/note-book/elasticsearch-core/distributed-document/31-consistency-quorum.html#quorum-%E6%9C%BA%E5%88%B6 | |
timeout | 时间 | 默认60s,可设置。es等待更多可用分片的出现时间 |
二、ES读流程
- 客户端发起读请求,随机请求到节点二,节点二成为协调节点。协调节点计算请求数据在P0、R0上
- 通过负载均衡轮询请求P0,R0。假设请求到副本分片R0
- R0查询数据后,反馈给客户端。
三、倒排索引
ik_max_word
ik_smart_word
词条:英文对应一个单词,中文对应一个词组
词典:文档被分词后的结果,存储在词典表中
倒排表:
倒排索引在写入磁盘后,是不可变的,原因有下:
优点:
- 不需要锁。如果你从来不更新索引,你就不需要担心多进程同时修改数据的问题。
- 一旦索引被读入内核的文件系统缓存,便会留在哪里,由于其不变性。只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘。这提供了很大的性能提升。(内存读取)
- 其它缓存(像filter缓存),在索引的生命周期内始终有效。它们不需要在每次数据改变时被重建,因为数据不会变化。(减少重建成本)
- 写入单个大的倒排索引允许数据被压缩,减少磁盘 I/O 和 需要被缓存到内存的索引的使用量。
总结下来:不可变的原因是为了更快
缺点:
新文档的加入,需要重建整个索引。这样会对索引可包含的数据量、可更新频率有很大的限制
动态更新索引
按段搜索(TODO):通过增加新的补充索引来反映新近的修改,而不是直接重写整个倒排索引。每一个倒排索引都会被轮流查询到,从最早的开始查询完后再对结果进行合并。
新文档建立索引过程:
-
新文档被收集到内存索引缓存
-
不时地, 缓存被 提交
(1) 一个新的段(一个追加的倒排索引)被写入磁盘。
(2) 一个新的包含新段名字的 提交点 被写入磁盘
(3) 磁盘进行同步 — 所有在文件系统缓存中等待的写入都刷新到磁盘,以确保它们被写入物理文件 -
新的段被开启,让它包含的文档可见以被搜索
-
内存缓存被清空,等待接收新的文档
当一个查询被触发,所有已知的段按顺序被查询。词项统计会对所有段的结果进行聚合,以 保证每个词和每个文档的关联都被准确计算。 这种方式可以用相对较低的成本将新文档添 加到索引。 段是不可改变的,所以既不能从把文档从旧的段中移除,也不能修改旧的段来进行反映文档 的更新。 取而代之的是,每个提交点会包含一个 .del 文件,文件中会列出这些被删除文档 的段信息。
当一个文档被 “删除” 时,它实际上只是在 .del 文件中被 标记 删除。一个被标记删除的文档仍然可以被查询匹配到, 但它会在最终结果被返回前从结果集中移除。
文档更新也是类似的操作方式:当一个文档被更新时,旧版本文档被标记删除,文档的新版 本被索引到一个新的段中。 可能两个版本的文档都会被一个查询匹配到,但被删除的那个 旧版本文档在结果集返回前就已经被移除。