es集群、索引压缩以及相关度评分计算


es的集群
需要有n/2+1的票数才能当选主节点
最好采用 2+ 1部署方案:即3节点集群有一个节点设置为投票节点,这样可以更高效率的选出主节点

 

1.es的选举,选举过程可以看一下源码
首先查找存活的节点,包括自己,然后对节点进行过滤,找出具有投票权的节点
进行投票,记录票数,选出临时master(还不是主节点)
如果主节点是自己,那么向各节点发布通告,自己是主节点,开始接受其他节点的注册
如果主节点不是自己,尝试向主节点进行注册。
开启心跳检测

深度分页问题
当用户查询 select * from x limit 10000 10,如果是分片场景下,且分片无序,需要从每个分片查询100010条数据,然后进行统一排序,这样就非常耗性能
sharding jdbc是怎么做的呢?当查询的数据分片内有序,会流式查询出来,然后进行归并
es的默认数据查询数量窗口为1w,多于该数据会报错
es这边处理这个问题:
1.避免深度分页
如百度,谷歌这种都是不支持跳页的,业务场景上跳页也没有必要,毕竟相关度最高的在前面
2.scroll_search
这个是在内存中全部查询出来排好序,让用户根据上下文一次次去取下面的数据,但并不适合C端场景,也就是类似百度这种,他只适合B端要流式排序获取全部数据的场景
3.search_after
这个是记录查询最后的结果,往后继续迭代,这个不支持往前,如果要使用这种,需要配合缓存使用

 

脑裂问题
1.减少误判,增加心跳检测的时间
2.选举的触发 需要有n/2+1的票数才能当选主节点 比如 3节点的集群,挂掉两个后并不会触发选举, 但只挂掉一个呢?会直接触发选举形成脑裂
3.角色分离

es的倒排索引
三部分组成
1.postinglist
存储的数据 小米 [1,2,4]
for压缩算法
对于差值比较小的数组,会对原数组进行差值存储 比如 [1,2,4] -> [1,1,2]
这样就能把int的4字节进行缩小,比如1 就只需要1bit就能存储

roaringbitmap算法 RBM 适用于稀疏数组
这边是对值进行 2的32次方取模和余, 模作为key, 余作为值
以下是ArrayContainer
short[]
1 23,4323
3 345,45435

每个模组里面都是一段65535的数据

BitMapContainer
这个是一共65535个bit来存储 每一个bit位如果是1,代表该坐标位置的数据是存在的
比如 0 0 0 1 0 0 0 0
7 6 5 4 3 2 1 0
代表我们的idlist里面有个4的数据
BitMapContainer 与 roaringbitmap 相比就是BitMapContainer在65536bit=内空间占用固定,而roaringbitmap是线性增长的,最大占用128kb

runContainer是 记录连续数据的首末位,中间就不记录了,这就完全取决于数据的连续性,如果连续性好,那么可以节省非常大的空间,如果零碎断续,其实没有节省
2.词项字典term

3.词项索引
FST有限状态自动机
对于词的存储使用的是FST数据结构,他的查询效率近似map但是不如map,但是空间使用率比map要小很多
节约空间主要是复用了相同词的节点,这块的思想是利用最小通用算法
比如 abc,abe,abef,abcf

a-b-c\
      \e-f
这样就能节省大量的重复词占用的空间

多字段匹配
best_fields 按匹配度最高的字段计算得分,不过可以配置 tie_breaker来给其他字段设置评分
cross_fields 多字段一起参与评分
most_fields 每个字段的权重一样

聚合的时候可选择深度优先还是广度优先算法
collect_mode: breadth_first/depth_first

相关度评分,可以使用_explain查看执行计划
1.TF-IDF
1.词频 出现次数高就多
2.反词频 全索引出现的多,证明该词很通用,不适用于检索
3.文档长度规约,doc长度,越长评分越低
计算公式:

score(q,d) =
queryNorm(q)
coord(q,d)
Σ (
tf(t in d)
idf(t)²
t.getBoost()
norm(t,d)
) (t in q)


2.BM25
BM25降低了TF的评分增益
反词频IDF

{
"value" : 0.47000363,
"description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
"details" : [
{
"value" : 2,
"description" : "n, number of documents containing term",
"details" : [ ]
},
{
"value" : 3,
"description" : "N, total number of documents with field",
"details" : [ ]
}
]
}
词频 TF
{
"value" : 0.5263158,
"description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
"details" : [
{
"value" : 1.0,
"description" : "freq, occurrences of term within document",
"details" : [ ]
},
{
"value" : 1.2,
"description" : "k1, term saturation parameter",
"details" : [ ]
},
{
"value" : 0.75,
"description" : "b, length normalization parameter",
"details" : [ ]
},
{
"value" : 2.0,
"description" : "dl, length of field",
"details" : [ ]
},
{
"value" : 3.0,
"description" : "avgdl, average length of field",
"details" : [ ]
}
]
}

 


评分都是基于分片内来计算的,ES有自己的分片策略,在不了解分布式文档路由原理的前提下,不要随意使用 routing 来指定文档的分配机制。以免挖坑。

ES的并发版本控制
_version 文档及的版本号
_seq_no 是索引级的
_primary_term 是节点级的


ES的写入过程
先计算数据的hash,路由到对应的主分片节点,进行写入
写一致性原理
wait_for_active_shards 参数来控制返回客户端之前必须处于active的分片数,默认为1,即只要主分片成功写入,默认情况下主分片的写入会等待1分钟,1分钟后没返回就会失败

索引的操作
索引别名的作用相当于域名,对真实索引进行反向代理
索引压缩、刷新、迁移、别名、滚动索引

 

posted @ 2024-05-20 21:24  有虫子啊  阅读(15)  评论(0编辑  收藏  举报