中间件ES(Elastic Search)

image-20240816142759894

分词操作个人理解就是在做一个表来记录term和id的关系,可能会再存储一大段信息的时候会出现一定时间的延迟创建。

优化,先按字典序排序通过二分查找来找到词项。

image-20240816143228788

Term dictionary过大所以不可能会放在内存里面,但是放在磁盘里面,搜索过程又会很慢。

优化

每一个词项会有相似的地方,那么把这些相似的地方拎出来进行复用,然后就能构建出一个目录树的结构,进行偏移量的辅助指向后续拼接的term。感觉有一点像计算机的存储方式结构。

image-20240816160254477

term index(上面优化出来的目录树结构就是index)

通过index能够找到term的大概位置,通过少量的检索找到target.

Stored Fields

存放完整文档内容,行式存储结构

Doc Values

空间换时间,把形同的字段归纳在一起,列式存储结构。

segment

具备完整搜索功能的最小单元

image-20240816161638829

Lucene

  • 因为segment结构特殊,若是有数据写入,则需要刷新整个segment架构的所有信息。这样读取和写入若是并行的话,性能会大量降低。因此为了规避这个风险,所以不允许新的信息写入segment,所以只能生成新的segment,那么问题就来了,我怎么知道我要取的信息在哪个Segment里面呢。
  • 为了解决上面的问题,所以需要程序进行并发读取,但是随着数据量过大,并发读取的任务就会变得很重。导致文件句柄耗尽。
  • 为了解决句柄消耗严重的问题引出了段合并,segment merging,这个功能就是解决了segment过多的问题,是用来把小一点的segment合并成一个大的segment。和前面的不允许新的信息写入是不冲突的。

到这里都还没有解释到lucene,综合上面多个segment组成的一个单机文本检索库,这个就是一个有名的开源基础搜索库Lucene

Lucene高性能

其实和kafka的原理基本都是一样的,为了用多用户并发读取,所以就回用topic来继续区分,在Lucene中我们叫index name,继续topic里面可能存在的问题,所以会把这个topic区分片,形成partition,我们这里叫作shard。其实每一个shard就是一个独立Lucene库。

Lucene高扩展
  • 为了避免多个分片shard过多导致性能过高,存在宕机隐患。我们可以把它们不定的shard放在不同的node里面,来防止性能过高。
Lucene高可用
  • 为了避免node换了,到时分片shard不能服务,保证高可用,添加副本,分词主分片和负分片,主分片会同步到副分片,副本分片不仅能够提供读操作也能够保证主分片挂了时候顶上
node分化
  • 为了避免某个集群压力过大,若是每个node都需要集群管理,存储数据,和处理请求的功能,这会导致node的压力还是会变大。所以会进行角色分化的一个操作,每一个node负责不一样的功能。

image-20240816164543933

去中心化

image-20240816164646524

总图 这就是ES

image-20240816164731547

写入流程

image-20240816165843222

搜索流程

查询阶段

搜索内容:跳过。

转发:是通过index name了解信息在哪个分片和哪个node上面,让后Lucene会并发搜索segment来获取倒排索引的文档id和docvalues获取排序信息。

返回:聚合返回协调节点,然后排序聚合。

image-20240816170246591

获取阶段

找寻分片:通过文档id,在Stored Fields获取完整文档,然后返回给协调节点,然后返回给客户。

image-20240816170854349