• Elasticsearch 调优之 shrink


    对于索引分片数量,我们一般在模板中统一定义,在数据规模比较大的集群中,索引分片数一般也大一些,在我的集群中设置为 24。但是,并不是所有的索引数据量都很大,这些小数据量的索引也同样有较大的分片数。在 elasticsearch 中,主节点管理分片是很大的工作量,降低集群整体分片数量可以降低 recovery 时间,减小集群状态的大小。很多时候,冷索引不会再有数据写入,此时,可以使用 shrink API 缩小索引分配数。缩小完成后,源索引可删除。

    shrink API 是 es5.0之后提供的新功能,他并不对源索引进行操作,他使用与源索引相同的配置创建一个新索引,仅仅降低分配数。由于添加新文档时使用对分片数量取余获取目的分片的关系,原分片数量是新分片倍数。如果源索引的分片数为素数,目标索引的分片数只能为1.

    我们跟随一个例子,分析缩小过程。

    准备源索引

    创建索引: my_source_index,5个主分片,1个副分片,并写入几条测试数据

    通过下面的命令,将索引标记为只读,且所有分片副本都迁移到名为node-idea的节点上。

    注意,“所有分片副本”不指索引的全部分片,无论主分片还是副分片,任意一个就可以。分配器也不允许将主副分片分配到同一节点。

    选项:
    index.blocks.write
    设置为 true 来禁止对索引的写操作。但索引的 metadatra 可以正常写。

    缩小索引

    执行shrink:

    这将创建含义一个主分片和一个副分片的目的索引:my_target_index

    恢复原索引写操作
     
    PUT /source_index/_settings
     
    {
     
    "settings": {
     
    "index.blocks.write": false
     
    }
     
    }

    shrink 工作过程

    引用官方手册对 shrink 工作过程的描述:

    • First, it creates a new target index with the same definition as the source index, but with a smaller number of primary shards.
    • Then it hard-links segments from the source index into the target index. (If the file system doesn’t support hard-linking, then all segments are copied into the new index, which is a much more time consuming process.)
    • Finally, it recovers the target index as though it were a closed index which had just been re-opened.

    创建新索引

    第一点,使用旧索引的配置创建新索引,新索引的 shard 同样需要与源索引一样,所有副本都分配到相同节点,否则无法执行硬链接

    创建硬链接

    从源索引到目的索引创建硬链接。如果操作系统不支持硬链接,就拷贝lucene 分段。

    在 linux 下通过 strace 命令跟踪硬链接创建过程,能清晰看到内部过程:

    图中基本信息
    JYglvWRnSqmNgA3E1CahZw 为源索引
    RvDP65d-QD-QTpwOCaLWOg 为目的索引
    _0.cfe,_0.si,_0.cfs 类型的文件为 lucene 编号为 0 的 segment,编号依次类推

    链接过程
    从源索引的 shard[0] 开始,遍历所有 shard,将所有 segment 链接到目的索引,目的索引的 segment 从 0 开始命名,依次递增。在本例中,由于源索引的 shard[0] 没有数据,因此从 shard[1] 开始链接

    为什么一定要硬链接,不使用软链接?
    文件系统由两部分组成,inode 和 block。block用于存储用户数据,inode 用于记录元数据,系统通过 inode 定位唯一的文件。
    硬链接:文件有相同的 inode 和 block
    软链接:文件有独立的 inode 和 block,block 内容为目的文件路径名
    那么为什么一定要硬链接过去呢?如果软链接过去,删除源索引,目的索引的数据也会被删除,硬链接则不会。满足下面条件时操作系统才真正删除文件:

    文件被打开的 fd 数量为0且硬链接数量为0

    使用硬链接,删除源索引,只是将文件的硬链接数量减1
    由于使用了硬链接,也因为硬链接的特性带来一些限制:不能交叉文件系统或分区进行硬链接的创建,因为不同分区和文件系统有自己的 inode。

    不过,既然都是链接,shrink 完成后,修改源索引,目的索引会变吗?答案是不会。虽然链接到了源分段,shrink 期间索引只读,目标索引能看到的只有源索引的当前数据,shrink 完成后,由于 lucene 中分段的不变性,源索引新写入的数据随着 refrensh 会生成新分段,而新分段没有链接,在目标索引中是看不到的。如果源索引进行 merge,源分段被删除,硬链接数量减1,目标索引仍然不受影响。因此,shrink 完毕后最终的效果就是,两个索引的数据看起来是完全独立的

    目的索引 recovery

    经过链接过程之后,主分片已经就绪了,副分片还是空的,通过 recovery 将主分片数据拷贝到副分片。recovery 如何触发的?就是通过内部对索引的_close 再_open 操作

    事实上,硬链接也是走的 recovery 流程,下面看一下相关实现代码

    硬链接过程源码分析

    硬链接过程在目标索引 my_target_index 的恢复流程中,入口:IndexShard#startRecovery,有下列几中类型的recovery:

    • EXISTING_STORE 主分片从 translog恢复
    • PEER 副分片从主分片远程拉取
    • SNAPSHOT 从快照恢复
    • LOCAL_SHARDS 只有 shrink 用到?

    此时的恢复类型为 LOCAL_SHARDS,执行 storeRecovery.recoverFromLocalShards在 addIndices中,调用 lucene 中的 org.apache.lucene.store.HardlinkCopyDirectoryWrapper实现硬链接。

    addIndices 将整个源索引的全部 shard 链接到目标路径。

    本例中源索引由5个分片,sources 的值为:

    target 值为:

  • 相关阅读:
    python 进程、线程、协程感悟
    elk部署心得
    虚拟安装centos后无法上网、DNS无法解析问题解决
    mysql测试题
    爬取lol皮肤
    ping使用
    第一篇技术博客
    PADS layout修改字符时发生严重错误退出问题
    PADS 快捷键
    电容知识整理
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/11158628.html
Copyright © 2020-2023  润新知