极力推荐: 官网地址: https://www.elastic.co/guide/en/elasticsearch/reference/6.0
肺腑之言,学ES先学原生的语法,SpringData封装的是太好用了,但是没玩过原生的语法,可能不知道Spring提供的API在干什么
核心概念:
Near Realtime (NRT)
在ES中进行搜索是近实时的,意思是数据从写入ES到可以被searchable仅仅需要1秒钟,因此说基于ES执行的搜索和分析可以达到秒级
Cluster
集群 , 集群是一个或多个node的集合,他们一起保存你存放进去的数据,用户可以在所有的node之间进行检索,一般的每个集群都会有一个唯一的名称标识,默认的名称标识为 elasticsearch
, 这个名字很重要,因为node想加入cluster时,需要这个名称信息
确保别在不同的环境中使用相同的集群名称,进而避免node加错集群的情况,一颗考虑下面的集群命名风格logging-stage
和logging-dev
和logging-pro
Node
单台server就是一个node,他和 cluster一样,也存在一个默认的名称,但是它的名称是通过UUID生成的随机串,当然用户也可以定制不同的名称,但是这个名字最好别重复,这个名称对于管理来说很在乎要,因为需要确定,当前网络中的哪台服务器,对应这个集群中的哪个节点
node存在一个默认的设置,默认的,当每一个node在启动时都会自动的去加入一个叫elasticsearch的节点,这就意味着,如果用户在网络中启动了多个node,他们会彼此发现,然后组成集群
在单个的cluster中,你可以拥有任意多的node,假如说你的网络上没有有其他正在运行的节点,然后你启动一个新的节点,这个新的节点自己会组件一个集群
Index
Index是一类拥有相似属性的document的集合,比如你可以为消费者的数据创建一个index,为产品创建一个index,为订单创建一个index
index名称(必须是小写的字符), 当需要对index中的文档执行索引,搜索,更新,删除,等操作时,都需要用到这个index
一个集群中理论上你可以创建任意数量的index
Type
Type可以作为index中的逻辑类别,为了更细的划分,比如用户数据type,评论数据type,博客数据type
在设计时,尽最大努力让拥有更多相同field的document会分为同一个type下
Document
document就是ES中存储的一条数据,就像mysql中的一行记录一样,可以是一条用户的记录,一个商品的记录等等
一个不严谨的小结:
为什么说这是不严谨的小结呢? 就是说下面三个对应关系只能说的从表面上看起来比较相似,但是ES中的type其实是一个逻辑上的划分,数据在存储是时候依然是混在一起存储的(往下看下文中有写,),然而mysql中的不同表的两个列是绝对没有关系的
Elasticsearch | 关系型数据库 |
---|---|
Document | 行 |
type | 表 |
index | 数据库 |
Shards & Replicas
问题引入:
如果让一个Index自己存储1TB的数据,响应的速度就会下降为了解决这个问题,ES提供了一种将用户的Index进行subdivide的骚操作,就是将index分片, 每一片都叫一个Shards,实现了将整体庞大的数据分布在不同的服务器上存储
什么是shard?
shard分成replica shard和primary shard,顾名思义一个是主shard一个是备份shard, 负责容错以及承担部分读请求
shard可以理解成是ES中最小的工作单元,所有shard中的数据之和,才是整个ES中存储的数据, 可以把shard理解成是一个luncene的实现,拥有完成的创建索引,处理请求的能力
下图是两个node,6个shard的组成的集群的划分情况
大家可以看到,这时无论 java应用程序访问的是node1还是node2,其实都能获取到数据shard的默认数量
新创建的节点会存在5个primary shard,后续不然能再改动primary shard的值,如果每一个primary shard都对应一个replica shard,按理说单台es启动就会存在10个分片,但是现实是,同一个节点的replica shard和primary shard不能存在于一个server中,因此单台es默认启动后的分片数量还是5个
如何拓容Cluster
首先明确一点: 一旦index创建完成了,primary shard的数量就不可能再发生变化
因此横向拓展就得添加replica的数量, 因为replica shard的数量后续是可以改动的, 也就是说,如果后续我们将他的数量改成了2, 就意味着让每个primary shard都拥有了两个replica shard, 计算一下: 5+5*2=15 集群就会拓展成15个节点
如果想让每一个shard都有最多的系统的资源,就增加服务器的数量,让每一个shard独占一个服务器,
举个例子:
上图中存在上下两个node,每一个node,每个node中都有一个 自己的primary shard和其他节点的replica shard,为什么是强调自己和其他呢? 因为ES中规定,同一个节点的replica shard和primary shard不能存在于一个server中,但是不同节点的primary shard可以存在于同一个server上
当primary shard宕机时,它对应的replicas在其他的server不会受到影响,可以继续响应用户的读请求,通过这种分片的机制,并且分片的地位相当,假设单个shard可以处理2000/s的请求,通过横向拓展可以在此基础上成倍提升系统的吞吐量,天生分布式,高可用
此外:每一个document肯定存在于一个primary shard和这个primary shard 对应的replica shard中, 绝对不会出现同一个document同时存在于多个primary shard中的情况
入门探索:
集群的健康状况
GET /_cat/health?v
执行结果如下:
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1572595632 16:07:12 elasticsearch yellow 1 1 5 5 0 0 5 0 - 50.0%
解读上面的信息,默认的集群名是elasticsearch
,当前集群的status是yellow
,后续列出来的是集群的分片信息,最后一个active_shards_percent
表示当前集群中仅有一半shard是可用的
状态
存在三种状态分别是red green yellow
- green : 表示当前集群所有的节点全部可用
- yellow: 表示所有的数据是可以访问的,但是并不是所有的replica shard都是可以使用的(我现在是默认启动一个node,而ES又不允许同一个node的primary shard和replica shard共存,因此我当前的node中仅仅存在5个primary shard,为status为黄色)
- red: 集群宕机,数据不可访问
集群的索引信息
GET /_cat/indices?v
结果:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open ai_answer_question cl_oJNRPRV-bdBBBLLL05g 5 1 203459 0 172.3mb 172.3mb
显示,状态yellow表示存在replica shard不可用, 存在5个primary shard,并且每一个primary shard都有一个replica shard , 一共20多万条文档,未删除过文档,文档占用的空间情况为172.3兆
创建index
PUT /customer?pretty
ES 使用的RestfulAPI,新增使用put,这是个很亲民的举动
添加 or 修改
如果是ES中没有过下面的数据则添加进去,如果存在了id=1的元素就修改(全量替换)
- 格式:
PUT /index/type/id
全量替换时,原来的document是没有被删除的,而是被标记为deleted,被标记成的deleted是不会被检索出来的,当ES中数据越来越多时,才会删除它
PUT /customer/_doc/1?pretty
{
"name": "John Doe"
}
响应:
{
"_index": "customer",
"_type": "_doc",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
强制创建,加添_create
或者?op_type=create
PUT /customer/_doc/1?op_type=create
PUT /customer/_doc/1/_create
- 局部更新(Partial Update)
不指定id则新增document
POST /customer/_doc?pretty
{
"name": "Jane Doe"
}
指定id则进行doc的局部更新操作
POST /customer/_doc/1?pretty
{
"name": "Jane Doe"
}
并且POST相对于上面的PUT而言,不论是否存在相同内容的doc,只要不指定id,都会使用一个随机的串当成id,完成doc的插入
Partial Update先获取document,再将传递过来的field更新进document的json中,将老的doc标记为deleted,再将创建document,相对于全量替换中间会省去两次网络请求
检索
格式: GET /index/type/
GET /customer/_doc/1?pretty
响应:
{
"_index": "customer",
"_type": "_doc",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"name": "John Doe"
}
}
删除
删除一条document
大部分情况下,原来的document不会被立即删除,而是被标记为deleted,被标记成的deleted是不会被检索出来的,当ES中数据越来越多时,才会删除它
DELETE /customer/_doc/1
响应:
{
"_index": "customer",
"_type": "_doc",
"_id": "1",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
删除index
DELETE /index1
DELETE /index1,index2
DELETE /index*
DELETE /_all
可以在elasticsearch.yml中将下面这个设置置为ture,表示禁止使用 DELETE /_all
action.destructive_required_name:true
响应
{
"acknowledged": true
}
更新文档
上面说了POST关键字,可以实现不指定id就完成document的插入, POST
+ _update
关键字可以实现更新的操作</