es的分片和副本_Elasticsearch的分布式存储与分片内部原理

1、文档如何存储

1.1 分片与路由

当索引一个文档的时候,文档会被存储到一个主分片中。Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。(这里我很纳闷为什么不使用一致性hash,一致性hash可以解决动态添加节点的问题啊???)

所有的文档 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一个叫做 routing 的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

2、主分片与副本分片的交互

2.1 分片之间的交互

49896c64b097a0d657661922f0d78301.png

这是我创建的一个测试索引,该索引包含两个分片和两个副本,六个分片的状态如下顺序如上图依次展示,可以看到有两个主分片以及四个副本分片。

956a45e28f8fbc8f858b378ae7b0b559.png

那么如果要修改数据,这些分片是如何交互的呢?

  1. 客户端发出新建、索引、删除请求,请求被发送到node-1节点

  2. 节点使用索引的_id确定文档的分片位置,如果确定文档属于分片1,那么就会在当前节点node-1执行请求

  3. 请求执行成功后,那么会将该请求并行转发到node-2和node-3的副本分片上,副本分片执行成功后向node-1节点报告请求成功,那么node-1节点会向客户端报告成功。

3、分片内部原理

3.1 为什么是近实时搜索而不是实时搜索?

Elasticsearch并没有做到实时搜索,而是近实时搜索,当我们修改一个文档时,修改的内容并不会对搜索实时可见,需要等待一秒才可以。

而这个过程的实现原理为,修改的数据需要刷新到内存中的可被搜索区中才可以被es搜索。

如下图中修改的数据首先存放在buffer中,而可被搜索的数据是存放在searchable(searchable中存放的是一个个的segementFile)中,所以想要数据可被搜索需要将buffer中的数据刷新到searchable中。

e2c8b74debba9a6d6e09899d37707166.png

同时buffer中的数据每隔1s会刷新一次到searchable中,这也是近实时搜索的由来。fea9d7ac7e53dc3385818fb6d5e2b998.png

上图是缓冲区的内容已经被写入一个可被搜索的段中,但还没有进行提交。

3.2 Elasticsearch持久化是如何实现的?

从上个问题中可以知道数据都是在内存的存储都是在内存层面的,如果Es宕机,那么数据就会丢失,那么为了保证数据的持久化,需要将内存中的数据持久化到磁盘中。而Es是如何实现的呢?

Es的持久化类似数据库的binlog,在Es中通过一个Translog文件存储对Es的CRUD操作。下图中当数据写入到buffer中时,会同步追加到一个Translog文件中,Translog文件相当于数据库中的binlog日志,存储对Es的时 CRUD 操作。但是Translog文件也是存储在内存中的,相当于占据了内存中的一块区域,因此就需要将Translog中的数据持久化到磁盘中完成对Es的持久化。

Translog文件每5s执行依次刷新操作,将Translog数据刷新到磁盘中,当刷新到磁盘之后Translog会被清空,新的数据会重新存储到Translog中,执行下一轮的持久化。

4b5ec85e7379ea18a7ecd27edae71466.png

关于Translog的问题,官方文档中写到了两个问题,一个是删除Translog文件,然后重新创建新的Translog文件,另一种是清空Translog文件。

156a05f248673d4bff535f2ed7cf7260.png

这里再强调两个问题:

  • 当buffer中的数据刷新到searchable中时,buffer就会被清空,再重新写入数据。

  • searchable的数据也是存储在内存中的,因此也需要刷新到磁盘中,这也是上图中标明Commit point的原因,每一个Commit point都是一个提交点,每三十分钟执行依次提交或者当Translog日志容量达到512m时也会提交到磁盘中。

小结:

1、Es中buffer的数据每1s执行一次刷新到searchable的操作

2、Es的持久化通过Translog日志来实现,每5s执行依次刷新到磁盘的操作。

3、searchable中存储的就是一个个的segementFile文件

4、seachable的数据每30分钟或Translog日志达到512m执行依次刷新到磁盘的操作

5、Translog的刷新频率可以通过命令修改:PUT /my_index/_settings

{

    "index.translog.durability": "async",

    "index.translog.sync_interval": "5s"

}

3.3 什么是段合并?

由于自动刷新流程每秒会创建一个新的段 ,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。每一个段都会消耗文件句柄、内存和cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。

Elasticsearch通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。

启动段合并不需要你做任何事。进行索引和搜索时会自动进行。

下图是两个提交了的段和一个未提交的段正在被合并到一个更大的段

2b2fb78b7d2e061c1ff690fa4392b45b.png

段合并也会删除老的段,上图合并之后会删除三个老的段。

a9a776b359e3c15a5343ee26c90e5d20.png

通过段合并Es提高了搜索的性能,但是合并段也需要做一定的限制,防止段的数据过大消耗过大的I/O和CPU资源。

3.4 什么是倒排索引?

在ES中使用了一种倒排搜索的结构,这种结构可以实现快速的全文搜索。

理解倒排索引先知道正排索引,正排搜索就如同我们平时看的书,书对应内容,比如《骆驼祥子》这本书,这本书和内容的对应关系如下:

《骆驼祥子》----------->祥子、虎妞、小福子、刘四爷、骆驼........

如果我们要从书中找骆驼这个内容,我们就需要对书的内容进行全量的遍历,得到我们想要的数据。因此对于正排索引,书名是key,内容是value。

而倒排索引则相反,书和内容的关系如下:

祥子------------>《骆驼祥子》

虎妞------------>《骆驼祥子》

小福子------------>《骆驼祥子》

刘四爷------------>《骆驼祥子》

骆驼------------>《骆驼祥子》

如果查询骆驼两个字,则直接可以找到,因此骆驼两个字就是索引。所以倒排索引中拆分的内容是key,书名是value。

因此对比到ES中的倒排索引,key是拆分的词,value是document。

bdb7b8c8cb583bcf6b03aa7a4053288d.png

因此如果我们要搜索上如中的quick brown,则搜索结果如下:

4be3462ae4764d6ca38a1fa2cfa0e3ff.png

ES通过这样的方式实现全文搜索,提高搜索效率。

倒排搜索特点:

  • 在索引时创建
  • 序列化到磁盘
  • 全文搜索非常快
  • 不适合做排序
  • 默认开启
适用场景:
  • 查询
  • 全文检索

6、小结

  • 理解近实时搜索的含义

  • 理解ES中的倒排索引的使用

  • Translog是如何进行持久化的

  • ES中分片是如何交互的

  • ES的写入通过buffer以及Translog实现,实现过程是怎样的(这里可以查看大佬的文章:https://blog.csdn.net/xiaoyu_BD/article/details/81735473)


参考: 

  1. Elastic 官方文档

  2. 铭毅天下

  3. https://blog.csdn.net/xiaoyu_BD/article/details/81735473

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值