ElasticSearch初步学习

news/2024/5/18 7:05:03

本文来自 《Elasticsearch: 权威指南》

https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

 

ElasticSearch安装与基本使用

安装

去下载版本https://www.elastic.co/downloads/elasticsearch

解压之后

cd elasticsearch-<version>

./bin/elasticsearch

curl 'http://localhost:9200/?pretty' 检查是否成功

-d参数即可让其运行于后台进程

单个 节点 可以作为一个运行中的 Elasticsearch 的实例。 而一个 集群 是一组拥有相同 cluster.name 的节点, 他们能一起工作并共享数据,还提供容错与可伸缩性。(当然,一个单独的节点也可以组成一个集群) 你可以在 elasticsearch.yml 配置文件中 修改 cluster.name ,该文件会在节点启动时加载 (译者注:这个重启服务后才会生效)

 

客户端

https://www.elastic.co/guide/en/elasticsearch/client/index.html

Java客户端

节点客户端(Node client)

节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点。

传输客户端(Transport client)

轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上。

两个 Java 客户端都是通过 9300 端口并使用 Elasticsearch 的原生 传输 协议和集群交互。集群中的节点通过端口 9300 彼此通信。如果这个端口没有打开,节点将无法形成一个集群。
RESTful API with JSON over HTTP

所有其他语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信,你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上,正如你所看到的,你甚至可以使用 curl 命令来和 Elasticsearch 交互。

 

获取文档数量

curl -XGET 'http://localhost:9200/_count?pretty' -d '{

    "query": {

        "match_all": {}

    }}'

 

面向文档

使用关系型数据库的行和列存储,这相当于是把一个表现力丰富的对象塞到一个非常大的电子表格中:为了适应表结构,你必须设法将这个对象扁平化--通常一个字段对应一列--而且每次查询时又需要将其重新构造为对象。

Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档。并且基于JSON。Elasticsearch 不仅存储文档,而且 _索引 每个文档的内容,使之可以被检索。在 Elasticsearch 中,我们对文档进行索引、检索、排序和过滤--而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。

 

一个 Elasticsearch 集群可以 包含多个 索引(index) ,相应的每个索引可以包含多个 类型(type),这些不同的类型存储着多个 文档(document、实体) ,每个文档又有 多个 属性(field) 。

一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询。这非常类似于 SQL 语句中的 INSERT 关键词,除了文档已存在时,新文档会替换旧文档情况之外。关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。

PUT /megacorp索引/employee类型/1文档id{

    "first_name" : "John",

    "last_name" :  "Smith",

    "age" :        25,

    "about" :      "I love to go rock climbing",

    "interests": [ "sports", "music" ]}

 

GET /megacorp/employee/1

返回

{

  "_index" :   "megacorp",

  "_type" :    "employee",

  "_id" :      "1",

  "_version" : 1,

  "found" :    true,

  "_source" :  {

      "first_name" :  "John",

      "last_name" :   "Smith",

      "age" :         25,

      "about" :       "I love to go rock climbing",

      "interests":  [ "sports", "music" ]

  }}

将 HTTP 命令由 PUT 改为 GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT 。

搜索所有

GET /megacorp/employee/_search 搜索所有

 

简单查询字符串

GET /megacorp/employee/_search?q=last_name:Smith

 

DSL方式:

名字搜索

GET /megacorp/employee/_search{

    "query" : {

        "match" : {

            "last_name" : "Smith"

        }

}}

 

 

名字+age范围

GET /megacorp/employee/_search{

    "query" : {

        "bool": {

            "must": {

                "match" : {

                    "last_name" : "smith" 

                }

            },

            "filter": {

                "range" : {

                    "age" : { "gt" : 30 }

                }

            }

        }

    }}

 

about属性上搜索

GET /megacorp/employee/_search{

    "query" : {

        "match" : {

            "about" : "rock climbing"

        }

    }}

会对搜索到的文档进行打分,默认按照相关性得分排序,即每个文档跟查询的匹配程度。

短语搜索

GET /megacorp/employee/_search{

    "query" : {

        "match_phrase" : {

            "about" : "rock climbing"

        }

    }}

搜索高亮,结果中还多了一个叫做 highlight 的部分

GET /megacorp/employee/_search{

    "query" : {

        "match_phrase" : {

            "about" : "rock climbing"

        }

    },

    "highlight": {

        "fields" : {

            "about" : {}

        }

    }}

兴趣爱好的统计

GET /megacorp/employee/_search{

  "aggs": {

    "all_interests": {

      "terms": { "field": "interests" }

    }

  }}

某个员工的兴趣爱好统计

GET /megacorp/employee/_search{

  "query": {

    "match": {

      "last_name": "smith"

    }

  },

  "aggs": {

    "all_interests": {

      "terms": {

        "field": "interests"

      }

    }

  }}

特定兴趣爱好的员工的平均年龄

GET /megacorp/employee/_search{

    "aggs" : {

        "all_interests" : {

            "terms" : { "field" : "interests" },

            "aggs" : {

                "avg_age" : {

                    "avg" : { "field" : "age" }

                }

            }

        }

    }}

ElasticSearch集群原理

 

ElasticSearch屏蔽了分布式系统的复杂性,自动做好了以下工作:

  1. 分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
  2. 按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
  3. 复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
  4. 将集群中任一节点的请求路由到存有相关数据的节点
  5. 集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复

 

ElasticSearch 的主旨是随时可用和按需扩容。 而扩容可以通过购买性能更强大( 垂直扩容 ,或 纵向扩容 ) 或者数量更多的服务器( 水平扩容 ,或 横向扩容 )来实现。

虽然 Elasticsearch 可以获益于更强大的硬件设备,但是垂直扩容是有极限的。 真正的扩容能力是来自于水平扩容--为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中。

一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

Elasticsearch是去中心化的,当一个节点被选举成为 主 节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。

作为用户,我们可以将请求发送到 集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。

获取集群健康

GET /_cluster/health

 

GET _cluster/health?level=indices

 

GET _cluster/health?level=shards

 

返回字段中的status:green、yellow、red代表越来越不健康

green

所有的主分片和副本分片都正常运行。

yellow

所有的主分片都正常运行,但不是所有的副本分片都正常运行。

red

有主分片没能正常运行。

Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。一个分片可以是 主 分片或者 副本 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。一个主分片最大能够存储 Integer.MAX_VALUE - 128 个文档,但是实际最大值还需要参考你的使用场景:包括你使用的硬件, 文档的大小和复杂程度,索引和查询文档的方式以及你期望的响应时长。一个副本分片只是一个主分片的拷贝。 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。在索引建立的时候就已经确定了主分片数,并且无法修改,但是副本分片数可以随时修改。

新建一个索引blogs,主分片3个,每个1个副本分片。

PUT /blogs{

   "settings" : {

      "number_of_shards" : 3,

      "number_of_replicas" : 1

   }}

 

 

只要cluster.name相同,那么新增一个节点即可自动加入集群中,最好配置单播模式而非组播,后续详说。

分片是一个功能完整的搜索引擎,它拥有使用一个节点上的所有资源的能力。 我们这个拥有6个分片(3个主分片和3个副本分片)的索引可以最大扩容到6个节点,每个节点上存在一个分片,并且每个分片拥有所在节点的全部资源。所以我们在规划数据主机的时候要预估某个索引的可能最大的数据量,以决定分片数量。

副本可以随时按需伸缩。在相同节点增加副本量并不能提高性能,因为每个分片获取的资源变少了,需要增加更多的硬件资源(说白了就是主机)来提升吞吐量,但是更多的副本提高了数据冗余。

PUT /blogs/_settings{

   "number_of_replicas" : 2}

 

故障转移

 

我们关闭的节点是一个主节点。而集群必须拥有一个主节点来保证正常工作,所以发生的第一件事情就是选举一个新的主节点: Node 2 。

在我们关闭 Node 1 的同时也失去了主分片 1 和 2 ,并且在缺失主分片的时候索引也不能正常工作。 如果此时来检查集群的状况,我们看到的状态将会为 red :不是所有主分片都在正常工作。

幸运的是,在其它节点上存在着这两个主分片的完整副本, 所以新的主节点立即将这些分片在 Node 2 和 Node 3 上对应的副本分片提升为主分片, 此时集群的状态将会为 yellow 。 这个提升主分片的过程是瞬间发生的,如同按下一个开关一般。

为什么我们集群状态是 yellow 而不是 green 呢? 虽然我们拥有所有的三个主分片,但是同时设置了每个主分片需要对应2份副本分片,而此时只存在一份副本分片。 所以集群不能为 green 的状态,不过我们不必过于担心:如果我们同样关闭了 Node 2 ,我们的程序 依然 可以保持在不丢任何数据的情况下运行,因为 Node 3 为每一个分片都保留着一份副本。

如果我们重新启动 Node 1 ,集群可以将缺失的副本分片再次进行分配,那么集群的状态也将如图 5 “将参数 number_of_replicas 调大到 2”所示。 如果 Node 1 依然拥有着之前的分片,它将尝试去重用它们,同时仅从主分片复制发生了修改的数据文件。

 

文档就是一个被ES实时序列化的JSON串,并对所有字段进行了索引。

文档包含三个元数据:

_index 文档在哪存放

_type 文档表示的对象类别

_id 文档唯一标识,可以自己指定,让ES自动生成【20位的URLSafe、Base64】

返回文档的一部分

GET /website/blog/123?_source=title,text

不需要返回元数据

GET /website/blog/123/_source

删除文档

DELETE /website/blog/123

ES使用乐观锁(_version版本号)来控制并发修改。文档也是不可更改的,对于API提供的更新操作实际上操作的是不同的版本的数据。

 

路由一个文档到一个分片中

当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

 

主分片和副本分片如何交互

 

我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。

写或者删除

 

  1. 客户端向 Node 1 发送新建、索引或者删除请求。
  2. 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3`,因为分片 0 的主分片目前被分配在 `Node 3 上。
  3. Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

 

  1. 客户端向 Node 1 发送获取请求。
  2. 节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2 。
  3. Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。

在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

 

一些重要的配置项

elasticsearch.yaml

cluster.name: elasticsearch_production

node.name: elasticsearch_005_data

path.data: /path/to/data1,/path/to/data2

path.logs: /path/to/logs

path.plugins: /path/to/plugins

discovery.zen.minimum_master_nodes: 2 最小节点数

gateway.recover_after_nodes: 8

gateway.expected_nodes: 10

gateway.recover_after_time: 5m

discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]

 


http://www.niftyadmin.cn/n/3568786.html

相关文章

0.04折老司机建站节福利来了,没时间解释了快上车!

CNNIC日前发布第39次统计报告称&#xff0c;国内网站去年增速高达14.1%。这意味着2016年&#xff0c;我国网站数量增长大约60万&#xff0c;网站作为企业信息化的基础迎来再次爆发。业内人士认为&#xff1a;H5自助建站迎来了最好的发展时机&#xff0c;“苦逼这么多年的建站行…

POI操作ppt,合并,转图片

引入POI compile group: org.apache.poi, name: poi-ooxml, version: 4.1.0 compile group: batik, name: batik-bridge, version: 1.6-1 compile group: org.apache.xmlgraphics, name: batik-anim, version: 1.11 /*** https://www.w3cschool.cn/apache_poi_ppt/apache_po…

读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用

一个关于赋值的有趣的事情是你可以将它们链在一起&#xff1a; 1 int x, y, z; 2 3 x y z 15; // chain of assignments 同样有趣的是赋值采用右结合律&#xff0c;所以上面的赋值链被解析成下面这个样子&#xff1a; 1 x (y (z 15)); 在这里&#xff0c;15被赋值给z,然…

IDEA 使用方法快捷键

CtrlShift Enter&#xff0c;语句完成“&#xff01;”&#xff0c;否定完成&#xff0c;输入表达式时按 “&#xff01;”键CtrlE&#xff0c;最近的文件CtrlShiftE&#xff0c;最近更改的文件ShiftClick&#xff0c;可以关闭文件Ctrl[ OR ]&#xff0c;可以跑到大括号的开头…

微信小程序自定义数据分析试水

昨晚收到小程序自定义分析的内测邀请&#xff0c;简单试用了一下。说明挺长的&#xff0c;大概是这个意思&#xff1a; 一、定义一系列事件&#xff0c;对其进行统计 事件可以对页面中的这些事件进行追踪 click enterPage leavePage pageLoad pageUnload pullDownRefresh launc…

乡愁 余光中

小时候 乡愁是一枚小小的邮票 我在这头 母亲在那头 长大后 乡愁是一张窄窄的船票 我在这头 新娘在那头 后来啊 乡愁是一方矮矮的坟墓 我在外头 母亲在里头 而现在 乡愁是一湾浅浅的海峡 我在这头 大陆在那头

基于Jenkins+Git+Gradle实现自动打包部署

下载地址&#xff1a;https://jenkins.io/zh/download/ jenkins依赖Java&#xff0c;所以首先配置好java环境。建议下载 xxx.war,使用java -jar的方式来启动&#xff0c;其中java -jar可以写到脚本中&#xff0c;做到一键启动。 jenkins的默认配置和工作目录运行在~/.jenkins…

再别康桥 徐志摩

轻轻的我走了&#xff0c;正如我轻轻的来&#xff1b; 我轻轻的招手&#xff0c;作别西天的云彩。 那河畔的金柳&#xff0c;是夕阳中的新娘&#xff1b; 波光里的艳影&#xff0c;在我的心头荡漾。 软泥上的青荇&#xff0c;油油的在水底招摇&#xff1b; 在康河的柔波里…