ElasticSearch定义

  1. index索引含义
    1. 一个索引index就像传统关系数据库的数据库,它是存储相关文档存储的地方
    2. 索引一个文档,表示把一个文档存储到索引中,以便他可以被检索或者查询
  2. shard分片
    1. 我们的文档存储在分片中,并且在分片中被索引

ElasticSearch安装和配置

ElasticSearch 安装

ElasticSearch基于JDK1.8,请先安装JDK
关于Linux如何安装JDK和配置
请参考Ubuntu下配置jdk

curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.3.tar.gz
tar -xvf elasticsearch-5.6.3.tar.gz
cd elasticsearch-5.6.3/bin
./elasticsearch #启动

ElasticSearch配置

由于虚拟机内存问题
需要将JVM虚拟机内存设置修改
./elasticsearch-5.6.3/config/jvm.options
修改
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
#从2g修改为1g
-Xms1g
-Xmx1g

常见问题

max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
max number of threads [1024] for user [lishang] likely too low, increase to at least [2048]
切换到root用户,编辑limits.conf 添加类似如下内容
vi /etc/security/limits.conf
添加如下内容:
* soft nofile 655360
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
--------------------------------------
或者以一下方法
sysctl -w vm.max_map_count=655360
并用以下命令查看是否修改成功
sysctl -a | grep "vm.max_map_count"
如果能正常输出655360,则说明修改成功,然后再次启动elasticsearch

环境配置

远程访问主机
需要在config目录下的elasticsearch.yml修改如下

network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

插件cerebro安装

插件cerebro的GitHub地址为GitHub https://github.com/lmenezes/cerebro/

wget https://github.com/lmenezes/cerebro/releases/download/v0.6.5/cerebro-0.6.5.tgz
tar zxvf cerebro-0.6.5.tgz
cd cerebro-0.6.5/
bin/cerebro
#可以直接通过外网端口访问 http://yourip:9000/

ElasticSearch搜索curl

新建索引

新建并设置主分片和复制分片

PUT tj
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}

修改mapping

POST tj/mail/_mapping
{
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
}
}
}

添加数据

GET tj/mail
{
"name":"dubo",
"age":23
}

轻量搜索

GET tj/mail/_search
GET tj/mail/_search?q=name:dubo

更新数据

全部更新会是直接把之前的老数据,标记为删除状态,然后,再添加一条更新的。
是局部更新不会覆盖其他数据
POST _index/_type/_id/_update
{
"doc":{
}
}

查询表达式搜索

GET /tj/mail/_search
{
"query" : {
"match" : {
"name" : "dubo"
}
}
}

范围搜索

#过滤器搜索
GET tj/mail/_search
{
"query": {
"bool": {
"filter": {
"range": {
"FIELD": {
"gte": 10,#大于等于 great than
"lte": 20 #小于等于 less than
}
}
}
}
}
}

复杂的搜索

GET tj/mail/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "dubo"
}
}
],
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
嵌套过滤器与bool
#搜索大于20岁,并且姓名为dubo或者爱好为book的
#bool查询中能继续嵌套bool
GET tj/mail/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"name": "dubo"
}
},
{
"match": {
"interests": "book"
}
}
]
}
}
],
"filter": {
"range": {
"age": {
"gt": 20
}
}
}
}
}
}

搜索相关性得分问题

Elasticsearch 默认按照相关性得分排序,即每个文档跟查询的匹配程度。
Elasticsearch中的 相关性 概念非常重要,也是完全区别于传统关系型数据库的一个概念,数据库中的一条记录要么匹配要么不匹配。

精确匹配

使用match_phrase精确匹配一系列单词或者短语.
切分是根据空格切分
如果没有切分,即使match也不会返回

GET tj/mail/_search
{
"query": {
"match_phrase": {
"name": "dubo"
}
}
}

高亮搜索

#em标签在html为红色斜体
GET tj/mail/_search
{
"query": {
"match": {
"name": "dubo"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}

分析聚合

Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 GROUP BY 类似但更强大。

在使用aggs会提示报错

Fielddata is disabled on text fields by default.
Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index.
Note that this can however use significant memory.
Alternatively use a keyword field instead.
默认情况下,Fielddata在文本字段上禁用。
在[name]中设置fielddata = true
以便通过反转反向索引来加载内存中的fielddata。
PUT my_index/_mapping/my_type
{
"properties": {
"my_field": {
"type": "text",
"fielddata": true
}
}
}
GET tj/mail/_search
{
"aggs": {
"NAME": {
"AGG_TYPE": {}
}
}
}
AGG_TYPE可以选择terms,avg,sum,value_count,range
#计算每种爱好的平均年龄
GET tj/mail/_search
{
"aggs": {
"all_interests": {
"terms": { "field": "interests" },
"aggs": {
"ages": {
"avg": {
"field": "age"
}
}
}
}
}
}

权重

过指定 boost 来控制任何查询语句的相对的权重

GET /_search
{
"query": {
"bool": {
"must": {
"match": {
"content": {
"query": "full text search",
"operator": "and"
}
}
},
"should": [
{ "match": {
"content": {
"query": "Elasticsearch",
"boost": 3
}
}},
{ "match": {
"content": {
"query": "Lucene",
"boost": 2
}
}}
]
}
}
}

dis_max

单个匹配最佳字段
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
]
}
}
}
{
"hits": [
{
"_id": "1",
"_score": 0.12713557, #两个评分一样
"_source": {
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
}
},
{
"_id": "2",
"_score": 0.12713557,
"_source": {
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
}
]
}
#我们可能期望同时匹配 title 和 body 字段的文档
#比只与一个字段匹配的文档的相关度更高,
#但事实并非如此,
#因为 dis_max 查询只会简单地使用 单个 最佳匹配语句
#的评分 _score 作为整体评分。
tie_breaker_参数
可以通过指定 tie_breaker 这个参数将其他匹配语句的评分也考虑其中:
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
],
"tie_breaker": 0.3
}
}
}

集群监控操作

集群健康

GET _cluster/health
{
"cluster_name": "PDVM01", #集群名称
"status": "yellow",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 4, # 指出你集群中的主分片数量。这是涵盖了所有索引的汇总值
"active_shards": 4, #是涵盖了所有索引的_所有_分片的汇总值,即包括副本分片
"relocating_shards": 0, #显示当前正在从一个节点迁往其他节点的分片的数量
"initializing_shards": 0,
"unassigned_shards": 4,
"delayed_unassigned_shards": 0, #推迟的未分配
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 50
}
GET _cluster/health?level=indices
#具体至每一个索引
{
"cluster_name": "PDVM01",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 4,
"active_shards": 4,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 4,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 50,
"indices": {
"tj": {
"status": "yellow",
"number_of_shards": 3,
"number_of_replicas": 1,
"active_primary_shards": 3,
"active_shards": 3,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 3
}
}
}

集群的部署

重要配置修改

#指定集群的名字和节点名字
cluster.name:
node.name:
#指定路径
#默认情况下, Elasticsearch 会把插件、日志以及你最重要的数据放在安装目录下。
#这会带来不幸的事故, 如果你重新安装 Elasticsearch 的时候不小心把安装目录覆盖了。如果你不小心,你就可能把你的全部数据删掉了。
path.data: /path/to/data1,/path/to/data2
# Path to log files:
path.logs: /path/to/logs
# Path to where plugins are installed:
path.plugins: /path/to/plugins

Elasticsearch之元数据

什么是meta-fields

在Elasticsearch下,一个文档除了有数据之外,它还包含了元数据(Metadata)。每创建一条数据时,都会对元数据进行写入等操作,当然有些元数据是在创建mapping的时候就会设置,
它里面定义了每个添加的doc的处理方式。 类似于数据库的表结构数据。

有哪些meta-fields

ES中元数据大体分为五中类型:身份元数据、索引元数据、文档元数据、路由元数据以及其他类型的元数据

  1. 身份元数据
    _index:文档所属索引 , 自动被索引,可被查询,聚合,排序使用,或者脚本里访问

    _type:文档所属类型,自动被索引,可被查询,聚合,排序使用,或者脚本里访问

    _id:文档的唯一标识

  2. 索引元数据
    _all: 自动组合所有的字段值,以空格分割,可以指定分器词索引,但是整个值不被存储,所以此字段仅仅能被搜索,不能获取到具体的值

    _field_names:索引了每个字段的名字,可以包含null值,可以通过exists查询或missing查询方法来校验特定的字段

    _timestamp:可以手工指定时间戳值,也可以自动生成使用now()函数,除此之外还可以设置日期的格式化,忽略确实等功能

    _ttl:对于一些会话数据或者验证码失效时间,一般来说是有生命周期的,在es中可以很方便的通过这个ttl来设置存活时间,比如1小时,或者10分钟,在超时过后,这个doc会被自动删除,这种方式并不适合按周或按天删除历史数据,如果是这种需求,可考虑使用索引级别的管理方式

  3. 文档元数据

    _source : 一个doc的原生的json数据,不会被索引,用于获取提取字段值 ,启动此字段,索引体积会变大,如果既想使用此字段,又想兼顾索引体积,可以开启索引压缩 ._source是可以被禁用的,不过禁用之后部分功能不再支持更新、高亮、重建索引、索引自动修复

数据可以保存到多个不同的目录, 如果将每个目录分别挂载不同的硬盘,这可是一个简单且高效实现一个软磁盘阵列( RAID 0 )的办法。Elasticsearch 会自动把条带化(注:RAID 0 又称为 Stripe(条带化),在磁盘阵列中,数据是以条带的方式贯穿在磁盘阵列所有硬盘中的) 数据分隔到不同的目录,以便提高性能。

集群重启

再关闭一个节点时候,Elasticsearch会立即试图复制这个节点的数据到集群中的其他节点上,这导致大量的IO操作。设置参数避免。

PUT /_cluster/settings
{
"transient":{cluster.routing.allocation.enable":"none"}
}

等待所有的主分片分配完成后,启动部分分片分配

PUT /_cluster/settings
{
"transient":{"cluster.routing.allocation.enable":"all"}
}

lucene 高亮问题

高亮的逻辑
第一个高亮词前面的片段就是从0到这个词的起始偏移位置,人社部的起止位置为:[26,29],也就是0~26,然后下一次循环的时候srcIndex会变为29,即从29开始再找高亮片段,然后第二个词”杜波”的起止偏移为:[13,16],src.substring(29,13)显然会导致异常,第一个高亮词前面的片段就是从0到这个词的起始偏移位置,阿森纳的起止位置为:[26,29],也就是0~26,然后下一次循环的时候srcIndex会变为29,即从29开始再找高亮片段,然后第二个词”杜波”的起止偏移为:[13,16],src.substring(29,13)显然会导致异常,

bootstrap.memory_lock:true

关闭swap缓冲区

#elasticsearch性能调优

  1. 评估集群初始大小信息包括:
    • 索引吞吐量
    • 文档数
    • 搜索吞吐量
    • 查询类型
    • 热索引文档数
    • 保留策略
    • 需要的响应时间
    • SLA 级别
  2. 显式设置mapping
    • Elasticsearch可以动态创建mapping,但这并不适用于所有场景。例如,在Elasticsearch5.x中默认string字段同时是”keyword”和”text”类型。这在很多场景下是不需要的。
  3. 如果文档是以用户自定义ID或者路由方式索引的请避免不平衡的分片。
    • Elasticsearch使用随机生成DI和hash算法以确保文档均匀的分配到各个分配。当你使用用户自定义ID或者路由,ID或者可能可能不够随机,这样某些索引可能会比其他索引大很多。在这种场景下,在大分片上进行读/写操作可能会比较慢。我们可以使用index.routing_partition_size 优化ID/路由key(5.3及以上版本)

Elasticsearch索引文档的过程

  • 协调节点默认使用文档ID参与计算(也支持通过routing),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
  • 当分片所在的节点接收到来自协调节点的请求后,会将请求写入到Memory Buffer,然后定时(默认是每隔1秒)写入到Filesystem Cache,这个从Momery Buffer到Filesystem Cache的过程就叫做refresh;
  • 当然在某些情况下,存在Momery Buffer和Filesystem Cache的数据可能会丢失,ES是通过translog的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到translog中,当Filesystem cache中的数据写入到磁盘中时,才会清除掉,这个过程叫做flush;
  • 在flush过程中,内存中的缓冲将被清除,内容被写入一个新段,段的fsync将创建一个新的提交点,并将内容刷新到磁盘,旧的translog将被删除并开始一个新的translog。
  • flush触发的时机是定时触发(默认30分钟)或者translog变得太大(默认为512M)时;

esindex

以上内容参考萌萌哥ElasticSearch集群部署文档
以上内容参考官方API www.elastic.co
未经授权请勿转载
Copyright © 2017 Mr.DuBo. All Rights Reserved