Elasticsearch原理解析与性能调优

类似于insert。例如索引一个文档到一个索引

倒排索引

默认每个属性都会有一个倒排索引,可以设置属性不被索引,它只能被覆盖,不能被修改

类型

类似表,同一索引的不同类型,可以拥有不同的字段,但应该拥有大部分相似的字段。它可以包含大小写,不能包含句号,不能以下划线开头,长度限制为256.

Id

文档的id,可以在生成文档时指定或自动生成,自动生成的ID,在大部分情况下多个节点的时候唯一。如果在创建文档时,ID冲突,服务器会返回409

文档

类似于记录,文档只能被替换,而不能被修改,文档的字段类型需要一致,否则无法进行精确匹配

精确值字段

对于数字,日期,布尔和一个not_analyzed字段,进行查询,会适用精确匹配

全文搜索字段

否则,进行相关性搜索

PUT /megacorp/employee/1
{
“first_name” : “John”,
“last_name” : “Smith”,
“age” : 25,
“about” : “I love to go rock climbing”,
“interests”: [ “sports”, “music” ]
}
例如

megacorp是索引
employee是类型
1是文档id
json内容是文档
交互
RESTful API
curl -X ‘😕/:/ ?<QUERY_STRING>’ -d ‘’
VERB 适当的 HTTP 方法 或 谓词 : GET、 POST、 PUT、 HEAD 或者 DELETE。
PROTOCOL http 或者 https(如果你在 Elasticsearch 前面有一个 https 代理)
HOST Elasticsearch 集群中任意节点的主机名,或者用 localhost 代表本地机器上的节点。
PORT 运行 Elasticsearch HTTP 服务的端口号,默认是 9200 。
PATH API 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。
QUERY_STRING 任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)
BODY 一个 JSON 格式的请求体 (如果请求需要的话)
例子
request:

curl -XGET ‘http://localhost:9200/_count?pretty’ -d ’
{
“query”: {
“match_all”: {}
}
}

response:

{
“count” : 0,
“_shards” : {
“total” : 5,
“successful” : 5,
“failed” : 0
}
}
检索文档功能
获取一个文档

GET /megacorp/employee/1
简单查询

GET /megacorp/employee/_search #查询前十条记录
GET /megacorp/employee/_search?q=last_name:Smith #查询smith的前十条记录
表达式查询

GET /megacorp/employee/_search
{
“query” : {
“match” : {
“last_name” : “Smith”
}
}
}
GET /megacorp/employee/_search
{
“query” : {
“bool”: {
“must”: {
“match” : {
“last_name” : “smith”
}
},
“filter”: {
“range” : {
“age” : { “gt” : 30 }
}
}
}
}
}
全文检索

GET /megacorp/employee/_search
{
“query” : {
“match” : {
“about” : “rock climbing”
}
}
}
短语查询

GET /megacorp/employee/_search
{
“query” : {
“match_phrase” : {
“about” : “rock climbing”
}
}
}
分析(类似于聚合group by)

request:

GET /megacorp/employee/_search
{
“aggs” : {
“all_interests” : {
“terms” : { “field” : “interests” },
“aggs” : {
“avg_age” : {
“avg” : { “field” : “age” }
}
}
}
}
}
response:


“all_interests”: {
“buckets”: [
{
“key”: “music”,
“doc_count”: 2,
“avg_age”: {
“value”: 28.5
}
},
{
“key”: “forestry”,
“doc_count”: 1,
“avg_age”: {
“value”: 35
}
},
{
“key”: “sports”,
“doc_count”: 1,
“avg_age”: {
“value”: 25
}
}
]
}
修改文档

PUT /website/blog/123
{
“title”: “My first blog entry”,
“text”: “I am starting to get the hang of this…”,
“date”: “2014/01/02”
}
旧文档不会马上删掉

新文档会被索引

文档的version会加一

删除文档

DELETE /megacorp/employee/123
文档的version依然会加一

分布式特性
ES自动执行的分布式动作
分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
将集群中任一节点的请求路由到存有相关数据的节点
集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复
水平扩展VS垂直扩展
ES对水平扩展是友好的,通过购置更多的机器,可以更好的使用ES的分布式功能

集群
集群拥有一个或多个节点,当有节点加入或者退出集群时,集群会重新平均分配所有数据的分布

主节点功能
增加/删除索引

增加/删除节点

不涉及文档的变更和搜索,因此单一的主节点不会成为集群的性能瓶颈

索引分片的元数据在每个ES节点都有存储,每个节点在接到请求后,都知道到哪台ES node找到数据,通过转发请求到ES node所在的机器

一个分片的最大文档数:(2^31-128)

一个索引的主分片数在建立时被确定,且无法修改:因为文档的存储是用shard = hash(routing) % number_of_primary_shards来确定文档的位置的。routing默认是id,也可以自定义

分片的副本数可以随时修改

建立索引
PUT /blogs
{
“settings” : {
“number_of_shards” : 3,
“number_of_replicas” : 1
}
}
ES-cluster

故障转移
增加一台机器到集群
ES-addonenode

删除节点
ES-delonenode

分布式写入冲突
ES-datalose
对于多个client的写入ES,有可能造成写入冲突,导致数据的丢失

在一些场景下,数据丢失是可以接受的

但是在某些场景下,是不允许的。

悲观控制并发
传统数据库的控制方式。通过对记录加锁,来实现并发的串行执行

乐观并发控制
ES采用乐观控制

所谓乐观控制,就是服务器假设大部分情况下,是不会发生冲突的,如果发生冲突,则拒绝修改,客户端可以需要通过重新获取并重试进行处理。

过程如下图

ES-versionConflict

分布式文档存储
确定文档位于那个shard
shard = hash(routing) % number_of_primary_shards
API支持带routing参数,来自定义路由,来确保相关文档路由到同一个分片

以ID新建,写入和删除文档
ES-writedocbyid

一致性保证
none: 主分片活跃,允许写入
all: 在所有分片活跃,允许写入
quorum: 半数以上节点活跃,允许写入
如果暂时没有足够的分片活跃,ES会等待,默认等待1分钟,可以通过参数timeout改变这个值,如果超时,则失败返回

新索引默认有 1 个副本分片,这意味着为满足 规定数量 应该 需要两个活动的分片副本。 但是,这些默认的设置会阻止我们在单一节点上做任何事情。为了避免这个问题,要求只有当 number_of_replicas 大于1的时候,规定数量才会执行。

以ID检索文档
与上图类似

以ID更新文档
与上图类似,但在更新完文档后,会重建索引

在局部更新文档的时候,主分片会以整份文档来同步给副本,来保证数据的完整性

通过条件获取多个文档
ES-mget

搜索
返回特殊字段
GET /_search
{
“hits” : {
“total” : 14,
“hits” : [
{
“_index”: “us”,
“_type”: “tweet”,
“_id”: “7”,
“_score”: 1,
“_source”: {
“date”: “2014-09-17”,
“name”: “John Smith”,
“tweet”: “The Query DSL is really powerful and flexible”,
“user_id”: 2
}
},
… 9 RESULTS REMOVED …
],
“max_score” : 1
},
“took” : 4,
“_shards” : {
“failed” : 0,
“successful” : 10,
“total” : 10
},
“timed_out” : false
}
took

执行的毫秒数

_shards

查询分片的状态,例如有几个分片是失败的,几个是成功的

timeout

可以通过在查询设定超时,如果查询超过时间,则只返回已经成功获得的数据,剩余的数据将丢弃

_index

数据来源的Lucene索引,文档的每一个字段,都拥有一个不同的Lucene索引

在查询中可以指定Lucene的索引,默认是不指定的,所以会查询该文档的所有索引,并汇总结果。如果指定,则会限定仅在指定的Lucene索引中查询数据

分页
GET /_search?size=5&from=5
此方式只适用于浅分页,如果查询过深,会导致严重的性能问题。

因为例如查询size为5,from=10000。那么ES会从各分片中都查询10005条记录,如果有100个shard,那么就会有10010005条记录,ES再对这10010005排序,并仅返回5条记录

深分页
使用游标scroll

它在ES中建立了一个有有效期的快照,提供给scroll进行数据的深度查询

倒排索引
对一下文档进行倒排:

The quick brown fox jumped over the lazy dog
Quick brown foxes leap over lazy dogs in summer
得到:

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跟quick,用户有可能认为它们是相同的,也有可能认为是不同的
dog和dogs非常接近,在相关性搜索时,它们应该都被搜索到
jump和leap是同义词,在相关性搜索时,它们应该都被搜索到
亚马逊测评 www.yisuping.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值