倒排索引,分片机制
目录
2.1 primary shard 和 replica shard机制
1. 倒排索引及其数据结构以及优缺点
1.1 倒排索引
Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
例如,假设我们有两个文档,每个文档的 content
域包含如下内容:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们首先将每个文档的 content
域拆分成单独的 词(我们称它为 词条
或 tokens
),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:
-
Term Doc_1 Doc_2
-
-------------------------
-
Quick | | X
-
The | X |
-
brown | X | X
-
dog | X |
-
dogs | | X
-
fox | X |
-
foxes | | X
-
in | | X
-
jumped | X |
-
lazy | X | X
-
leap | | X
-
over | X | X
-
quick | X |
-
summer | | X
-
the | X |
-
------------------------
现在,如果我们想搜索 quick brown
,我们只需要查找包含每个词条的文档:
-
Term Doc_1 Doc_2
-
-------------------------
-
brown | X | X
-
quick | X |
-
------------------------
-
Total | 2 | 1
两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单 相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。
但是,我们目前的倒排索引有一些问题:
-
Quick
和quick
以独立的词条出现,然而用户可能认为它们是相同的词。 -
fox
和foxes
非常相似, 就像dog
和dogs
;他们有相同的词根。 -
jumped
和leap
, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。
使用前面的索引搜索 +Quick +fox
不会得到任何匹配文档。(记住,+
前缀表明这个词必须存在。)只有同时出现 Quick
和 fox
的文档才满足这个查询条件,但是第一个文档包含 quick fox
,第二个文档包含 Quick foxes
。
我们的用户可以合理的期望两个文档与查询匹配。我们可以做的更好。
如果我们将词条规范为标准模式,那么我们可以找到与用户搜索的词条不完全一致,但具有足够相关性的文档。例如:
-
Quick
可以小写化为quick
。 -
foxes
可以 词干提取 --变为词根的格式-- 为fox
。类似的,dogs
可以为提取为dog
。 -
jumped
和leap
是同义词,可以索引为相同的单词jump
。
现在索引看上去像这样:
-
Term Doc_1 Doc_2
-
-------------------------
-
brown | X | X
-
dog | X | X
-
fox | X | X
-
in | | X
-
jump | X | X
-
lazy | X | X
-
over | X | X
-
quick | X | X
-
summer | | X
-
the | X | X
-
------------------------
这还远远不够。我们搜索 +Quick +fox
仍然 会失败,因为在我们的索引中,已经没有 Quick
了。但是,如果我们对搜索的字符串使用与 content
域相同的标准化规则,会变成查询 +quick +fox
,这样两个文档都会匹配!
1.2 倒排索引结构
(1)包含这个关键词的document list
(2)包含这个关键词的所有document的数量:IDF(inverse document frequency)
(3)这个关键词在每个document中出现的次数:TF(term frequency)
(4)这个关键词在这个document中的次序
(5)每个document的长度:length norm
(6)包含这个关键词的所有document的平均长度
1.3 倒排索引不可变
(1)不需要锁,提升并发能力,避免锁的问题
(2)数据不变,一直保存在os cache中,只要cache内存足够
(3)filter cache一直驻留在内存,因为数据不变
(4)可以压缩,节省cpu和io开销
每次都要重新构建整个索引,比较繁琐。
2. 分片、扩容以及容错机制
2.1 primary shard 和 replica shard机制
(1):index包含多个shard;
(2):每个shard都是一个最小的工作单元,承载部分的数据,Lucene实例,完整的简历索引和处理请求的能力;
(3):增减节点时,shard会自动在nodes中负载均衡;
(4):primary shard和replica shard,每一个doc只会存在某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard中;
(5):replica shard是primary shard的副本,负责容错,以及承担读请求负载(通常情况可以让primary shard负责写,replica shard负责读,来实现读写分离);
(6):primary shard 的数量在创建索引的时候就固定了,replica shard的数量可以随时修改;
(7):primary shard的默认数量是5,replica shard默认是1,默认有10个shard,其中5个primary shard以及5个replica shard;
(8):primary shard和replica shard不能和自己的replica shard 放在一个节点中(这样规定是为避免节点宕机的时候,primary shard和replica shard数据都都丢失,起不到容错的作用),但是可以和其他的primary shard的replica shard放在同一个节点中;
2.2 极限扩容
性能扩容
就像上面说的primary shard 在创建的时候就已经固定了,不可以再修改。也就是说如果我在创建的时候设置了primary shard是3(6个shard,3 primary,3 replica),最多扩容到6台机器,每个shard可以占用单台服务器的所有资源,性能最好。那如果我们的超出了上面所说的扩容极限了怎么办呢?primary shard不是不能修改么?
是的,primary shard 在创建后是不能修改的,但是replica shard可以添加啊,我们可以创建9个shard(3primary,6 replica),将服务器扩容到9台机器,吞吐量会大大增加,是3台服务器的三倍,当然为了提高容错率也可以在此基础上在每台服务器上部署多个shard(primary和replica不能在同一台服务器上)
容量扩容
上述的扩容指的是性能上的扩容(即高可用),但是在实际生活中可能会面临需要内存上扩容,他的极限就是每个primary shard部署单台服务器(3个primary shard分别部署3台服务器),所以在创建的时候自己要注意创建primary shard的数量,如果内存上问题还是不能解决,那么就需要通过扩容磁盘和定期清理数据来解决内存问题了
2.3 容错机制
master node宕机后,会自动重新选举master,此时为red;
replica容错:新master是将replica提升为primary shard,此时为yellow(因为replica被升级为primary了,此时replica并不齐全);
重启宕机node,master copy replica到该node,但是该node使用原有的shard并同步宕机后的修改(即仅同步宕机后丢失的数据),此时为green;