搜索系统关于存储以及检索的思考
笔者本人目前在搜索部门,做的是基于搜索的更加上层的ai 应用,他本质是基于搜索能力以及搜索生态的组合式创新,关于搜索本身,本人对于大数据的数据存储也就是分布式索引构建以及索引检索这两个系统。
随着数据流式生成,持续膨胀,索引,系统必须支持,快速查询以及动态扩展,同时要保证系统的可维护性,这需要一套成熟的索引分片管理机制。
为什么需要分片
因为随着数据量的增大,耽搁索引会变得过大,导致
- 写入性能会变大
- 查询延迟增加
- 扩展性收到限制
因此我们需要将索引插入分为多个分片,每个分片都是独立的索引单元,可以:
- 分布式存储在不同的节点上
- 并行写入查询,提高吞吐和性能
- 独立扩展,按需进行扩容
索引分片的核心管理问题
当数据是流式生成的时候,持续膨胀时,索引分片管理涉及到一下几个关键问题:
1、如何分片?
数据分配到不同的分片上,按照时间或者哈希
2、如何写入?
新数据来了,写入到那个分片,保证写入的高效性
3、如何查询?
数据是如何路由到多个分片,然后在合并相应的结果的
4、如何支持更新?
索引是不可变的,如何支持更新?
5、如何管理声明周期
索引如何滚动、归档、删除?
典型的索引分片管理方法(以分布式搜索引擎为例)
1、分片策略:静态分片 + 动态路由
- 静态分片,在创建索引的时候就指定了分片的数量,分片数量一般不推荐修改
- 动态路由:数据写入时候,通过哈希算法对文档ID 进行取模 决定写入哪个分片中,保证数据分布均匀
优点: 写入路径简单,查询可以并行化
缺点:分片数量固定,无法根据数据增长动态调整
2、写入路径:写入最新活跃索引
新的数据不能直接修改已有的索引,
- 将增量数据写入到一个增量索引中,写入的是近实时的,通常会有一个refresh 机制, 例如每隔一段时间将数据合并到磁盘索引中
- 写入是近实时(Near Real-Time, NRT)的,通常会有一个Refresh 机制(例如每隔 1 秒刷新一次内存中的数据到磁盘索引)
关键点:写入是追加,不会修改历史数据,保证写入的高性能
3、索引的扩容:索引滚动(index rollover)+ 分片再平衡
当耽搁索引数据量过大的时候(超过设定的阈值), 或者写入压力增加时:
- 触发索引滚动(rollover): 创建一个新的索引,后续的数据写入到新的索引中
- 旧的索引变为只读,不再接受新数据
4、索引的更新:不可变索引 + 新索引覆盖
由于索引是不可变的,更新操作(如修改某条文档)不能直接在原索引上修改, 而是:
- 写入一条新的版本到新的索引(或新的分片)
- 查询时候通过版本控制或是加范围使用哪个索引数据
5、索引全声明周期管理
为了自动化管理索引的声明周期,通常会引入ILM 策略
- Hot 阶段:索引正在频繁写入和查询(如最近 1 天的数据)
+ Warm 阶段:索引不再写入,但需要保留用于查询(如 1~7 天的数据)
+ Cold 阶段:索引很少查询,可以转移到低成本存储(如 7~30 天的数据)
+ Delete 阶段:索引过期,直接删除(如 30 天前的数据)