ES数据存储和集群路由原理

ES数据存储

1、存储流程

为了将数据添加到Elasticsearch,我们需要索引(index)——一个存储关联数据的地方。实际上,索引   只是一个用来指向一个或多个分片(shards)逻辑命名空间(logical namespace)”.一个分片(shard)是一个最小级别工作单元(worker unit)”,它只是保存了索引中所有数据的一部分。

当一个写请求发送到 es 后,es 将数据写入 memory buffer 中,并添加事务日志( translog )。如果每次一条数据写入内存后立即写到硬盘文件上,由于写入的数据肯定是离散的,因此写入硬盘的操  作也就是随机写入了。硬盘随机写入的效率相当低,会严重降低es的性能。

因此 es 在设计时在 memory buffer 和硬盘间加入了 Linux 的页面高速缓存( File system cache 来提高 es 的写效率。

当写请求发送到 es 后,es 将数据暂时写入 memory buffer 中,此时写入的数据还不能被查询到。默认设置下,es 1秒钟将 memory buffer 中的数据 refresh Linux File system cache ,并清memory buffer ,此时写入的数据就可以被查询到了。

File system cache 依然是内存数据,一旦断电,则 File system cache 中的数据全部丢失。默认设置下,es 30分钟调用 fsync File system cache 中的数据 flush 到硬盘。因此需要通过translog 来保证即使因为断电 File system cache 数据丢失,es 重启后也能通过日志回放找回丢失的数据。

translog 默认设置下,每一个 index delete update bulk 请求都会直接 fsync 写入硬盘。为了保证 translog 不丢失数据,在每一次请求之后执行 fsync 确实会带来一些性能问题。对于一些允许丢失几秒钟数据的场景下,可以通过设置 index.translog.durability index.translog.sync_interval 参数让 translog 每隔一段时间才调用 fsync 将事务日志数据写入硬盘。

2、动态更新索引

以在线动态服务的层面看,要做到实时更新条件下数据的可用和可靠,就需要在倒排索引的基础上,再  做一系列更高级的处理。

其实总结一下 Lucene 的处理办法,很简单,就是一句话:新收到的数据写到新的索引文件里

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

    1. 当前索引有 3 segment 可用。索引状态如图 2-1

 2-1

    1. 新接收的数据进入内存 buffer索引状态如图 2-2

2-2

    1. 内存 buffer 刷到磁盘,生成一个新的 segmentcommit 文件同步更新。索引状态如图 2-3

图 2-3

3、利用磁盘缓存实现的准实时检索

既然涉及到磁盘,那么一个不可避免的问题就来了:磁盘太慢了!对我们要求实时性很高的服务来说,  这种处理还不够。所以,在第 3 步的处理中,还有一个中间状态:

  1. 内存 buffer 生成一个新的 segment,刷到文件系统缓存中,Lucene 即可检索这个新 segment索引状态如图 2-4

图 2-4

  1. 文件系统缓存真正同步到磁盘上,commit 文件更新。达到图 2-3 中的状态

​​​这一步刷到文件系统缓存的步骤,在 Elasticsearch 中,是默认设置为 1 秒间隔的,对于大多数应用来

说,几乎就相当于是实时可搜索了。Elasticsearch 也提供了单独的

间隔还不满意的,可以主动调用该接口来保证搜索可见。

接口,用户如果对 1 秒

注:5.0 中还提供了一个新的请求参数: ?refresh=wait_for ,可以在写入数据后不强制刷新但一直等到刷新才返回。

不过对于 Elastic Stack 的日志场景来说,恰恰相反,我们并不需要如此高的实时性,而是需要更快的写入性能。所以,一般来说,我们反而会通过/_settings接口或者定制 template 的方式,加大参数:

# curl -XPOST http://127.0.0.1:9200/logstash-2015.06.21/_settings -d'

{ "refresh_interval": "10s" }

如果是导入历史数据的场合,那甚至可以先完全关闭掉:

# curl -XPUT http://127.0.0.1:9200/logstash-2015.05.01 -d'
{
"settings" : { "refresh_interval": "-1"
}
}'

在导入完成以后,修改回来或者手动调用一次即可:

# curl -XPOST http://127.0.0.1:9200/logstash-2015.05.01/_refresh

4translog 提供的磁盘同步控制

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

这里,其实有另一个机制来控制。 Elasticsearch 在把数据写入到内存 buffer  的同时,其实还另外记录 了一个 translog 日志。也就是说,第 2 步并不是图 2-2 的状态,而是像图 2-5 这样:

2-5

在第 3 和第 4 步, refresh 发生的时候, translog 日志文件依然保持原样,如图 2-6

2-6

也就是说,如果在这期间发生异常,Elasticsearch 会从 commit 位置开始,恢复整个 translog 文件中的记录,保证数据一致性。

等到真正把 segment 刷到磁盘,且 commit 文件进行更新的时候, translog 文件才清空。这一步,叫做 flush。同样,Elasticsearch 也提供了   /_flush             接口

对于 flush 操作,Elasticsearch 默认设置为:每 30 分钟主动进行一次 flush,或者当 translog 文件大小大于 512MB (老版本是 200MB)时,主动进行一次 flush。这两个行为,可以分别通过

index.translog.flush_threshold_period

index.translog.flush_threshold_size

参数修 改。

如果对这两种控制方式都不满意,Elasticsearch 还可以通过

index.translog.flush_threshold_ops

参数,控制每收到多少条数据后 flush 一次。

5translog 的一致性

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

默认情况下,Elasticsearch 5 秒,或每次请求操作结束前,会强制刷新 translog 日志到磁盘上。

后者是 Elasticsearch 2.0 新加入的特性。为了保证不丢数据,每次 indexbulkdeleteupdate 成的时候,一定触发刷新 translog 到磁盘上,才给请求返回 200 OK。这个改变在提高数据安全性的同时当然也降低了一点性能。

如果你不在意这点可能性,还是希望性能优先,可以在 index template 里设置如下参数:

{

"index.translog.durability": "async"

}

五、集群路由

1、 文档路由

1document路由到shard分片上,就叫做文档路由 ,如何路由? 2)路由算法

算法公式:shard = hash(routing)%number_of_primary_shards

例子:

一个索引index ,3primary shard : p0,p1,p2

增删改查 一个document文档时候,都会传递一个参数 routing number, 默认就是document文档 _id, (也可以手动指定)

Routing = _id,假设: _id = 1

算法:

Hash(1) = 21 % 3 = 0 表示 请求被 路由到 p0分片上面。

  1. 自定义路由请求:

PUT /index/item/id?routing = _id (默认)

PUT /index/item/id?routing = user_id(自定义路由)--- 指定把某些值固定路由到某个分片上面。

  1. primary shard不可变原因

即使加服务器也不能改变主分片的数量

2、增删改原理

  1. 客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)
  2. coordinating node,对document进行路由,将请求转发给对应的node(有primary shard
  3. 实际的node上的primary shard处理请求,然后将数据同步到replica node
  4. coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端

所有文章都是以专栏系列编写,建议系统性学习,更容易成为架构师!

博主每天早晚坚持写博客给与读者价值提升,为了让更多人受益,请多多关照,如果觉得文章质量有帮助到你,请关注我的博客,收藏此文,持续提升,奥利给!

另外我不打算靠运营方式拿到博客专家的认证,纯纯的科技与狠活来征服读者,就看读者的感恩之心了,祝你好运连连。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xianghan收藏册

极简精品作,一分也是一份鼓励哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值