特性操作
- 手动或者自动生成id
POST /shop/product #自动,必须是post PUT /shop/product/4 #手动制定
- 定制源返回结果
GET /shop/product/4?_source=name #只返回name列
-
delete操作不会立即删除,只是标记删除,如果数据多了,才会删除
-
primary shard和replica 同步更新的时候是并发同步,版本较后的如果先到,版本前面的后到,就会丢弃
-
完整数据更新流程
- 客户端发送数据给任意节点,这个节点就变为协调节点
- 根据路由算法,默认根据_id%shard数量算doc存到那个shard #所以不能更改shard数量
- 协调节点发送数据给可以处理的shard节点
- shard判断是post还是put操作,如果是post操作,把上一个版本的数据取出来,内存中修改好全量数据,部分更新,旧版本标记为delete
- 把数据存入buffer,默认1s将数据刷入index segment(NTR的原因) ,同时将数据同步给replica ,返给协调节点为成功
- 协调节点把数据返回给客户端
-
version并发控制
?version=1 ?version=1&version_type=external
version_type=external,唯一的区别在于,_version,只有当你提供的version与es中的_version一模一样的时候,才可以进行修改,只要不一样,就报错;当version_type=external的时候,只有当你提供的version比es中的_version大的时候,才能完成修改
- 手动制定路由值(默认:_id)
也可以在发送请求的时候,手动指定一个routing value,比如说put /index/type/id?routing=user_id
手动指定routing value是很有用的,可以保证说,某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的
- quorum机制
consistency,one(primary shard),all(all shard),quorum(default) put /index/type/id?consistency=quorum
one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行 all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作 quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作
-
timeout机制 达到timeout时间,就先返回一部分数据
-
deep paging 原理 GET /_search?size=10&from=20 协调节点,从所有的shard上分别取出来10条,然后合并排序,再取出来10条,这个才是结果
-
_all query string查询原理 在搜索的时候,没有对某个field指定搜索,就默认搜索_all field,其中是包含了所有field的值的
es在新建一个doc的时候,会将各个字段的值,合并到_all字段中去
-
精准匹配(exact )和全文匹配 查询倒排索引,排序正排索引 建立倒排索引的时候,以对值进行拆分词语后(分词)进行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配
-
_mapping
- 往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping
- mapping中就自动定义了每个field的数据类型
- 不同的数据类型(比如说text和date),可能有的是exact value,有的是full text
- exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;full text,会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换),才会建立到倒排索引中
- 同时呢,exact value和full text类型的field就决定了,在一个搜索过来的时候,对exact value field或者是full text field进行搜索的行为也是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索
- 可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等
mapping,就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为
-
是否建立索引设置
analyzed not_analyzed no
"publisher_id": { "type": "text", "index": "not_analyzed" }
-
filter和query
filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响 query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序
-
query bool must,must_not,should,filter
-
字符串排序问题
通常解决方案是,将一个string field建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序
"mappings": {
"article": {
"properties": {
"title": { #分词
"type": "text",
"fields": {
"raw": { #原始数据
"type": "string",
"index": "not_analyzed" #不分词
}
},
"fielddata": true
},
-
term frequency/inverse document frequency算法,简称为TF/IDF算法
TF:各个词条出现的频率 IDF:搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关
#分析一个document是如何被匹配上的
GET /test_index/test_type/6/_explain
{
"query": {
"match": {
"test_field": "test hello"
}
}
}
- scoll滚动搜索
可以先搜索一批数据,然后下次再搜索一批数据(根据上一次返回的_scroll_id),以此类推,直到搜索出全部的数据来
看起来挺像分页的,但是其实使用场景不一样。分页主要是用来一页一页搜索,给用户看的;scoll主要是用来一批一批检索数据,让系统进行处理的
-
reindex(重建索引) 类型一旦建立,无法修改,比如date改成string 使用别名+scoll+bulk
-
倒排索引的结构
- 包含这个关键词的document list
- 包含这个关键词的所有document的数量:IDF(inverse document frequency)
- 这个关键词在每个document中出现的次数:TF(term frequency)
- 这个关键词在这个document中的次序
- 每个document的长度:length norm
-
包含这个关键词的所有document的平均长度
倒排索引不可变的好处
- 不需要锁,提升并发能力,避免锁的问题
- 数据不变,一直保存在os cache中,只要cache内存足够
- filter cache一直驻留在内存,因为数据不变
- 可以压缩,节省cpu和io开销
倒排索引不可变的坏处:每次都要重新构建整个索引
- 再次优化的写入流程
- 数据写入buffer缓冲和translog日志文件
- 每隔一秒钟,buffer中的数据被写入新的segment file,并进入os cache,此时segment被打开并供search使用
- buffer被清空
- 重复1~3,新的segment不断添加,buffer不断被清空,而translog中的数据不断累加
- 当translog长度达到一定程度的时候,commit操作发生
- buffer中的所有数据写入一个新的segment,并写入os cache,打开供使用
- buffer被清空
- 一个commit ponit被写入磁盘,标明了所有的index segment
- filesystem cache中的所有index segment file缓存数据,被fsync强行刷到磁盘上
-
现有的translog被清空,创建一个新的translog
基于translog和commit point,如何进行数据恢复
fsync+清空translog,就是flush,默认每隔30分钟flush一次,或者当translog过大的时候,也会flush
POST /my_index/_flush,一般来说别手动flush,让它自动执行就可以了
translog,每隔5秒被fsync一次到磁盘上。在一次增删改操作之后,当fsync在primary shard和replica shard都成功之后,那次增删改操作才会成功
但是这种在一次增删改时强行fsync translog可能会导致部分操作比较耗时,也可以允许部分数据丢失,设置异步fsync translog