目 录CONTENT

文章目录

数工总结 | ElasticSearch 知识点

Wissy
2021-08-05 / 0 评论 / 2 点赞 / 52 阅读 / 0 字

一、介绍

越来越多的公司使用ELK技术栈做为日志分析平台,ELK是三个工具的简称,即Logstash+ElasticSearch+Kibana,
其中以ElasticSearch(es)为核心(存储数据和查询数据),Logstash收集数据,Kibana进行数据展示,具体流程就是使用Logstash将日志做简单的分析后收集到ElasticSearch中,最后使用Kibana根据不同的业务进行展示(预警)。

ElasticSearch底层使用lucene进行索引,到目前为止ElasticSearch共有3个大版本
ElasticSearch1.x 最初的版本
ElasticSearch2.x
ElasticSearch5.x 提高了性能,并且将elastic所有版本都统一
ElasticSearch6.x

ElasticSearch 是基于 Apache Lucene™ 开发的开源的全文搜索引擎库,2021 年 1 月 15 开始,自 Elastic 7.11 版本开始,Elasticsearch 与 Kibana 代码所遵循的 Apache 2.0 许可会调整为 SSPL 与 Elastic License 双许可。SSPL 是由 MongoDB 制定的源代码许可,目的在于限制云供应商修改 Elasticsearch 源码发布自己的服务版本,而不贡献于社区。查看详细解说

SSPL 允许用户以自由且不受限制的方式使用并修改代码成果,唯一的要求是:如果将产品以作为一种服务进行交付,那么必须同时公开发布所有关于修改及 SSPL 之下管理层的源代码。

使用注意

  1. 使用 Spark 和 Flink 在写 ElasticSearch 的时候,写入的总分区应该 <= ElasticSearch 数据节点 * 3(最大),并且应该优化 ElasticSearch Index 存储和刷新类型。目前写入总上限为 10w/s(去掉副本&不刷新),5w/s(有副本和刷新)。

  2. index.mapping.total_fields.limit​ 默认是系统设置 1000 个字段,如果是宽表索引应该增加该参数。

  3. ​index.refresh_interval​ 刷新时间间隔,-1 代表不刷新,刷新指写入的数据可以查询到。

  4. 一定不能使用 swap。

二、本地安装

安装依赖程序

安装JDK
es5+需要jdk8的版本

  • 下载JDK

wget http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz?AuthParam=1499007315_3290c5ba69a1db872cf77e9abbd5018e
cd /usr/share && tar xavf jdk-8u131-linux-x64.tar.gz
  • 配置环境变量

sudo vim /etc/profile
#加入以下代码
export JAVA_HOME=/usr/share/jdk1.8.0_131
export PATH=$JAVA_HOME/bin:$PATH 
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 

下载

  • 下载elasticSearch-5.4

curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.1.tar.gz
  • 下载elasticSearch其他格式或其他版本<br>​ElasticSearch

解压并快速启动

tar xzvf elasticsearch-5.4.1.tar.gz

#创建一个普通用户
user add elastic

sudo passwd elastic #盲打密码

su elastic

chown -R elastic:elastic ./elasticsearch-5.4.1

cd elasticsearch-5.4.1

bin/elasticsearch #按Ctrl+C结束

#浏览器数据,显示json数据
http://127.0.0.1:9200

安装head插件(ElasticSearch可视化)

Haed

  • ES 2.0sudo elasticsearch/bin/plugin install mobz/elasticsearch-head​

  • ES 1.0sudo elasticsearch/bin/plugin -install mobz/elasticsearch-head/1.x​

  • ES 0.xsudo elasticsearch/bin/plugin -install mobz/elasticsearch-head/0.9​
    open http://localhost:9200/_plugin/head/

  • ES 5.x

git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
open http://localhost:9100/

三、集群安装

下载

  • 下载elasticSearch-5.4

curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.1.tar.gz
  • 下载elasticSearch其他格式或其他版本 <br>​ElasticSearch

修改配置文件

由于作者没有多余的机器进行集群安装(不喜欢虚拟机里面操作),所以通过修改端口的形式来安装启动多个ES

  • ES有两个端口,一个是9200(rest端口),另一个是9300(内部通讯端口)

  • node1==>9200,9300(数据节点)

  • node2==>9400,9500(数据节点)

  • node3==>9600,9700(辅助选举节点,不存储索引数据)

  • ​vim config/elasticsearch.yml​

  • 通用配置

# 集群名称 一个网段的多个ES通过集群名称来识别,默认是elasticsearch
cluster.name: my-application
#节点名称 同一集群的节点名称不重复
node.name: node-1
#节点所在机架 可以不配置
#node.attr.rack: r1
#数据存储路径
path.data: /opt/soft/elasticsearch-5.4.0-9200/data
#日志存储路径 默认在安装路径/logs
#path.logs: /path/to/logs
#IP地址 广播地址 绑定端口地址
network.host: 127.0.0.1
#rest端口 一台机器上面唯一
http.port: 9200
#通讯端口
transport.tcp.port: 9300
#初始化节点信息 使用通讯端口,默认是9300
#discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300",  "127.0.0.1:9500","127.0.0.1:9700"]
# 最小选举节点数(存在选举节点无需配置)
#discovery.zen.minimum_master_nodes: 2

#指定该节点是否被选举为Master,默认是true
node.master: true
#指定该节点是否存储索引数据
node.data: true
  • node1

cluster.name: my-application
node.name: node-1
path.data: /opt/soft/elasticsearch-5.4.0-9200/data
network.host: 127.0.0.1
http.port: 9200
transport.tcp.port: 9300
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9500","127.0.0.1:9700"]
node.master: true
node.data: true

  • node2

cluster.name: my-application
node.name: node-2
path.data: /opt/soft/elasticsearch-5.4.0-9400/data
network.host: 127.0.0.1
http.port: 9400
transport.tcp.port: 9500
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9500","127.0.0.1:9700"]
node.master: true
node.data: true
  • node3

cluster.name: my-application
node.name: node-3
path.data: /opt/soft/elasticsearch-5.4.0-9600/data
network.host: 127.0.0.1
http.port: 9600
transport.tcp.port: 9700
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9500","127.0.0.1:9700"]
node.master: true
node.data: false

四、Docker安装

Docker 环境准备

首先安装Docker 一般Linux发行版本中都支持Docker

# centos
yum install docker
#debian
apt-get install docker
#arch
pac-man install docker

将自己添加到Docker用户组中

#user1 为要添加的用户名 docker为Docker用户组 a为append G为group
sudo usermod -aG docker user1

启动Docker

#新版本服务启动(centos7)
systemctl start docker
#旧版本服务启动(centos6)
service docker start

Docker 基本命令

# 查看Docker进程
docker ps
#查看所有的镜像文件
docker images
# 将远程的Docker镜像pull到本地(比较漫长,视时间和地区大小而定)
docker pull imgName
#前台运行一个容器
docker run -it imgName
#后台运行一个容器
docker run -d imgName
#停止一个容器
docker stop name|uuid

运行Docker-ES local

#获取镜像文件(存在则不会重复获取)
docker pull elasticsearch
#后台运行容器 容器名:elas-local 映射容器端口9200到宿主机9200端口上
docker run -d --name elas-local -p 9200:9200 elasticsearch
#停止容器
docker stop elas-local

运行Docker-ES cluster

#获取镜像文件(存在则不会重复获取)
docker pull elasticsearch
#启动集群模式(使用环境变量传入配置,默认集群名称为:elasticsearch)
docker run -d --name elas-node1 -p 9200:9200 elasticsearch  -Etransport.host=127.0.0.1 -Ediscovery.zen.minimum_master_nodes=1 
docker run -d --name elas-node2 -p 9400:9200 elasticsearch  -Etransport.host=127.0.0.1 -Ediscovery.zen.minimum_master_nodes=1 
docker run -d --name elas-node3 -p 9600:9200 elasticsearch  -Etransport.host=127.0.0.1 -Ediscovery.zen.minimum_master_nodes=1

#使用配置文件启动
docker run -d -v "$PWD/config":/usr/share/elasticsearch/config elasticsearch
#讲数据文件另存
docker run -d -v "$PWD/esdata":/usr/share/elasticsearch/data elasticsearch

五、实现like搜索(模糊匹配)

六、QA

Q:我的集群最大可以有多少分片?

A:分片的数量和可用堆内存大小成正比,1GB 堆内存在 20-25 个。

Q:index.number_of_shards​ 设置多少合适?

A:分片的数据应该结合数据大小,需要考虑导未来新增的数据容量,默认是 5,太大和太小都会影响查询性能。每个查询在每个分片中是单线程查询的,并且小分片不利于高速缓存。按照经验设置 30G-50GB 一个分片。

Q:index.store.type​ 该如何选择?

A:官方文档,如果你的运行环境不是 Windows 并且追求高效率应该使用 niofs,niofs 因为 sun 在 Windows 中实现有错误。mmapfs 会消耗虚拟地址空间,在内存紧张的情况下容易写挂 ElasticSearch,性能不如 niofs。

Q:index.translog​ 是什么?

A:官方文档,translog 是 ElasticSearch 的事务日志,用于重启断电后的恢复。translog 越短恢复越快,flush 一次表示从内存中刷新导磁盘上。index.translog.durability​ 表示 translog 到磁盘刷新的类型 async 和 request。async 更快但是有数据丢失的分险,必须确定你容忍丢失 index.translog.sync_interval​ 的数据。否则应该设置 request。

Q:查询的数量 total=1000,如何显示全部文档?

A:7.x 加上 "track_total_hits": 2147483647​ 参数,6.x 加上 "adjust_pure_negative": true​ 参数。

Q:ElasticSearch 内部的文档是只读的,如何实现删除和更新?

A:更新操作其实是根据以前的文档和现在的操作生成一个新的文档,使用乐观锁(_sep_no​ 、_version​)去控制。删除标注其实也是更新操作,查询时如果遇到删除的文档则跳过,在段(segment)合并的时候才会真正删除该文档。

Q:keyword 类型有什么作用?

A:ElasticSearch 字段是支持多类型,默认 string 类型有 text 和 keyword。text 适合存储大的文本,并且可以结合分词器对其相关度打分。keyword 一般用于不太长的文本最大支持的长度为——32766 个 UTF-8 类型的字符,中文应该是 255 个字,超过给定长度不再索引,适合存储姓名,邮箱,电话号码等。

text

keyword

分词

模糊查询

精确查询

聚合

排序

支持的字符长度

无限制

有限

Q:有分片没有被 node 管理,如何操作?

A:有可以大批量分片恢复有一些分片超时并且重试 3 次都失败了,尝试执行“分片重路由”。

Q:我有一个内存是 125G 的机器,如何部署节点?

A:官方文档,由于 JVM 大于 ~32G 内存时不会使用内存压缩技术,为了避免造成浪费,需要查询并设置小于临界值。采用多节点的方式部署,需要设置 cluster.routing.allocation.same_shard.host: true​ 避免同一个分片都在同一个物理机上面。需要给 Lucene 至少机器一半的内存也就是 64G,剩余的 64G 分别启动两个节点。

$ JAVA_HOME=`/usr/libexec/java_home -v 1.7` java -Xmx32600m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops
     bool UseCompressedOops   := true
$ JAVA_HOME=`/usr/libexec/java_home -v 1.7` java -Xmx32766m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops
     bool UseCompressedOops   = false

Q:如何做冷热数据存储

A:在节点的配置文件中标注是冷/热节点

node.attr.temperature: hot //热节点
node.attr.temperature: cold //冷节点

在创建索引时标注索引到节点的属性

index.routing.allocation.include.{attribute}   //表示索引可以分配在包含多个值中其中一个的节点上。
index.routing.allocation.require.{attribute}   //表示索引要分配在包含索引指定值的节点上(通常一般设置一个值)。
index.routing.allocation.exclude.{attribute}   //表示索引只能分配在不包含所有指定值的节点上。
PUT /xxx
{
  "settings": {
    "index.routing.allocation.require.hotwarm_type": "hot",   # 指定为热数据节点 
    "number_of_replicas": 0
  }
}
# 迁移至冷节点
PUT /xxx/_settings 
{ 
  "settings": { 
    "index.routing.allocation.require.hotwarm_type": "cold"    # 指定数据存放到冷数据节点
  } 
}

Q:有好用的索引运维的工具吗?

A:elastic.co 提供了 elasticsearch-curator,一个 python 写的工具

七、索引(Index)

创建索引

PUT xxx
{
    "mappings": {
        "properties": {}
    },
    "settings": {
        "index.mapping.total_fields.limit": 100000,
        "index.refresh_interval": -1,
        "index.number_of_shards": 32,
        "index.number_of_replicas": 0,
        "index.translog.sync_interval": "30s",
        "index.translog.durability": "async",
        "index.translog.flush_threshold_size": "1g",
        "index.store.type": "niofs",
        "index.max_result_window":"2147483647"
    }
}

使用脚本搜索

GET xxx/_search
{
  "post_filter": {
    "script" : {
        "script" : "doc['f.value'].values.length > 1"
    }
  }
}

创建固定内存索引

PUT xxx
{
  "settings": {
    "index.store.preload": [
      "nvd",
      "dvd",
      "tim",
      "doc",
      "dim"
    ],
    "index.mapping.total_fields.limit":100000,
    "index.refresh_interval": "-1",
    "index.number_of_shards": "14",
    "index.number_of_replicas": "0",
    "index.translog.sync_interval": "10s",
    "index.translog.durability": "async",
    "index.translog.flush_threshold_size": "1g",
    "index.store.type": "niofs",
    "index.max_result_window":"2147483647"
  }
}

写入前修改索引

PUT xxx/_settings
{
  "index.refresh_interval": "-1",
  "index.number_of_replicas": 0
}

写入完成后修改索引

PUT xxx/_settings
{
  "index.refresh_interval": "5s",
  "index.number_of_replicas": 1
}

只删除指定标签

POST xxx/_update_by_query?conflicts=proceed
#&max_docs=100000&refresh=true&requests_per_second=5000
{
  "script" : "ctx._source.remove('1')",
    "query" : {
        "exists": { "field": "1" }
    }
}

根据删除查询到的文档

POST xxx/_delete_by_query?conflicts=proceed
#&max_docs=100000&refresh=true&requests_per_second=5000
{
  "query": {"exists": {"field": "f"}}, 
  "track_total_hits": 2147483647
}

创建 reindex 任务

POST /_reindex?slices=1&refresh&wait_for_completion=false
{
  "source": {
    "index": "xxx",
    "remote": {
      "host": "http://10.0.0.19200",
      "socket_timeout": "1m",
      "connect_timeout": "60s"
    },
    "size": 10000
  },
  "dest": {
    "index": "xxxx",
    "routing": "=cat"
  }
}

查询 reindex 任务

GET _tasks?detailed=true&actions=*reindex

取消所有 reindex 任务

POST _tasks/_cancel?actions=*reindex

八、内存模型

九、路由

分片重路由

POST /_cluster/reroute?retry_failed=true&pretty

十、任务&集群

重启之后设置集群大批量恢复分片

PUT _cluster/settings
{
  "persistent" :
  {
     "cluster.routing.rebalance.enable": "all",
      "cluster.routing.allocation.node_concurrent_incoming_recoveries":2,
      "cluster.routing.allocation.node_concurrent_outgoing_recoveries":2,
      "cluster.routing.allocation.node_initial_primaries_recoveries":4,
      "cluster.routing.allocation.same_shard.host":true,
      "cluster.routing.allocation.node_concurrent_recoveries": 10,
      "indices.recovery.max_bytes_per_sec": "40mb"
    }
}

Task 任务查询

GET _cat/tasks
GET _tasks
GET _tasks?actions=indices:*
GET _tasks?actions=indices:data/write/*
GET _tasks?actions=indices:data/write/bulk
GET _tasks?actions=indices:data/write/update/byquery
GET _tasks?actions=indices:data/write/delete/byquery
GET _tasks?actions=indices:admin/flush
GET _tasks?actions=indices:admin/refresh[s]
GET _tasks?actions=indices:admin/forcemerge

清除 JVM cache 数据

POST _cache/clear

刷新至让文档可读

POST /_refresh
POST _flush
POST _flush/synced

节点下线操作(禁止分片迁移)

下线节点
# start
# 步骤1:将节点从集群路由策略中排除
PUT /_cluster/settings?pretty
{"transient":{"cluster.routing.allocation.exclude._name":"10.10.10.11"}}

# 步骤2:等待节点上分片全部被迁移
##检查集群状态,若出现pening_tasks,当pending_tasks的等级>=HIGH时,存在集群无法新建索引的风险
GET /_cluster/health?pretty
GET /_cluster/pending_tasks?pretty
##若集群中出现UNASSIGNED shards,检查原因,查看是否是分配策略导致无法迁移分片
GET /_cluster/allocation/explain?pretty
#步骤3:下线节点
#步骤4:取消节点禁用策略
PUT /_cluster/settings?pretty
{"transient":{"cluster.routing.allocation.exclude._ip": null}}
#end

PUT /_cluster/settings?pretty
{
  "transient": {
    "cluster.routing.allocation.exclude._name": "es1,es2,es3,es4..."
  }
}

2

评论区