节点(node)一个节点是一个逻辑上独立的服务,可以存储数据,并参与集群的索引和搜索功能,一个节点也有唯一的名字,集群通过节点名称进行管理和通信
索引(index)索引与关系型数据库实例(Database)相当,
文档类型(type)相当于数据库中的table概念
文档(Document)相当于数据库中的row
Mapping:相当于数据库中的schema,用来约束字段的类型,不过Elasticsearch的mapping可以自动根据数据创建
分片(shard) :是 工作单元(worker unit) 底层的一员,用来分配集群中的数据,它只负责保存索引中所有数据的一小片。
分片是一个独立的Lucene实例,并且它自身也是一个完整的搜索引擎。
文档存储并且被索引在分片中,但是我们的程序并不会直接与它们通信。取而代之,它们直接与索引进行通信的
把分片想象成一个数据的容器。数据被存储在分片中,然后分片又被分配在集群的节点上。当你的集群扩展或者缩小时,elasticsearch 会自动的在节点之间迁移分配分片,以便集群保持均衡
分片分为 主分片(primary shard) 以及 从分片(replica shard) 两种。在你的索引中,每一个文档都属于一个主分片
从分片只是主分片的一个副本,它用于提供数据的冗余副本,在硬件故障时提供数据保护,同时服务于搜索和检索这种只读请求
索引中的主分片的数量在索引创建后就固定下来了,但是从分片的数量可以随时改变。
一个索引默认设置了5个主分片,每个主分片有一个从分片对应
Cluster(集群)Cluster.name 集群名称,节点是一个运行着的Elasticsearch实例。集群是一组具有相同 Cluster.name的节点集合,他们那协同工作,共享数据并提供故障转移和扩展功能,
当然一个节点也可以组成一个集群。(你最好找一个合适的名字来替代cluster.name的默认值,比如你自己的名字,这样可以防止一个新启动的节点加入到相同网络中的另一个同名的集群中。
你可以通过修改config/目录下的elasticsearch.yml文件,然后重启ELasticsearch来做到这一点。当Elasticsearch在前台运行,可以使用Ctrl-C快捷键终止,或者你可以调用shutdown API来关闭:)
API
两个java客户端都通过9300端口与集群交互,使用Elasticsearch传输协议,集群中的节点之间也是通过9300端口通信。
查询 GET /department/employee/1
Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL)它允许你构建更加复杂,强大的查询
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
ES分布式集群
集群中一个节点会被选举为主节点(master)它将临时管理集群级别的一些变更,例如新建或者删除索引,增加或者一出节点等。主节点不参与文档级别的变更或索引
这意味着在流量增长的时候,该主节点不会成为集群的瓶颈。任何节点都可以成为主节点,作为用户,我们能够与集群中的任何节点通信,包括主节点,每一个节点都知道文档存在
于哪个节点上,他们可以转发请求到相应的节点上。我们访问的节点负责收集各节点返回的数据,最后一起返回给客户端。
node.master: 这个属性表示节点是否具有成为主节点的资格,此属性的值为true,并不是意味着这个节点就是主节点。因为真正的主节点,是由多个具有主节点资格的节点选举产生的
所以这个属性只是代表这个节点是不是具有主节点选举资格。
node.data:这个属性表示节点是否存储数据
node.master: true
node.data: true
node.ingest: true 最后这个,表示是否是(预处理服务器 前两个属性如果都是为 false的话,表示,这个节点 没有成为主节点的功能,同时没有存储数据的功能,单纯只有一个负载均衡的功能)
集群健康:
GET /_cluster/health
green 所有主要分片和复制都可以用
yellow 所有主要分片可用,但是不是所有的复制分片都可用
red 不是所有的主要分片都可用
每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档
应该如何被索引
自增ID的问题
put 方法(自己添加id) post方法(自动生成id)
创建一个新文档:
当索引一个文档,我们如何确定是完全创建了一个新的还是覆盖了一个已经存在了的?
首先,_index,_type,_id三者唯一确定一个文档。所以要想保证文档是新加入的,最简单的方式是使用post方法让Elasticsearch自动生成唯一id
另外:使用op_type关键字 put /website/blog/123?op_type=create{......}
使用url在后边追加 /_create作为端点
put /website/blog/123/_create{........}
如果请求成功的常见了一个文档,Elasticsearch将返回正常的元数据且响应状态码是201 Created
另一方面,如果包含相同的_index,_type,_id的文档已经存在,Elasticsearch将会返回409响应状态码
删除
删除文档的语法模式与之前基本一致,只不过要使用delete方法:
delete /webstite/blog/123
如果找到,将返回200 ok的状态码 同时将会返回删除的相应 信息,但是同时_version 版本号已经增加了
{
"found" : true,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 3
}
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除,ES将会在你之后添加更多索引 的时候才会在后台进行删除内容的清理。
版本控制和冲突:
1. put /website/blog/1?version=1 //这个请求表示:我们希望_version 版本是1 这个更新才会生效。成功ES将返回200 失败返回 409
2. 使用外部的版本号控制,比如说时间戳
多文档检索
POST /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
批量操作:bulk API允许我们使用单一请求来实现多个文档的,create,index,update,delete 这对索引类似于日志活动这样的数据流非常有用,他们可以以成百上千的数据为一个批次进行索引
bulk 请求体如下,
{action:{metadata}}\n
{request boody }\n
路由文档到分片:
当创建一个新的文档,它是怎么知道应该储存在哪个分片上的,
根据一个简单的算法,shard =hash(routing) % number_of_primary_shards
routing 值 是一个任意字符串,它默认是_id 但也可以自己定义,这个routing字符串通过哈希函数,生成一个数字,然后除以主切片的数量,得到一个余数
余数的范围永远是0到number_of_primary_shards-1,这个数字就是特定文档所在的额分片
这也解释了为什么主分片的数量只能在创建索引时定义且不能修改,如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档就找不到了
所有的文档API(get,index,delete,bulk,update,mget)都接收一个routing参数,它用来自定义文档到分片的映射,自定义路由值,可以确保所有相关文档
被保存到同一分片上。
默认,客户端接收到成功相应的时候,文档的修改已经被应用到主分片和所有的复制分片上了
replication(复制)
复制默认的值是sync,这将导致主分片得到复制分片的成功响应后才会返回。
如果你设置的replication为async,请求在主分片上被执行后就会返回给客户。它依旧会转发请求给复制节点,但你将不知道复制节点成功与否
(async)复制可能会因为在不等其他分片就绪的情况下发送过多的请求而使ES过载
consistency(一致性)
分页查询:和使用sql Limit关键字相同 ES接受from和size参数:
size:结果数,默认为10 from:跳过开始的结果数,默认是0
GET /_search?size=5&from=10
(应该当心分页太深或者一次请求太多的结果,结果在返回前会被排序,但是一个搜索请求常常设计多个分片,每个分片生成自己排好的结果
它们接着需要集中起来排序,以保证整体的排序正确)
集群中的深度分页:
为了理解什么是深度分页问题,让我们假设在一个有5个主分片的索引中搜索。当我们请求结果的第一页(结果1到10)时,,每个分片产生自己最顶端10个结果然后返回它们给请求
节点(requesting node)它再排序这所有的50个结果,以选出顶端的10个结果
假设现在我们请求第1000页——结果10001到10010,工作方式都相同,不同的是每个分片都必须产生顶端的10010个结果,然后请求节点排序这50050个结果,并丢弃500040个
你可以看到在分布式系统中农,排序结果的花费,随着分页的深入而成倍的增长,这也是为什么网络搜索引擎中,任何语句不能反悔多于1000个的原因
映射和分析:
映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型(string,number,booleans,date等)
分析(analysis)机制用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引
确切值和全文文本:
确切值是确定的,全文文本常常被称为“非结构化的数据”
倒排索引:ES使用一种叫做倒排索引(inverted index)的结构来做快速的全文搜索,倒排索引由在文档中出现的唯一的单词列表,以及对每一个单词在文档中的位置组成。