ElasticSearch 入门

REST

  • Representational State Transfer

一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

image-20200308220744690

核心算法

正排索引

ES核心算法是倒排索引,可以先简单谈谈正排索引。

例如

url1 的内容是林俊杰2019演唱会行程 分词后林俊杰/2019/演唱会/行程

url2 内容是 林俊杰吴亦凡终于同框合影,粉丝们尖叫连连分词后 林俊杰/吴亦凡/终于/同框/合影 /惹/粉丝们/尖叫/连连

建立索引

url        	|      keywords
--------------------------------------
url1        |      林俊杰,2019,演唱会,行程
url2        |      林俊杰,吴亦凡,终于,同框,合影 ,粉丝们,尖叫,连连

有点类似 Mysql 索引是 id 对于具体的 row

优点

建立索引非常快,只需要将新增的索引往后追加就可以了。

缺点

搜索关键字非常困难,因为它必须查看索引的每个内容才能检索与单词相关的所有页面。

使用场景

  • 书中的目录
  • DNS查询

倒排索引

keywords   |      url
--------------------------------------
林俊杰      |      url1,url2
2019       |      url1
演唱会      |      url1
行程        |      url1
吴亦凡      |      url2
终于        |      url2

缺点

建立索引时比较慢,每次新增的时候需要判断是否存在,然后往里面追加

优点

关键字搜索很快

使用场景

  • 书后面的关键字索引
  • 搜索引擎

核心概念

cluster

代表一个集群,集群中有多个节点

  • 只需要在同一个网段之内启动多个es节点,就可以自动组成一个集群。

  • 默认情况下es会自动发现同一网段内的节点,自动组成集群。

  • 集群状态查看 http://192.168.57.4:9200/_cluster/health?pretty

主节点

这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。

主节点的职责是负责管理集群状态,包括管理分片的状态和副本的状态,以及节点的发现和删除。

Shard

代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。

可以在创建索引库时指定

curl -XPUT 'localhost:9200/index/' -d'{"settings":{"number_of_shards":3}}'

Replicate

代表索引副本,es可以给索引设置副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高es的查询效率,es会自动对搜索请求进行负载均衡。

可以在创建索引库的时候指定,默认 1(集R群中总共有2个索引)

curl -XPUT 'localhost:9200/test2/' -d'{"settings":{"number_of_replicas":2}}'

Recovery

代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配,挂掉的节点重新启动时也会进行数据恢复。

Gateway

代表es索引的持久化存储方式,es默认是先把索引存放到内存中,当内存满了时再持久化到硬盘。当这个es集群关闭再重新启动时就会从gateway中读取索引数据。es支持多种类型的gateway,有本地文件系统(默认),分布式文件系统,Hadoop的HDFS和amazon的s3云存储服务。可以配置多个目录

–如果需要将数据落地到hadoop的hdfs需要先安装插件 elasticsearch-hadoop,然后再elasticsearch.yml配置

gateway:
   type: hdfs
gateway:
       hdfs:
          uri: hdfs://localhost:9000

discovery.zen

代表es的自动发现节点机制,es是一个基于p2p的系统,它先通过广播寻找存在的节点,再通过多播协议来进行节点之间的通信,同时也支持点对点的交互。

如果是不同网段的节点如何组成es集群

#禁用自动发现机制
discovery.zen.ping.multicast.enabled: false

#设置新节点被启动时能够发现的主节点列表
discovery.zen.ping.unicast.hosts: [“192.168.27.4", " 192.168.17.5"]

Transport

代表es内部节点或集群与客户端的交互方式,默认内部是使用TCP协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。

Settings和Mappings

Settings

修改索引库默认配置,例如:分片数量,副本数量

查看:curl -XGET http://localhost:9200/index/_settings?pretty

设置:

curl -XPUT 'localhost:9200/index/' -d'{"settings":{"number_of_shards":3,"number_of_replicas":2}}'

Mapping

对索引库中索引的字段名称及其数据类型进行定义,类似于关系数据库中表建立时要定义字段名及其数据类型那样,(和solr中的schme类似)不过es的mapping比数据库灵活很多,它可以动态添加字段。一般不需要要指定mapping都可以,因为es会自动根据数据格式定义它的类型,如果你需要对某些字段添加特殊属性(如:定义使用其它分词器、是否分词、是否存储等),就必须手动添加mapping

•查询索引库的mapping信息 curl -XGET http://localhost:9200/index/emp/_mapping?pretty

mappings修改字段相关属性,例如:字段类型,使用哪种分词工具

装机配置


cluster.name: es_cluster

node.name: node06 

network.host: 192.168.133.6 

http.port:9200 

# 末尾增加防脑裂:
discovery.zen.ping.multicast.enabled: false 
discovery.zen.ping.unicast.hosts: ["192.168.133.6","192.168.133.7", "192.168.133.8"]
discovery.zen.ping_timeout: 120s
client.transport.ping_timeout: 60s

API

image-20200308220828125

Java API

使用反射获取Elasticsearch客户端,可以使用通过new获取client

使用反射方式:网上反映这种方式效率明显高于new客户端,并可避免线上环境内存溢出和超时等问题

TransportClient client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("host1", 9300)).addTransportAddress(new InetSocketTransportAddress("host2", 9300));
// 如果需要使用其他名称的集群(默认是elasticsearch),需要如下设置
Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", "myClusterName").build();
TransportClientclient = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress("host1", 9300));


// 索引index(四种json,map,bean,es helpers)
IndexResponse response = client.prepareIndex(“index", "type", "1").setSource().execute().actionGet();
// 查询get
GetResponse response = client.prepareGet(“index", "type", "1").execute().actionGet();
// 更新update
//更新或者插入upsert
// 删除delete
DeleteResponse response = client.prepareDelete(“index", "type", "1").execute().actionGet();
// 总数count
long count = client.prepareCount(“index").execute().get().getCount();

查询:query
.setQuery(QueryBuilders.matchQuery("name", "test"))
分页:from/size
.setFrom(0).setSize(1)
排序:sort
.addSort("age", SortOrder.DESC)
过滤:filter
.setPostFilter(FilterBuilders.rangeFilter("age").from(1).to(19))
高亮:highlight

统计:facet(已废弃)使用aggregations 替代
根据字段进行分组统计
根据字段分组,统计其他字段的值
size设置为0,会获取所有数据,否则,只会返回10条

ES分页

与SQL使用LIMIT来控制单“页”数量类似,Elasticsearch使用的是from以及size两个参数:

  • size:每次返回多少个结果,默认值为10

  • from:从哪条结果开始,默认值为0

假设每页显示5条结果,那么1至3页的请求就是:

- GET /_search?size=5
- GET /_search?size=5&from=5
- GET /_search?size=5&from=10

注意:不要一次请求过多或者页码过大的结果,这么会对服务器造成很大的压力。因为它们会在返回前排序。一个请求会经过多个分片。每个分片都会生成自己的排序结果。然后再进行集中整理,以确保最终结果的正确性。

timed_out告诉了我们查询是否超时
curl -XGET http://localhost:9200/_search?timeout=10ms
es会在10ms之内返回查询内容
注意:timeout并不会终止查询,它只是会在你指定的时间内返回当时已经查询到的数据,然后关闭连接。在后台,其他的查询可能会依旧继续,尽管查询结果已经被返回了。

批量操作bulk

image-20200308222921805

ES的搜索类型有4种

  • query and fetch(速度最快)(返回N倍数据量)

  • query then fetch(默认的搜索方式)

  • DFS query and fetch(可以更精确控制搜索打分和排名。)

  • DFS query then fetch

•DFS解释:见备注

•总结一下,从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。

分片查询

默认是randomize across shards
随机选取,表示随机的从分片中取数据
_local:指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。
_primary:指查询只在主分片中查询
_primary_first:指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。
_only_node:指在指定id的节点里面进行查询,如果该节点只有查询索引的部分分片,就只在这部分分片中查找,所以查询结果可能不完整。如_only_node:123在节点id为123的节点中查询。
_prefer_node:nodeid 优先在指定的节点上执行查询
_shards:0 ,1,2,3,4:查询指定分片的数据
自定义:_only_nodes:根据多个节点进行查询

优化

操作系统

  • 调大系统的"最大打开文件数",建议32K甚至是64K
–ulimit -a (查看)
–ulimit -n 32000(设置)

内存

修改配置文件调整ES的JVM内存大小

1:修改bin/elasticsearch.in.sh中ES_MIN_MEM和ES_MAX_MEM的大小,建议设置一样大,避免频繁的分配内存,根据服务器内存大小,一般分配60%左右(默认256M)

2:如果使用searchwrapper插件启动es的话则修改bin/service/elasticsearch.conf(默认1024M)

内存地址

设置mlockall来锁定进程的物理内存地址

避免交换(swapped)来提高性能,修改文件conf/elasticsearch.yml

boostrap.mlockall: true

分片

分片可以提升建立索引的能力,5-20个比较合适。如果分片数过少或过多,都会导致检索比较慢。分片数过多会导致检索时打开比较多的文件,另外也会导致多台服务器之间通讯。而分片数过少会导至单个分片索引过大,所以检索速度慢。建议单个分片最多存储20G左右的索引数据,所以,分片数量=数据总量/20G。

elasticsearch在建立索引时,根据id或id,类型进行hash,得到hash值与该索引的文档数量取余,取余的值即为存入的分片。

–具体源码为:根据OperationRouting类的shardId方法进行分片

副本

副本多,可以提升搜索的能力,但是如果设置很多副本的话也会对服务器造成额外的压力,因为需要同步数据。所以建议设置2-3个即可。

Index

要定时对索引进行优化,不然segment越多,查询的性能就越差,索引量不是很大的话情况下可以将segment设置为1

–curl -XPOST 'http://localhost:9200/index/_optimize?max_num_segments=1'

client.admin().indices().prepareOptimize(“index").setMaxNumSegments(1).get();

Mapping-all

去掉mapping中_all域,Index中默认会有_all的域,(相当于solr配置文件中的拷贝字段text),这个会给查询带来方便,但是会增加索引时间和索引尺寸

"_all":{"enabled":"false"}

Log

log输出的水平默认为trace,即查询超过500ms即为慢查询,就要打印日志,造成cpu和mem,io负载很高。把log输出水平改为info,可以减轻服务器的压力。

–修改ES_HOME/conf/logging.yaml文件

–或者修改ES_HOME/conf/elasticsearch.yaml

其他

  • 删除文档

在Lucene中删除文档,数据不会马上在硬盘上除去,而是在lucene索引中产生一个.del的文件,而在检索过程中这部分数据也会参与检索,lucene在检索过程会判断是否删除了,如果删除了在过滤掉。这样也会降低检索效率。所以可以执行清除删除文档

curl -XPOST 'http://localhost:9200/elasticsearch/_optimize?only_expunge_deletes=true'

client.admin().indices().prepareOptimize("elasticsearch ").setOnlyExpungeDeletes(true).get();
  • 首次导入数据

如果在项目开始的时候需要批量入库大量数据的话,建议将副本数设置为0。因为es在索引数据的时候,如果有副本存在,数据也会马上同步到副本中,这样会对es增加压力。待索引完成后将副本按需要改回来。这样可以提高索引效率

脑裂

所谓脑裂问题(类似于精神分裂),就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。

正常情况下,集群中的所有的节点,应该对集群中master的选择是一致的,这样获得的状态信息也应该是一致的,不一致的状态信息,说明不同的节点对master节点的选择出现了异常——也就是所谓的脑裂问题。这样的脑裂状态直接让节点失去了集群的正确状态,导致集群不能正常工作。

#用于控制选举行为发生的最小集群节点数量。推荐设为大于1的数值,因为只有在2个以上节点的集群中,主节点才是有意义的
discovery.zen.minimum_master_nodes

原因

  • 网络:由于是内网通信,网络通信问题造成某些节点认为master死掉,而另选master。可能性较小

  • 节点负载:由于master节点与data节点都是混合在一起的,所以当工作节点的负载较大时,导致对应的ES实例停止响应,而这台服务器如果正充当着master节点的身份,那么一部分节点就会认为这个master节点失效了,故重新选举新的节点,这时就出现了脑裂;同时由于data节点上ES进程占用的内存较大,较大规模的内存回收操作也能造成ES进程失去响应。

解决

# 主节点
node.master: true  
node.data: false  
# 从节点
node.master: false  
node.data: true  
# 所有节点
discovery.zen.ping.multicast.enabled: false  
discovery.zen.ping.unicast.hosts: [“master”, “slave1”, “slave2"]  

插件

中文分词 ik

安装

https://github.com/medcl/elasticsearch-analysis-ik

编译后放入es 节点的plugins 目录

分别执行如下命令:
mvn clean
mvn compile
mvn package
当然这里是用maven对此工程进行编译,前提要安装maven
Maven安装也很简单,下载包以后解压缩,配置环境变量即可,如图:

使用分词

设置
curl -XPOST http://localhost:9200/index/fulltext/_mapping -d'
{
    "fulltext": {
        "properties": {
            "content": {
                "type": "string",
                "store": "no",
                "term_vector": "with_positions_offsets",
                "analyzer": "ik_max_word",
                "search_analyzer": "ik_max_word",
                "include_in_all": "true",
                "boost": 8
            }
        }
    }
}'
建立索引
curl -XPOST http://localhost:9200/index/fulltext/1 -d'
{"content":"美国留给伊拉克的是个烂摊子吗"}
'
curl -XPOST http://localhost:9200/index/fulltext/2 -d'
{"content":"公安部:各地校车将享最高路权"}
'
curl -XPOST http://localhost:9200/index/fulltext/3 -d'
{"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"}
'
curl -XPOST http://localhost:9200/index/fulltext/4 -d'
{"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"}
'
搜索
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
    "query" : { "term" : { "content" : "中国" }},
    "highlight" : {
        "pre_tags" : ["<tag1>", "<tag2>"],
        "post_tags" : ["</tag1>", "</tag2>"],
        "fields" : {
            "content" : {}
        }
    }
}
'
结果
{
    "took": 14,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 2,
        "hits": [
            {
                "_index": "index",
                "_type": "fulltext",
                "_id": "4",
                "_score": 2,
                "_source": {
                    "content": "中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
                },
                "highlight": {
                    "content": [
                        "<tag1>中国</tag1>驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首 "
                    ]
                }
            },
            {
                "_index": "index",
                "_type": "fulltext",
                "_id": "3",
                "_score": 2,
                "_source": {
                    "content": "中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"
                },
                "highlight": {
                    "content": [
                        "均每天扣1艘<tag1>中国</tag1>渔船 "
                    ]
                }
            }
        ]
    }
}

不用在es 中安装插件
https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm/related

posted on 2020-03-08 22:59  chouc  阅读(406)  评论(0编辑  收藏  举报

导航