• 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 值为:

  • 相关阅读:
    hive与hbase整合
    待重写
    hive DML
    【知识强化】第六章 总线 6.1 总线概述
    【知识强化】第五章 中央处理器 5.1 CPU的功能和基本结构
    【知识强化】第四章 指令系统 4.3 CISC和RISC的基本概念
    【知识强化】第四章 指令系统 4.2 指令寻址方式
    【知识强化】第四章 指令系统 4.1 指令格式
    【知识强化】第三章 存储系统 3.6 高速缓冲存储器
    【知识强化】第三章 存储系统 3.5 双口RAM和多模块存储器
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/11158628.html
Copyright © 2020-2023  润新知