es是开源的高扩展的分布式、RESTful风格、全文搜索和分析引擎。ELK技术栈的核心部分。
可以实现近乎实时的存储,检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别数据。
针对的数据类型是:
- 安装:略
- 端口:
- 【9300】内部组件通信端口
- 【9200】浏览器访问http协议的restful端口
- 7.8版本需要jdk8以上
存储结构
es是面向文档型的数据库,一条数据就是一个文档。
es中的存储结构包括
- index:索引,相当于一个库
type,在es7以后被删除了- document:一条数据
- fields:字段,数据的属性
restful& json
restful
es的所有操作都是通过restful请求实现。
restful是资源定位、资源操作的一种规范,一种风格。REST式的web服务是一种ROA(面向资源的架构)。
规则要求使用http方法表明对资源的操作;使用URI确定资源。URI中不应包含与资源无关的其他描述(如,动词),仅仅能够指向对应资源。
- 路径是资源的定位
- 方法是资源的操作(请求方法)
- 【GET,POST,PUT,DELETE,HEAD,PATCH,OPTIONS】
URI:统一资源标识符,通过URI能够确定某资源
URL:统一资源定位符,通过URL能够找到某资源,URL是URI的子集。
幂等性
同样的多次请求并不会产生不同的结果,每次请求都是相同的结果(对数据的影响是相同的)。如,get请求,并不是保证返回结果是相同的,而是对资源本身没有影响。
HTTP方法名称 | 描述 | 是否幂等 | 是否安全 |
---|---|---|---|
OPTIONS | 常用于获取服务器信息,不会对资源产生影响,也不会对资源进行修改。 - OPTIONS方法最常见的场景是在浏览器的跨域请求中,如果浏览器发起的是一个跨域访问的API(不论是GET方法还是POST方法),在真正发送业务之前发送一个OPTIONS方法从服务端获取信息,从返回的信息中得获取到是否支持跨域访问,从而决定下一步是否能成功发送真正的业务请求。 |
Y | Y |
HEAD | 用于请求资源的头部信息,不会对资源产生影响,也不会对资源进行修改。 | Y | Y |
GET | 用于获取资源信息,虽然可能每次返回的结果都不相同,但是GET方法本身不会对资源产生影响,在RESTFul语义里GET方法也不会修改资源。 | Y | Y |
PUT | 在RESTFul语义里表示对资源进行全量更新,因此调用1次或N次的结果都是一致的。 | Y | N |
DELETE | 用于删除资源,调用1次或N次的结果都是相同的,因此是幂等的,但不是安全的。 | Y | N |
POST | 在RESTFul语义里表示新建资源,调用1次与调用N次的结果不同。 | N | N |
PATCH | 在RESTFul语义里表示对资源的局部更新,因此不能保证调用1次与调用N次的结果相同。 | N | N |
Json
ES中数据的发送与响应是Json格式
Json:javascript object notation 表示特殊标记的JavaScript对象。极其适合序列化,在网络中传递。 对象中可以嵌套对象,整个对象作为属性。数组使用[]包裹 var obj = { “name”: “zhangsan”, “age”: 20, “info”: { “addr”: “xx” } } var objs = [obj,obj]
HTTP操作
post请求幂等非幂等均可以。请求后会返回一个id,不指定的情况下返回一个随机的字符串。可以自定义,自定义返回id的情况下,请求就是幂等性的,那么同样可以使用put请求。
DELETE方法也是幂等性的。
url请求参数
路径参数 | 作用 |
---|---|
_cat | 打印信息 |
_doc | 文档数据操作 |
_create | 文档数据的创建 |
_serach | 全查询 |
_update | 更新数据 |
_mapping | 映射,类似mysql表结构 |
_cluster | 集群操作,heath健康状态 |
_analyze | 文档分析 |
_setting | 设置 |
_all | 应用于所有数据 |
请求参数说明
请求参数 | 说明 |
---|---|
from | 起始位置 |
size | 查询数量 |
_source | 显示字段 |
sort | 排序 |
must | 同时成立,类似and |
must_not | 必须不是xxxx |
should | 不用同时成立,类似or,满足条件最好,得分会更高,不满足没有关系 |
term | 和match一样可以匹配属性值,全文检索用match,非text字段使用term |
match | 分词匹配 |
match_phrase | 完全匹配 |
multi_match | 多字段分词匹配 |
filter | 过滤条件 |
range | 查询范围 |
highlight | 高亮显示 |
aggs | 聚合操作 |
avg | 求平均值 |
terms | 分组 |
type | 索引结构定义中字段类型,keyword关键字类型不支持分词 |
index | 索引结构定义中是否支持索引,false不支持根据该字段查询。 |
响应结果字段描述
键名称 | 描述 |
---|---|
hits | 查询匹配的根节点 |
total | 表示匹配到的文档总数 |
hits[] | hits数组包含了匹配到的前10条数据 |
_index | 索引,相当于数据库 |
_type | 文档类型,相当于数据库表 |
_id | 每个文档的标识符 |
_version | 版本号 |
_seq_no | 并发控制字段,每次更新+1,乐观锁控制 |
_primary_term | 同上,主分片重新分配时会改变 |
_source | 文档存储的实际数据 |
_score | 相关性得分(relevance score),它衡量了文档与查询的匹配程度。默认的,返回的结果中关联性最大的文档排在首位 |
took | 整个搜索请求花费的毫秒数 |
_shards | _shards节点告诉我们参与查询的分片数(total字段),有多少是成功的(successful字段),有多少的是失败的(failed字段) |
timed_out | 查询超时与否 |
_version和_seq_no: post更新会对比原来的数据,如果一样,_version不发生变化,seq_no也不变。 put和不带_update的post请求会直接更新_seq_no和_version。
// 创建索引
【put】 http://localhost:9200/indexname
// 获取索引信息
【get】 http://localhost:9200/indexname
// 查看所有索引信息
【get】 http://localhost:9200/_cat/indeices?v
// 删除索引
【delete】http://localhost:9200/indexname
// 创建文档(支持自定义id)
【post】http://localhost:9200/_doc(/id)
// 根据id查询文档
【get】http://localhost:9200/_doc/id
// 全查询,也可以使用json【{"query":{"match_all":{}}}
【get】http://localhost:9200/_serach
// 根据id修改数据(id已经存在)【全量修改】,会更新版本
【put】http://localhost:9200/_doc/id
// 修改数据,局部修改
【post】http://localhost:9200/_update/id
// 删除数据
【DELETE】http://localhost:9200/_doc/id
// 根据条件查询(category=小米),也可以使用json【{"query":{"match":{"category":"小米"}}}】
【get】http://localhost:9200/_serach?q=category:小米
// 分页查询,使用json【{"query":{"match_all":{},"from":0,"size":2,"_source":["category"]}}
【get】http://localhost:9200/_serach
// 查询请求json
{
"query": {
"match_all": {}, // 查询所有数据
"from": 0, //起始位置
"size": 2, //查询数量
"_source": ["category"], //显示字段
"sort":{
"price": {
"order":"desc" //倒序排序
}
}
},
highlight:{ //高亮显示
"fields":{ //高亮字段列表
"category":{} //高亮显示
}
}
}
// 多条件查询
{
"query": { //查询操作
"bool": { //查询条件集合
"must": [ // 同时成立,等同于and;should等同于or
{
"match": { // 分词匹配条件
"category": "小米" //条件1
}
},
{
"match": {
"category": "华为" //条件2
}
}
],
"filter": { //过滤条件
"range": { //范围
"price": { //条件
"gt": 5000 //大于5000
}
}
}
}
}
}
// 聚合查询
{
"aggs": { //聚合查询
"price_group": { //查询名称,随意
"terms": { // 分组 【avg】平均值
"filed": "price" // 分组字段
}
}
},
"size": 0 // 只显示聚合结果,不显示其他
}
// 索引结构json
{
"properties": {
"name": {
"type": "text",
"index": true
},
"sex": {
"type": "keyword",
"index": true
}
}
}
//
//
API操作
- 导入依赖
- 创建mvn工程
集群环境搭建
win环境解压后目录
- 【data】存放数据
- 【log】存放日志
- 【bin】存放启动命令
- 【jdk】自带jdk环境
- 【config】配置文件
- 【modules】模块
- 【plugins】存放插件
配置文件修改内容
- 【cluster.name】集群名称
- 【node.name】节点名称,不能重复
- 【node.master】是否为master
- 【node.data】是否为数据节点
- 【network.host】hostip
- 【http.port】http端口
- 【tcpsport.tcp.port】tcp监听端口
- 【http.cors.enabled: true/false】跨域配置
- 【http.cors.allow-origin:’*’】跨域配置
- 【discovery.seed_hosts:[“host1:port”]】加入的主节点ip和端口(内部端口)
- 【discovery.zen.fd.ping_timeout】连接超时时间
- 【discovery.zen.fd.ping_retries】重连次数
linux单机环境
es不允许root用户直接运行,所以要创建新用户。
# 新增用户
useradd es
# 设置密码
passwd es
#设置权限,设置文件夹所有者
chown -R es:es /path
配置文件修改内容
- elasticsearch.yml文件
- 【cluster.name】集群名称
- 【node.name】节点名称,不能重复
- 【network.host】hostip
- 【http.port】http端口
- 【cluster.initial_master_nodes:[“node-1”]】设置master节点
- limits.conf
- 【es soft nofile 65536】每个进程可以打开文件数量限制
- 【es hard nofile 65536】每个进程可以打开文件数量限制
- 20-nproc.conf
- 【es soft nofile 65536】每个进程可以打开文件数量限制
- 【es hard nofile 65536】每个进程可以打开文件数量限制
- sysctl.conf
- 【vm.max_map_count=655360】进程可以拥有的虚拟内存区域
sysctl -p
linux集群环境
配置文件修改
- elasticsearch.yml文件
- 【cluster.name】集群名称
- 【node.name】节点名称,不能重复
- 【node.master】是否为master
- 【node.data】是否为数据节点
- 【network.host】hostip
- 【http.port】http端口
- 【http.cors.enabled: true/false】跨域配置
- 【http.cors.allow-origin:’*’】跨域配置
- 【http.max_content_length】http请求体最大长度
- 【cluster.initial_master_nodes:[“node-1”]】设置master节点
- 【discovery.seed_hosts:[“host1:port”]】加入的主节点ip和端口(内部端口)
- 【gatway.recover_after_nodes:2】
- 数据备份时一致性参数
【consistency】一致性默认为大多数保存完即可;其他数值:1,只需要主分片执行完成;all,所有分片全部没问题。
【timeout】如选择all时,存在节点宕机,分片不会完成all的复制,设置timeout超时,超过规定时间可以终止。
- todo: P32
核心概念
索引:es中万物皆索引,一切都是为了提高搜索性能。
文档:一个可以被索引的基础信息单元,也就是一条数据。
字段:一条信息分有多个属性,属性也是字段。
映射:类似于表结构,如字段的类型,分片数量,备份数量等。
分片:一个索引可以分为多个分片,每个分片存储一定量的数据。创建索引时可以指定分片的数量。每一个分片也是一个功能完善独立的索引。可以提高容量和吞吐量。
副本:数据备份,副本分布在不同机器上达到高可用的目的
词条:索引中最小的存储和查询单元。
词典:字典,词条的集合。B+树,hashmap
倒排表:多个倒排项的合集。词条和文档Id列表的对应表
// 索引创建分配和副本配置
{
"setting" : {
"number_of_shards":3,
"number_of_replicas":1
}
}
写数据流程
- 客户端请求任意节点,称之为协调节点
- 协调节点经过hash计算,得出存放的分片,然后转发写入请求到主分片
- 目标分片接收到写入请求,写入到本地
- 将备份数据发送给备份分片
- 等待所有(根据配置不同)备份节点都保存完后返回协调节点
- 协调节点返回给客户端。
其中第3步写入本地磁盘的过程:
- 首先将数据写入内存中,此时新数据不可用,数据落盘后才能提供查询
- 将修改信息写入translog中
- 写入内存后每隔1秒refresh到缓冲区中(为解决只能落盘后才能查询效率低的问题,中间加入系统文件缓冲区)
- 清空内存中的segment,返回结果给客户端【数据写入到系统缓冲区之后可以提供查询,refresh的间隔是1s】
- translog每隔5s写入磁盘一次
- 每隔30min或者超出translog文件大小将触发commit操作。
commit操作会将内存中的数据refresh到系统缓存文件。然后创建一个commit point标记这段时间内产生的segement,生成新的translog文件。然后对标记了的segment进行合并,对标记删除的数据进行删除操作。
段合并:
为了避免过多segment,影响性能,会对段(segment)进行段合并,段合并的过程会造成大量的IO和性能消耗,会降低搜索性能。可以手动进行段合并(optimize)。
optimize命令建议不在运行环境中执行,导致无法搜索。
数据备份时一致性参数
【consistency】一致性默认为大多数保存完即可;其他数值:1,只需要主分片执行完成;all,所有分片全部没问题。
【timeout】如选择all时,存在节点宕机,分片不会完成all的复制,设置timeout超时,超过规定时间可以终止。
读取数据流程
docId搜索
- 请求发送给协调节点
- 协调节点通过hash算法根据docId找到对应的分片列表,此时使用随机轮询算法,在主分片和其余副本中随机选择转发查询请求,使得读取能够负载均衡。
- 目标节点收到请求,索引找到对应文档(数据),返回给协调节点。
- 协调节点返回给客户端。
全文搜索
- 请求发送给协调节点
- 协调节点先将搜索请求分发给所有的分片(主副都可)。
- 协调节点根据每个分片返回的数据【docId】进行合并,排序,分页等操作后,确定最后返回结果的docId,然后根据docId去对应的分片去拉取对应的文档【变为docId搜索】。
- 目标节点收到请求,索引找到对应文档(数据),返回给协调节点。
- 协调节点返回给客户端。
修改数据流程
- 请求发送给协调节点
- 协调节点通过hash算法找到对应的主分片所在节点,转发修改请求
- 目标节点收到请求,索引找到对应文档(数据),尝试修改数据,如果存在另外线程修改中,那么会进行自旋,直到修完成或者超过重复次数【retry_on_conflict】。
- 主分片修改完成后,将新版本数据转发到副本分片重新建立索引。
- 所有副本都返回成功,向协调节点返回,向客户端返回。
发送给副本分片的是新版本的文档数据,而不是更新请求。因为发送请求可能会以错误的顺序应用更改造成数据不一致。
多文档操作流程在单节点操作上加入了前期分解和最后返回的整合。
倒排索引
正向(排)索引 关系型数据库中,存储一条数据时,通过主键索引能够找到整条数据。是正向索引。 倒排索引 与正向索引相对,非关系型数据中存储一条数据时,将文本进行切割存储,文本内容当作索引,通过文本内容索引出对应的文档的docId。
倒排索引在写入到磁盘之后不能被修改。
不能被修改优点:
- 无需加锁,所有线程都只是查询,不能做修改操作
- 一旦读入到缓存中会长时间保存,因为其不会被修改,无需更新到磁盘中,直接请求缓存。
- 生命周期始终有效,不需要在每次数据改变时被重建。
- 大的倒排索引允许被压缩。
无法被修改的缺点:当需要更新的时候,只能删除之后再重建。
动态更新索引:解决删除之后再重建的问题
引入更多的索引,每次更新内容建立新的索引,查询时将所有的结果做合并后返回。每次更新的索引称为段,查询时将所有的段结果聚合后返回,遇到需要删除的情况,会存在一个.del文件列出被删除的段的信息。被标记删除的段(为被物理删除前)仍会被查询到,在聚合后进行过滤。最终在合适的时间进行真正删除。
近实时搜索
主要原因:内存与系统缓存间fresh时间是1s。
搜索时会查询系统缓存,但是部分数据仍然存在内存中,没有经过fresh,fresh的时间间隔是1s,所以1s内产生的数据,有可能查询不到,并非实时的搜索有这1s的误差,所以是近实时搜索。
文档分析
- 将文档切分成适合于倒排索引的词条
- 将词条进行标准格式化,利于搜索。
分析器
分析器的作用就是在创建索引的时候对文档进行拆解创建倒排索引;在查询的时候使用同样的分析器分析要搜索的内容,拆分成对应的词条。
- 字符过滤器:整理字符串。去除html,将符号转化成文字等。
- 分词器:整理好的字符串按照分词规则分为单个的词条。
- token过滤器:根据过滤规则改变词条,如大小写,去除无用词增加词条等。
内置分析器:
- 简单分析器:在任何不是字母的地方分割文本,将词条小写。
- 空格分析器:在空格的地方划分文本
- 语言分析器:特定语言的分析器,如英语无用词组的删除。
分词器
keyword:关键字不可以被分词
text:文本可以分词
【ik_max_word】:最细粒度拆分
【ik_smart】:最粗粒度的拆分
- IK分词器:默认分词器,会对中文每个字进行分词。
- IK中文分词器:按照中文的词组进行分词。使用方法【解压放到plugins目录下,重启es】,支持自定义词组
- 在ik文件夹下config目录下创建custom.dic文件,加入自定义词组
- 修改IKAnalyzer.cfg.xml将新建文件配置其中
- 重启es
文档冲突
如何保障文档一致性?
为解决文档访问冲突的问题,采用乐观锁的方式,使用版本号进行控制,保证读取和修改的数据都是最新数据,
对于旧版本的数据无法更新。
todo:_seq_no,_primary_term
使用version_type=external进行外部版本控制
管理工具
kibana,es-head
优化策略
硬件选择
所有文档数据存储在磁盘中。
- 使用SSD固态硬盘
- 使用RAID0,可以连续的存储空间分配到多个磁盘中,高效的利用每块磁盘,不需要备份,es已经提供了备份功能。
- 使用多块硬盘,配合RAID0
- 不使用远程挂载的存储。
分片策略
分片和副本是为了能够分布式扩容和故障转移,提高可用性。
分片数量不能动态修改,副本数量可以修改。
每个分片的底层都是lucene的索引,会消耗一定的文件句柄,内存以及CPU,如果多个分片处于同一个机器上就会竞争资源。用于计算相关度的词项统计是基于分片的,分片过多会造成每个分片分配的数据很少导致较低的相关度。
- 分片数不超过节点数的3倍。
- 节点数<=主分片数*(副本数+1)
分片瞬时宕机,集群会等待一分钟观察是否会重新加入,在此期间重新加入了,则不变,如果没有重新加入,会触发新的分片分配。自平衡分片分配会带来资源开销,修改【delayed_timeout】可以控制等待时间,防止短暂断开连接造成的分片重新分配。
路由查询
数据存放分片计算公式:
shard=hash(routing)%number_of_primary_shards
routing默认是文档id,也可以自定义。
不带路由查询:
- 分发:请求达到协调节点后,将查询请求分发到每个分片上
- 聚合:协调节点搜集每个分片上的查询结果,进行汇总返回
带路由查询:
直接根据路由信息转发到某个分片查询,不需要要查询所有分片。
写入速度优化
- 加大translog flush间隔,降低磁盘每秒的输入输出,和写锁的操作
- 增大index refresh间隔,减少segment merge的次数
- 调整bulk线程池和队列
- 优化节点间的任务分布
- 优化lucene层索引建立,降低cpu和IO
内存设置
ES默认的内存大小是1GB。
通过解压后的jvm.option文件来修改
- 【cluster.name】集群名称
- 【node.name】节点名称,不能重复
- 【node.master】是否为master
- 【node.data】是否为数据节点
- 【index.number_of_shards】分片数目,默认1
- 【index.number_of_replicas】副本数目,默认1
- 【transport.tcp.compress】节点间数据传输是否压缩,默认不压缩
- 【discovery.zen.minimum_master_nodes】选举master节点时需要的最少选举节点数。默认为1,网络不稳定时会出现脑裂(两个主节点),合理的数值为【候选节点数/2+1】
- 【dicovery.zen.ping.timeout】发现其他节点ping超时的时间。
常见面试题
为什么使用es?
主要解决关系型数据库全文索引的问题。关系型数据库使用like模糊查询,模糊查询会使得查询引擎放弃索引,使用全表扫描,在大数据量的情况下,效率低下。使用es全文索引能够解决模糊查询效率低的问题,提高查询速度。
master的选举流程?
- ZenDiscovery模块负责选举,主要包含ping和unicast两部分
- master节点的职责包括集群,节点,索引的管理,不负责文档级别的管理,data节点可以关闭http功能。
- 【选举出自己认为的master节点】所有可以成为master的节点按照nodeId排序,每次选举时,每个节点都把自己能够通过ping知道存在的节点进行排序,选出第一个节点,暂定为master,进行投票。可以选举自己。
- 【汇总选举结果】存在某个节点的投票数超过可以选举节点数量的一半【候选节点数/2+1;至少为2】,那么这个节点就是master。否则重新选举,直到满足选票条件。
集群启动时,第一个节点(A)启动,选取自己作为master节点,但是数量不够【候选节点数/2+1;至少为2】 第二个启动(B)后,首先寻找是否存在master节点, 发现没有后,通过ping进行寻找备选节点,找到第一个节点(A) 进行排序选择了第一个启动的节点,选举A为master A节点选举自己为master,如果集群只有三个节点的话此时选择master节点是A
脑裂问题?
- 脑裂【多个master】问题的成因
- 网络问题:网络延迟造成节点访问不到master,从而进行了选举产生了新的master
- 节点负载:主节点即为master又为data,访问量较大时造成es停止响应,其他节点收不到master的响应
- 内存回收:data节点上的es进程占用内存较大,引发大规模GC,造成es进程失去响应。
- 脑裂解决方案:
- 搜索分为两个阶段,称之为query then fetch
- 【query】初始查询节点,协调节点广播到索引中的主分片或副本分片,在每个分片执行搜索并构建一个优先队列,大小为from+size。【近实时搜索】
- 【query】每个分片返回各自的优先队列中所有文档的id和排序值给协调节点,协调节点进行合并,产生一个全局排序后的结果列表
- 【fetch】协调节点会判断哪些数据需要被取回,并向相关节点提交多个get请求
- 【fetch】所有节点全部返回,协调节点汇总后返回给客户端
优化方法?
- 机器64G内存最适合
- 多内核优于cpu
- 使用ssd固态硬盘
- 避免远程访问,外部挂载,避免跨越多个数据中心
- 保障jvm和服务器配置相同
- 通过【gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time】配置,避免重启时过多的分片交换
- 使用单播发现,避免节点无意中加入集群
- 避免修改垃圾回收器和线程池大小
- 内存分一半给lucene,通过【ES_HEAP_SIZE】配置
- 增大文件描述符的数量【es hard nofile 65536】
索引性能提升方法:
- 调整批量请求的大小
- 使用ssd
- 增加【index.translog.flush_threshold_size】默认512,设置为1G,可以在一次清空触发的时候在translog中累积更大的段,减少IO频率
- 对实时性不敏感可以修改【index.refresh_interval】改成30s,也能够减少磁盘IO频率
- 大批量导入时,可以关闭副本。
es的GC
- 倒排索引常驻内存,无法GC,需要监控内存增长趋势
- 合理分配各类缓存的空间,【field cache,filter cache,indexing cache,bulk cache】
- 避免大量返回结果搜索与聚合,如需要,采用scan&scroll api实现。
- 超大规模集群可以拆成多个集群通过tribe node连接
-
es如何实现大数据量的聚合?
HLL算法,HyperLoglog,一种基数统计算法,用来进行去重操作,类似redis中的hyperloglog,使用位数组和hash算法实现的去重。
并发情况下,如何保证读写一致?
乐观锁,版本号控制。
- 对于写操作,一致性级别【大多数、主、所有】设置成所有副本都同步完成后才支持访问,可以保证一致性
- 对于读操作,设置replication为sync,使操作在主分片和副本分片都完成后才返回;设置为async,通过请求参数_preference(偏好设置)为primary来查询,确保版本最新。
当write consistency不是all的时候,需要指定从primary shard读
当write consistency为all的时候,而且replication是sync模式(默认),无需额外指定,如果replication是async模式,则需要从primary shard读取。
_preference:偏好设置,偏好设置可以设置只查询主分片、副本分片、指定分片、优先主或副等,通常用于存在部分分片不可用时。
如何监控集群状态
字典树
字典树又叫单词查找树,trie树。哈希树的变种,用于统计、排序和保存大量的字符串(不仅限于字符串)。经常用于词频统计。
优点:利用字符串的公共前缀减少查询时间,最大限度的减少无谓的字符串比较,查询效率比哈希树高。
核心思想:用空间换时间。
- 根节点不包含字符,除根节点外,其他节点均包含一个字符
- 从根节点到某一结点,路径上的所有字符连起来,为该节点对应的字符串
- 每个节点的所有子节点包含的字符都不相同
中文字典树,每个节点的子节点用一个哈希表存储,减少空间浪费,速度能够保证哈希的O(1)。
es中集群、节点、索引、文档、类型是什么?
【见核心概念】
倒排索引是什么?
【见倒排索引】
todo
scan&scroll api:提高分页查询效率的方法
tribe node
replication async