文档
- 一个文档类似于mysql中的一条记录,数据被序列化成 JSON 并存储到 Elasticsearch 中
- 文档除了包括我们写入的数据外 ,也包含元数据, 几个主要的元数据如下
- _index,文档所属的索引名字
- _type,文档所属的类型名字,现在 ES 7.x 版本的类型统一为 "_doc" 。
- _id,文档的唯一 id,如果没有指定,Elasticsearch可以自动生成。
- _version,文档版本号,每次对文档进行修改时(包括删除), _version 的值会递增
- _score,相关性算分,代表着查询的匹配性,用来排序。
- 文档不可更改,我们更新文档时,实际上是用一个全新的文档对旧文档做了替换,旧文档会被标价为已删除,后台会定期清理这些已删除的文档。
- es通过**_version字段做乐观锁来处理文档修改冲突的场景**
_index
、_type
和_id
的组合可以唯一标识一个文档
文档在分片中的插入,更新和删除
主要步骤
- 请求到达
协调节点(一般该节点也是主节点)
- 计算文档应该写到哪个分片上,查询分片的
主分片所在节点
,将请求转发主分片所在节点
主分片
执行请求- 如果执行成功,
主分片所在节点
会将请求并行转发到其他副分片所在节点
上 - 副分片执行成功,向
主分片所在节点
报告成功 - 所有副分片报告成功后,
主分片所在节点
向协调节点
报告成功,协调节点
向客户端
报告成功。
路由(routing)
- 在Elasticsearch中,文档写入时的分片计算是通过
路由(routing)
实现的,Elasticsearch使用路由值来确定文档应该分配到哪个分片中。 - 默认情况下,Elasticsearch使用
文档ID
作为路由值
。 - 文档ID可以由Elasticsearch自动生成,也可以由应用程序显式指定。
- 分片位置计算: shard = hash(routing) % number_of_primary_shards
- routing就是
路由值
。 - number_of_primary_shards 是主分片的数量
- routing就是
数据更新与删除
- 在 Elasticsearch 中文档是 不可改变的,不能修改它们。相反,如果想要更新现有的文档,需要 重建索引 或者进行替换
- 在内部实现上,Elasticsearch 会将旧文档标记为已删除,并增加一个全新的文档, 旧版本文档不会立即消失,Elasticsearch 会在后台清理这些已删除文档。
删除文档
不会立即将文档从磁盘中删除,只是将文档标记为已删除状态。更新文档
步骤如下- 从旧文档构建 JSON
- 更改该 JSON
- 删除旧文档
- 索引一个新文档】
- 当主分片把更改转发到副本分片时, 它不会转发
更新请求,
而是转发新版本的完整文档
。这是因为更改将会异步转发到副本分片,无法保证按发送顺序到达副本分片,这可能会导致错误的数据。
数据写入的一些特点
- 写入数据时默认情况下需要所有副本分片写入成功才会向客户端返回写入成功。这被称为“同步刷新”(synchronous refresh)。
- 如果对写入性能要求比较高,也可以选择异步刷新(asynchronous refresh)方式,等待所有副本分片写入成功就返回成功响应,可以通过配置索引的刷新间隔(refresh_interval)来控制异步刷新的频率。
- 写入的数据默认的情况下会在 1 秒后才能被查询到,Refresh 操作(默认一秒执行一次)会把写入到缓存的数据写入磁盘缓存中
refresh
- 在文档写入的时候,ES 会将文档先写入到
Index Buffer
中,然后再将这些数据写入磁盘,并且清空 Index Buffer,每次写入磁盘的这批数据就是分段(Segment)
。 - 将 Index Buffer 的内容写入到文件生成 Segment 的过程称为
Refresh
,Refresh 不会调用 fsync 进行刷盘操作。 - 文档写入的时候不仅需要写 Index Buffer,而且还会写 Transaction Log 文件
- 每个分片都会有自己的 Transaction Log,在 Refresh 的时候系统会清空 Index Buffer,但不会清空 Transaction Log。
文档在分片中索引
- 索引文档是将一个新文档添加到一个索引中,使其可以被搜索和查询
主要步骤
- 先对字符串进行过滤,把一些 HTML、& 等字符处理掉;
- 分词器会将字符串按某些规律(空格、句号等)切分成单词,输出的这些单词为词条(token);
- 词条过滤器对切分后的词条进行过滤,例如过滤停用词(and、is 等),或者同义词转换等;
- 对过滤后的词条作进一步的处理,如小写转换、词根转换。