1. ElasticSearch疾速入门

1.1. 根本介绍

  • ElasticSearch特色

    Elasticsearch是实时的分布式搜寻剖析引擎,外部应用Lucene做索引与搜寻

    • 实时性:新增到 ES 中的数据在1秒后就能够被检索到,这种新增数据对搜寻的可见性称为“准实时搜寻”
    • 分布式:意味着能够动静调整集群规模,弹性扩容
    • 集群规模:能够扩大到上百台服务器,解决PB级结构化或非结构化数据
    • 各节点组成对等的网络结构,某些节点呈现故障时会主动调配其余节点代替其进行工作

Lucene是Java语言编写的全文搜寻框架,用于解决纯文本的数据,但它只是一个库,提供建设索引、执行搜寻等接口,但不蕴含分布式服务,这些正是 ES 做的

  • ElasticSearch应用场景

    ElasticSearch广泛应用于各行业畛域, 比方维基百科, GitHub的代码搜寻,电商网站的大数据日志统计分析, BI零碎报表统计分析等。

    • 提供分布式的搜索引擎和数据分析引擎

      比方百度,网站的站内搜索,IT零碎的检索, 数据分析比方热点词统计, 电商网站商品TOP排名等。

    • 全文检索,结构化检索,数据分析

      反对全文检索, 比方查找蕴含指定名称的商品信息; 反对构造检索, 比方查找某个分类下的所有商品信息;

      还能够反对高级数据分析, 比方统计某个商品的点击次数, 某个商品有多少用户购买等等。

    • 反对海量数据准实时的解决

      采纳分布式节点, 将数据扩散到多台服务器下来存储和检索, 实现海量数据的解决, 比方统计用户的行为日志, 可能在秒级别对数据进行检索和剖析。

  • ElasticSearch基本概念介绍

    ElasticSearchRelational Database
    IndexDatabase
    TypeTable
    DocumentRow
    FieldColumn
    MappingSchema
    Everything is indexedIndex
    Query DSLSQL
    GET http://...SELECT * FROM table...
    PUT http://...UPDATE table SET...
    • 索引(Index)

      相比传统的关系型数据库,索引相当于SQL中的一个【数据库】,或者一个数据存储计划(schema)。

    • 类型(Type)

      一个索引外部能够定义一个或多个类型, 在传统关系数据库来说, 类型相当于【表】的概念。

    • 文档(Document)

      文档是Lucene索引和搜寻的原子单位,它是蕴含了一个或多个域的容器,采纳JSON格局示意。相当于传统数据库【行】概念

    • 集群(Cluster)

      集群是由一台及以上主机节点组成并提供存储及搜寻服务, 多节点组成的集群领有冗余能力,它能够在一个或几个节点呈现故障时保障服务的整体可用性。

    • 节点(Node)

      Node为集群中的单台节点,其能够为master节点亦可为slave节点(节点属性由集群外部选举得出)并提供存储相干数据的性能

    • 切片(shards)

      切片是把一个大文件宰割成多个小文件而后扩散存储在集群中的多个节点上, 能够将其看作mysql的分库分表概念。 Shard有两种类型:primary主片和replica正本,primary用于文档存储,每个新的索引会主动创立5个Primary shard;Replica shard是Primary Shard的正本,用于冗余数据及进步搜寻性能。

留神: ES7之后Type被舍弃,只有Index(等同于数据库+表定义)和Document(文档,行记录)。

1.2 ElasticSearch装置

  1. 下载ElasticSearch服务

    下载最新版ElasticSearch7.10.2: https://www.elastic.co/cn/start

  2. 解压安装包

    tar -xvf elasticsearch-7.10.2-linux-x86_64.tar.gz
  3. ElasticSearch不能以Root身份运行, 须要独自创立一个用户

    1. groupadd elsearch2. useradd elsearch -g elsearch -p elasticsearch3. chown -R elsearch:elsearch  /usr/local/elasticsearch-7.10.2

    执行以上命令,创立一个名为elsearch用户, 并赋予目录权限。

  4. 批改配置文件

    vi config/elasticsearch.yml, 默认状况下会绑定本机地址, 外网不能拜访, 这里要批改下:

    # 外网拜访地址network.host: 0.0.0.0
  5. 敞开防火墙

    systemctl stop  firewalld.servicesystemctl disable  firewalld.service
  1. 指定JDK版本

    • 最新版的ElasticSearch须要JDK11版本, 下载JDK11压缩包, 并进行解压。
    • 批改环境配置文件

      vi bin/elasticsearch-env

      参照以下地位, 追加一行, 设置JAVA_HOME, 指定JDK11门路。

      JAVA_HOME=/usr/local/jdk-11.0.11# now set the path to javaif [ ! -z "$JAVA_HOME" ]; then  JAVA="$JAVA_HOME/bin/java"else  if [ "$(uname -s)" = "Darwin" ]; then    # OSX has a different structure    JAVA="$ES_HOME/jdk/Contents/Home/bin/java"  else    JAVA="$ES_HOME/jdk/bin/java"  fifi
  1. 启动ElasticSearch

    • 切换用户

      su elsearch

    • 当前台常驻形式启动

      bin/elasticsearch -d

  1. 问题记录

    呈现max virtual memory areas vm.max_map_count [65530] is too low, increase to at least 错误信息

    批改系统配置:

    • vi /etc/sysctl.conf

      增加

      vm.max_map_count=655360

      执行失效

      sysctl -p

    • vi /etc/security/limits.conf

      在文件开端增加

      * soft nofile 65536* hard nofile 131072* soft nproc 2048* hard nproc 4096elsearch soft nproc 125535elsearch hard nproc 125535

      从新切换用户即可:

      su - elsearch

  2. 拜访验证

    拜访地址:http://192.168.116.140:9200/_...

    启动状态有green、yellow和red。 green是代表启动失常。

1.3 Kibana服务装置

Kibana是一个针对Elasticsearch的开源剖析及可视化平台,用来搜寻、查看交互存储在Elasticsearch索引中的数据。

  1. 到官网下载, Kibana安装包, 与之对应7.10.2版本, 抉择Linux 64位版本下载,并进行解压。

    tar -xvf kibana-7.10.2-linux-x86_64.tar.gz
  2. Kibana启动不能应用root用户, 应用下面创立的elsearch用户, 进行赋权:

    chown -R elsearch:elsearch kibana-7.10.2-linux-x86_64
  3. 批改配置文件

    vi config/kibana.yml , 批改以下配置:

    # 服务端口server.port: 5601# 服务地址server.host: "0.0.0.0"# elasticsearch服务地址elasticsearch.hosts: ["http://192.168.116.140:9200"]
  4. 启动kibana

    ./kibana -q

    看到以下日志, 代表启动失常

    log   [01:40:00.143] [info][listening] Server running at http://0.0.0.0:5601

    如果呈现启动失败的状况, 要查看集群各节点的日志, 确保服务失常运行状态。

  5. 拜访服务

    http://192.168.116.140:5601/a...

1.4 ES的根底操作

  1. 进入Kibana治理后盾

    地址: http://192.168.116.140:5601

    进入"Dev Tools"栏:


    在Console中输出命令进行操作。

  1. 分片设置:

    这里减少名为orders的索引, 因为是单节点, 如果正本数, 是会呈现谬误。

    PUT orders{    "settings": {        "index": {            "number_of_shards": 2,            "number_of_replicas": 2        }    }}

    查看索引信息, 会呈现yellow提醒:

    因为单节点模式, 只有主节点信息:

    删除从新创立:

    PUT orders{    "settings": {        "index": {            "number_of_shards": 2,            "number_of_replicas": 0        }    }}

    将分片数设为0, 再次查看, 则显示失常:

  1. 索引

    3.1 新建索引orders

    ## 创立索引PUT orders

    3.2 查问索引orders

    ## 查问索引GET orders

通过查问命令, 能查看到对应信息, 默认分片数和正本数都为1:

"number_of_shards" : "1", ## 主分片数"number_of_replicas" : "1", ## 副分片数


3.3 删除索引

## 删除索引DELETE orders

3.4 索引的设置

## 设置索引PUT orders{  "settings": {    "index": {      "number_of_shards": 1,       "number_of_replicas": 0    }  }}
  1. 文档

    4.1 创立文档

    ## 创立文档,生成默认的文档idPOST orders/_doc{  "name": "袜子1双",  "price": "200",  "count": 1,  "address": "北京市"}## 创立文档,生成自定义文档idPOST orders/_doc/1{  "name": "袜子1双",  "price": "2",  "count": 1,  "address": "北京市"}

    4.2 查问文档

    ## 依据指定的id查问GET orders/_doc/1## 依据指定条件查问文档GET orders/_search{  "query": {    "match": {      "address": "北京市"    }  }}## 查问全副文档GET orders/_search

    4.3 更新文档

    ## 更新文档POST orders/_doc/1{  "price": "200"}## 更新文档POST orders/_update/1{  "doc": {    "price": "200"  }}

    4.4 删除文档

    ## 删除文档DELETE orders/_doc/1
  2. 对于映射,只能进行字段增加,不能对字段进行批改或删除,如有须要,则从新创立映射。

    ## 设置mapping信息PUT orders/_mappings{  "properties":{    "price": {      "type": "long"    }  }}## 设置分片和映射PUT orders{  "settings": {    "index": {      "number_of_shards": 1,       "number_of_replicas": 0    }  },  "mappings": {    "properties": {      "name": {        "type": "text"      },      "price": {        "type": "long"      },      "count": {        "type": "long"      },      "address": {        "type": "text"      }    }  }}

1.5 ES数据类型

整体数据类型构造:

  1. String 类型

    次要分为text与keyword两种类型。两者区别次要在于是否分词。

    • text类型

      会进行分词解决, 分词器默认采纳的是standard。

    • keyword类型

      不会进行分词解决。在ES的倒排索引中存储的是残缺的字符串。

  2. Date工夫类型

    数据库里的日期类型须要标准具体的传入格局, ES是能够管制,自适应解决。

    传递不同的工夫类型:

    PUT my_date_index/_doc/1{ "date": "2021-01-01" } PUT my_date_index/_doc/2{ "date": "2021-01-01T12:10:30Z" } PUT my_date_index/_doc/3{ "date": 1520071600001 } ## 查看日期数据:GET my_date_index/_mapping

    ES的Date类型容许能够应用的格局有:

    yyyy-MM-dd HH:mm:ss
    yyyy-MM-dd
    epoch_millis(毫秒值)
  3. 复合类型

    简单类型次要有三种: Array、object、nested。

    • Array类型: 在Elasticsearch中,数组不须要申明专用的字段数据类型。然而,在数组中的所有值都必须具备雷同的数据类型。举例:

      POST orders/_doc/1{  "goodsName":["足球","篮球","兵乓球", 3]}POST orders/_doc/1{  "goodsName":["足球","篮球","兵乓球"]}
    • object类型: 用于存储单个JSON对象, 相似于JAVA中的对象类型, 能够有多个值, 比方LIST<object>,能够蕴含多个对象。

      然而LIST<object>只能作为整体, 不能独立的索引查问。举例:

      # 新增第一组数据, 组别为美国,两个人。POST my_index/_doc/1{      "group" : "america",      "users" : [        {          "name" : "John",          "age" :  "22"        },        {          "name" : "Alice",          "age" :  "21"        }      ]    }    # 新增第二组数据, 组别为英国, 两个人。POST my_index/_doc/2{      "group" : "england",      "users" : [        {          "name" : "lucy",          "age" :  "21"        },        {          "name" : "John",          "age" :  "32"        }      ]    }

      这两组数据都蕴含了name为John,age为21的数据,

      采纳这个搜寻条件, 理论后果:

      GET my_index/_search{    "query": {        "bool": {            "must": [                {                    "match": {                        "users.name": "John"                    }                },                {                    "match": {                        "users.age": "21"                    }                }            ]        }    }}

      后果能够看到, 这两组数据都能找出,因为每一组数据都是作为一个整体进行搜寻匹配, 而非具体某一条数据。

    • Nested类型

      用于存储多个JSON对象组成的数组,nested 类型是 object 类型中的一个特例,能够让对象数组独立索引和查问。

      举例:

      创立nested类型的索引:

      PUT my_index{      "mappings": {        "properties": {          "users": {            "type": "nested"          }        }      }    }

      收回查问申请:

      GET my_index/_search{    "query": {        "bool": {            "must": [                {                    "nested": {                        "path": "users",                        "query": {                            "bool": {                                "must": [                                    {                                        "match": {                                            "users.name": "John"                                        }                                    },                                    {                                        "match": {                                            "users.age": "21"                                        }                                    }                                ]                            }                        }                    }                }            ]        }    }}

      采纳以前的条件, 这个时候查不到任何后果, 将年龄改成22, 就能够找出对应的数据:

      "hits" : [      {        "_index" : "my_index",        "_type" : "_doc",        "_id" : "1",        "_score" : 1.89712,        "_source" : {          "group" : "america",          "users" : [            {              "name" : "John",              "age" : "22"            },            {              "name" : "Alice",              "age" : "21"            }          ]        }      }    ]
  1. GEO地理位置类型

    当初大部分APP都有基于地位搜寻的性能, 比方交友、购物利用等。这些性能是基于GEO搜寻实现的。

    对于GEO地理位置类型,分为地理坐标类型:Geo-point, 和形态:Geo-shape 两种类型。

    经纬度英文简写负数正数
    维度latitudelat北纬南纬
    经度longitudelon或lng东经西经

    创立地理位置索引:

    PUT my_locations{  "mappings": {    "properties": {      "location": {        "type": "geo_point"      }    }  }}

    增加地理位置数据:

    # 采纳object对象类型PUT my_locations/_doc/1{    "user": "张三",    "text": "Geo-point as an object",    "location": {        "lat": 41.12,        "lon": -71.34    }}# 采纳string类型PUT my_locations/_doc/2{    "user": "李四",    "text": "Geo-point as a string",    "location": "45.12,-75.34"}# 采纳geohash类型(geohash算法能够将多维数据映射为一串字符)PUT my_locations/_doc/3{    "user": "王二麻子",    "text": "Geo-point as a geohash",    "location": "drm3btev3e86"}# 采纳array数组类型PUT my_locations/_doc/4{    "user": "木头老七",    "text": "Geo-point as an array",    "location": [        -80.34,        51.12    ]}

    需要:搜寻出间隔我{"lat" : 40,"lon" : -70} 200km范畴内的人:

    GET my_locations/_search{    "query": {        "bool": {            "must": {                "match_all": {}            },            "filter": {                "geo_distance": {                    "distance": "200km",                    "location": {                        "lat": 40,                        "lon": -70                    }                }            }        }    }}

2. ES高可用集群配置

2.1 ElasticSearch集群介绍

  • 主节点(或候选主节点)

    主节点负责创立索引、删除索引、调配分片、追踪集群中的节点状态等工作, 主节点负荷绝对较轻, 客户端申请能够间接发往任何节点, 由对应节点负责散发和返回处理结果。

    一个节点启动之后, 采纳 Zen Discovery机制去寻找集群中的其余节点, 并与之建设连贯, 集群会从候选主节点中选举出一个主节点, 并且一个集群只能选举一个主节点, 在某些状况下, 因为网络通信丢包等问题, 一个集群可能会呈现多个主节点, 称为“脑裂景象”, 脑裂会存在失落数据的可能, 因为主节点领有最高权限, 它决定了什么时候能够创立索引, 分片如何挪动等, 如果存在多个主节点, 就会产生抵触, 容易产生数据失落。要尽量避免这个问题, 能够通过 discovery.zen.minimum_master_nodes 来设置起码可工作的候选主节点个数。 倡议设置为(候选主节点/2) + 1 比方三个候选主节点,该配置项为 (3/2)+1 ,来保障集群中有半数以上的候选主节点, 没有足够的master候选节点, 就不会进行master节点选举,缩小脑裂的可能。

    主节点的参数设置:

    node.master = truenode.data = false
  • 数据节点

    数据节点负责数据的存储和CRUD等具体操作,数据节点对机器配置要求比拟高、,首先须要有足够的磁盘空间来存储数据,其次数据操作对系统CPU、Memory和IO的性能耗费都很大。通常随着集群的扩充,须要减少更多的数据节点来进步可用性。

    数据节点的参数设置:

    node.master = falsenode.data = true
  • 客户端节点

    客户端节点不做候选主节点, 也不做数据节点的节点,只负责申请的散发、汇总等等,减少客户端节点类型更多是为了负载平衡的解决。

    node.master = falsenode.data = false
  • 提取节点(预处理节点)

    能执行预处理管道,有本人独立的工作要执行, 在索引数据之前能够先对数据做预处理操作, 不负责数据存储也不负责集群相干的事务。

    参数设置:

    node.ingest = true
  • 协调节点

    协调节点,是一种角色,而不是实在的Elasticsearch的节点,不能通过配置项来指定哪个节点为协调节点。集群中的任何节点,都能够充当协调节点的角色。当一个节点A收到用户的查问申请后,会把查问子句散发到其它的节点,而后合并各个节点返回的查问后果,最初返回一个残缺的数据集给用户。在这个过程中,节点A表演的就是协调节点的角色。

    ES的一次申请十分相似于Map-Reduce操作。在ES中对应的也是两个阶段,称之为scatter-gather。客户端收回一个申请到集群的任意一个节点,这个节点就是所谓的协调节点,它会把申请转发给含有相干数据的节点(scatter阶段),这些数据节点会在本地执行申请而后把后果返回给协调节点。协调节点将这些后果汇总(reduce)成一个繁多的全局后果集(gather阶段) 。

  • 部落节点

    在多个集群之间充当联结客户端, 它是一个非凡的客户端 , 能够连贯多个集群,在所有连贯的集群上执行搜寻和其余操作。 部落节点从所有连贯的集群中检索集群状态并将其合并成全局集群状态。 把握这一信息,就能够对所有集群中的节点执行读写操作,就如同它们是本地的。 请留神,部落节点须要可能连贯到每个配置的集群中的每个单个节点。

2.2 ElasticSearch集群原理

2.2.1 集群分布式原理

ES集群能够依据节点数, 动静调整主分片与正本数, 做到整个集群无效平衡负载。

单节点状态下:

两个节点状态下, 正本数为1:

三个节点状态下, 正本数为1:

三个节点状态下, 正本数为2:

2.2.2 分片解决机制

设置分片大小的时候, 需事后做好容量布局, 如果节点数过多, 分片数过小, 那么新的节点将无奈分片, 不能做到程度扩大, 并且单个分片数据量太大, 导致数据重新分配耗时过大。

假如一个集群中有一个主节点、两个数据节点。orders索引的分片散布状况如下所示:

PUT orders{    "settings":{        "number_of_shards":2,  ## 主分片 2        "number_of_replicas":2  ## 副分片 4    }}

整个集群中存在P0和P1两个主分片, P0对应的两个R0正本分片, P1对应的是两个R1正本分片。

2.2.3 新建索引解决流程

  1. 写入的申请会进入主节点, 如果是NODE2正本接管到写申请, 会将它转发至主节点。
  2. 主节点接管到申请后, 依据documentId做取模运算(内部没有传递documentId,则会采纳外部自增ID),

    如果取模后果为P0,则会将写申请转发至NODE3解决。

  3. NODE3节点写申请解决实现之后, 采纳异步形式, 将数据同步至NODE1和NODE2节点。

2.2.4 读取索引解决流程

  1. 读取的申请进入MASTER节点, 会依据取模后果, 将申请转发至不同的节点。
  2. 如果取模后果为R0,外部还会有负载平衡解决机制,如果上一次的读取申请是在NODE1的R0, 那么以后申请会转发至NODE2的R0, 保障每个节点都可能平衡的解决申请数据。
  3. 读取的申请如果是间接落至正本节点, 正本节点会做判断, 若有数据则返回,没有的话会转发至其余节点解决。

2.3 ElasticSearch集群部署布局

筹备一台虚拟机:

192.168.116.140: Node-1 (节点一), 端口:9200, 9300

192.168.116.140: Node-2 (节点二),端口:9201, 9301

192.168.116.140: Node-3 (节点三),端口:9202, 9302

2.4 ElasticSearch集群配置

  1. 解压安装包:

    mkdir /usr/local/clustercd /usr/local/clustertar -xvf elasticsearch-7.10.2-linux-x86_64.tar.gz

    将安装包解压至/usr/local/cluster目录。

  2. 批改集群配置文件:

    vi /usr/local/cluster/elasticsearch-7.10.2-node1/config/elasticsearch.yml 

    192.168.116.140, 第一台节点配置内容:

    # 集群名称cluster.name: my-application#节点名称node.name: node-1# 绑定IP地址network.host: 192.168.116.140# 指定服务拜访端口http.port: 9200# 指定API端户端调用端口transport.tcp.port: 9300#集群通讯地址discovery.seed_hosts: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#集群初始化可能参选的节点信息cluster.initial_master_nodes: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#开启跨域拜访反对,默认为falsehttp.cors.enabled: true##跨域拜访容许的域名, 容许所有域名http.cors.allow-origin: "*"

    批改目录权限:

    chown -R elsearch:elsearch /usr/local/cluster/elasticsearch-7.10.2-node1
  3. 复制ElasticSearch装置目录:

    复制其余两个节点:

    cd /usr/local/clustercp -r elasticsearch-7.10.2-node1 elasticsearch-7.10.2-node2cp -r elasticsearch-7.10.2-node1 elasticsearch-7.10.2-node3
  4. 批改其余节点的配置:

    192.168.116.140 第二台节点配置内容:

    # 集群名称cluster.name: my-application#节点名称node.name: node-2# 绑定IP地址network.host: 192.168.116.140# 指定服务拜访端口http.port: 9201# 指定API端户端调用端口transport.tcp.port: 9301#集群通讯地址discovery.seed_hosts: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#集群初始化可能参选的节点信息cluster.initial_master_nodes: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#开启跨域拜访反对,默认为falsehttp.cors.enabled: true##跨域拜访容许的域名, 容许所有域名http.cors.allow-origin: "*"

    192.168.116.140 第三台节点配置内容:

    # 集群名称cluster.name: my-application#节点名称node.name: node-3# 绑定IP地址network.host: 192.168.116.140# 指定服务拜访端口http.port: 9202# 指定API端户端调用端口transport.tcp.port: 9302#集群通讯地址discovery.seed_hosts: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#集群初始化可能参选的节点信息cluster.initial_master_nodes: ["192.168.116.140:9300", "192.168.116.140:9301","192.168.116.140:9302"]#开启跨域拜访反对,默认为falsehttp.cors.enabled: true##跨域拜访容许的域名, 容许所有域名http.cors.allow-origin: "*"
  1. 启动集群节点

    先切换elsearch用户, 在三台节点顺次启动服务:

    su elsearch/usr/local/cluster/elasticsearch-7.10.2-node1/bin/elasticsearch -d/usr/local/cluster/elasticsearch-7.10.2-node2/bin/elasticsearch -d/usr/local/cluster/elasticsearch-7.10.2-node3/bin/elasticsearch -d

    留神: 如果启动呈现谬误, 将各节点的data目录清空, 再重启服务。

  2. 集群状态查看

    集群装置与启动胜利之后, 执行申请: http://192.168.116.140:9200/_...

    能够看到三个节点信息,三个节点会自行选举出主节点:

2.5 ElasticSearch集群分片测试

批改kibana的配置文件,指向创立的集群节点:

elasticsearch.hosts: ["http://192.168.116.140:9200","http://192.168.116.140:9201","http://192.168.116.140:9202"]

重启kibana服务, 进入控制台:

http://192.168.116.140:5601/a...

再次创立索引(正本数量范畴内):

PUT orders{    "settings": {        "index": {            "number_of_shards": 2,            "number_of_replicas": 2        }    }}

能够看到, 这次后果是失常:

集群并非能够随便减少正本数量, 创立索引(超出正本数量范畴):

PUT orders{    "settings": {        "index": {            "number_of_shards": 2,            "number_of_replicas": 5        }    }}

能够看到呈现了yellow正告谬误:

好了,至此ES集群搭建结束,欢送气味相投的小伙伴,一起交流学习成长。进阶架构师,Fighting!!!

本文由传智教育博学谷 - 狂野架构师教研团队公布,转载请注明出处!

如果本文对您有帮忙,欢送关注和点赞;如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源