[转载] ElasticStack 系列之三 & 索引前半段过程

1. 索引分片

上图所示,一共有 3 个分片(shard),每个 shard 上有一个副本(replica),看到的蓝色图片为一个一个不同的 datanode,目的是为了高可用。其中 3 个 shard 将所有的数据进行分割到不同的片上。如果使用 es 默认配置,你用一个节点进行启动,发现服务器状态总是 yellow 的,那是因为默认配置每个分片上都有一个副本,且 es 规定分片和副本不能放到一个节点上,那么一个节点启动es是找不到地方存放副本的地方,故集群服务状态始终为 yellow,除非将副本数设置为 0,那么机器就会变为 green。

2. 路由策略

es 底层查询方式是:search and get , 即先通过查询条件获得一大堆 id,之后再通过这些 id 直接 get 到所需要的数据再返回。

3. mapping 解析

es 默认使用的是动态解析,即在建立索引的时候不需要你提前创建对应的 schema 或者表结构,其实内部 es 也是对你提交的数据进行推测 mapping 后才索引,这个时候 es 可能会出现一些问题,(当然,大部分的时候还是可以正常使用的。建议能不用动态解析还是不要用,因为会发生一些意向不到的问题,如果遇到一些奇葩的需求,例如真的不知道对应的 schema 对应的是什么,只能选用 es 动态解析)

如上图所示,各个类型的匹配规则就是如此。但是有时候业务方为了图省事或者写入有误,将所有的内容都加上了双引号,除了日期无影响外,其他的所有非 string 类型字段都会被解析为 string 类型,那么测试你的数据类型可能就都会有问题了。

例如:

  1. 一个属性字段应该都是 long 类型,将所有数字都导进来了,但是无法进行 sum 计算,那么问题就来了,人家找过来问你为什么呢?所以这是有问题的。

  2. 还有一个很严重的实例,你不是说 es 可以不用设计表结构,那好,那我就拿到数据直接往你 es 里灌,后续人家说了,我给你导入无重复的 2 亿数据,怎么导完之后查了很多条数据都没有查到呢。那这个问题你想破了头皮也查不出来。最后通过对方导出日志发现是因为查询的这些条数据其中有一个字段 value 写成了 valeu,导致你查询的时候怎么查都查不到。

提前申明:

如果有人非得用这个动态功能,那么我必须先要告诉你们用这个的风险,有什么问题自己负责。你不要说 es 有问题什么的,这个我提前都已经告诉你了,需要你心里有数。

4. 倒排索引

正排索引:通过id可以找到这个文章中包含哪些词

倒排索引:通过关键词可以找到包含有哪些文章

5. 写入存储

数据进入 ES 且如何才能让数据更快的被检索使用,用 Lucene 的设计思路就是“开新文件”

Lucene 把每次生成的倒排索引叫做一个段(segment)。然后另外使用一个 commit 文件,记录索引内所有的 segment。而生成 segment 的数据来源选择是内存中的 buffer,即动态更新如下:

  1. 当前索引有 3 个 segment 可用,状态图 –> 5-1图

  2. 新接收的数据进入内存 buffer,状态图 –> 5-2图

  3. 内存 buffer 刷到磁盘,生成一个新的 segment,commit 文件同步更新。既然涉及到磁盘,那么一个不可避免的问题来了:磁盘太慢了!所以需要在刷新到磁盘中间加一个缓存用于提升速度。

  4. 内存 buffer 生成一个新的 segment,刷到文件系统缓存中,lucene 可以检索这个新的 segment,状态图 –> 5-3图

  5. 文件系统缓存真正同步到磁盘上,commit 文件更新,达到状态图 –> 5-4图

对于第 5 步刷到文件系统缓存的步骤,在 ES 中默认设置为 5s(ES2.x 之前的 flush 时间间隔为:1s)间隔,对于大多数应用来说几乎相当于实时可搜索了。ES也提供了单独的 /_refresh 接口,用户可以手动设置:

curl -xpost http://ip:9200/logstash/_settings -d
{
    "refresh_interval" : "10s" //-1代表完全关闭刷新
}

既然 refresh 只是写到文件系统缓存,那么最后一步写到实际磁盘又是由什么来控制?如果这期间发生主机错误、硬件故障等异常情况,数据会不会丢失?

其实 ES 在把数据写入到内存 buffer 的同时还会另外记录一个 translog 日志(记录的是 commit 的原始内容,即当前文档的原样 json 串)。在 5-3 图和 5-4 图 refresh 发生的时候,translog 日志文件依然保持原样如图 5-5 图所示。也就是说,如果在这期间发生异常,ES 会从 commit 位置开始,恢复整个translog 文件中的记录,保证数据的一致性。

等到真正把 segment 刷到磁盘且 commit 文件进行更新的时候,translog 文件才清空,这一步叫 flush,ES 默认 30 分钟(或 translog 大小达到 512MB)主动进行一次 flush。

5-1. translog 的一致性

索引数据的一致性通过 translog 保证,那么 translog 文件自己呢?

默认清空,ES 每 5s 强制刷新 translog 日志到磁盘上。所以,如果数据没有副本然后又发生故障,ES确实可能会丢失 5s 的数据。

作者:星火燎原智勇
原文链接:www.cnblogs.com/liang1101/articles...

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!