zoukankan      html  css  js  c++  java
  • es

    Elasticsearch

    介绍

    Elasticsearch(ES)是一个基于Lucene构建的开源、分布式、RESTful接口的全文搜索引擎。Elasticsearch还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,ES能够横向扩展至数以百计的服务器存储以及处理PB级的数据。可以在极短的时间内存储、搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的核心发动机。

    Elasticsearch能做什么

    1. 当你经营一家网上商店,你可以让你的客户搜索你卖的商品。在这种情况下,你可以使用ElasticSearch来存储你的整个产品目录和库存信息,为客户提供精准搜索,可以为客户推荐相关商品。
    2. 当你想收集日志或者交易数据的时候,需要分析和挖掘这些数据,寻找趋势,进行统计,总结,或发现异常。在这种情况下,你可以使用Logstash或者其他工具来进行收集数据,当这引起数据存储到ElasticsSearch中。你可以搜索和汇总这些数据,找到任何你感兴趣的信息。
    3. 对于程序员来说,比较有名的案例是GitHub,GitHub的搜索是基于ElasticSearch构建的,在github.com/search页面,你可以搜索项目、用户、issue、pull request,还有代码。共有40~50个索引库,分别用于索引网站需要跟踪的各种数据。虽然只索引项目的主分支(master),但这个数据量依然巨大,包括20亿个索引文档,30TB的索引文件。

    Elasticsearch基本概念

    Near Realtime(NRT) 几乎实时

    Elasticsearch是一个几乎实时的搜索平台。意思是,从索引一个文档到这个文档可被搜索只需要一点点的延迟,这个时间一般为毫秒级。

    Cluster 集群

    群集是一个或多个节点(服务器)的集合, 这些节点共同保存整个数据,并在所有节点上提供联合索引和搜索功能。一个集群由一个唯一集群ID确定,并指定一个集群名(默认为“elasticsearch”)。该集群名非常重要,因为节点可以通过这个集群名加入群集,一个节点只能是群集的一部分。

    确保在不同的环境中不要使用相同的群集名称,否则可能会导致连接错误的群集节点。例如,你可以使用logging-dev、logging-stage、logging-prod分别为开发、阶段产品、生产集群做记录。

    Node节点

    节点是单个服务器实例,它是群集的一部分,可以存储数据,并参与群集的索引和搜索功能。就像一个集群,节点的名称默认为一个随机的通用唯一标识符(UUID),确定在启动时分配给该节点。如果不希望默认,可以定义任何节点名。这个名字对管理很重要,目的是要确定你的网络服务器对应于你的ElasticSearch群集节点。

    我们可以通过群集名配置节点以连接特定的群集。默认情况下,每个节点设置加入名为“elasticSearch”的集群。这意味着如果你启动多个节点在网络上,假设他们能发现彼此都会自动形成和加入一个名为“elasticsearch”的集群。

    在单个群集中,你可以拥有尽可能多的节点。此外,如果“elasticsearch”在同一个网络中,没有其他节点正在运行,从单个节点的默认情况下会形成一个新的单节点名为”elasticsearch”的集群。

    Index索引

    索引是具有相似特性的文档集合。例如,可以为客户数据提供索引,为产品目录建立另一个索引,以及为订单数据建立另一个索引。索引由名称(必须全部为小写)标识,该名称用于在对其中的文档执行索引、搜索、更新和删除操作时引用索引。在单个群集中,你可以定义尽可能多的索引。

    Type类型

    在索引中,可以定义一个或多个类型。类型是索引的逻辑类别/分区,其语义完全取决于你。一般来说,类型定义为具有公共字段集的文档。例如,假设你运行一个博客平台,并将所有数据存储在一个索引中。在这个索引中,你可以为用户数据定义一种类型,为博客数据定义另一种类型,以及为注释数据定义另一类型。

    Document文档

    文档是可以被索引的信息的基本单位。例如,你可以为单个客户提供一个文档,单个产品提供另一个文档,以及单个订单提供另一个文档。本文件的表示形式为JSON(JavaScript Object Notation)格式,这是一种非常普遍的互联网数据交换格式。

    在索引/类型中,你可以存储尽可能多的文档。请注意,尽管文档物理驻留在索引中,文档实际上必须索引或分配到索引中的类型。

    Shards & Replicas分片与副本

    索引可以存储大量的数据,这些数据可能超过单个节点的硬件限制。例如,十亿个文件占用磁盘空间1TB的单指标可能不适合对单个节点的磁盘或可能太慢服务仅从单个节点的搜索请求。

    为了解决这一问题,Elasticsearch提供细分你的指标分成多个块称为分片的能力。当你创建一个索引,你可以简单地定义你想要的分片数量。每个分片本身是一个全功能的、独立的“指数”,可以托管在集群中的任何节点。

    Shards分片的重要性主要体现在以下两个特征:

    1. 分片允许你水平拆分或缩放内容的大小
    2. 分片允许你分配和并行操作的碎片(可能在多个节点上)从而提高性能/吞吐量 这个机制中的碎片是分布式的以及其文件汇总到搜索请求是完全由ElasticSearch管理,对用户来说是透明的。

    在同一个集群网络或云环境上,故障是任何时候都会出现的,拥有一个故障转移机制以防分片和节点因为某些原因离线或消失是非常有用的,并且被强烈推荐。为此,Elasticsearch允许你创建一个或多个拷贝,你的索引分片进入所谓的副本或称作复制品的分片,简称Replicas。

    Replicas的重要性主要体现在以下两个特征:

    1. 副本为分片或节点失败提供了高可用性。为此,需要注意的是,一个副本的分片不会分配在同一个节点作为原始的或主分片,副本是从主分片那里复制过来的。
    2. 副本允许用户扩展你的搜索量或吞吐量,因为搜索可以在所有副本上并行执行。

    ES基本概念与关系型数据库的比较

    ES概念 关系型数据库
    Index(索引)支持全文检索 Database(数据库)
    Type(类型) Table(表)
    Document(文档),不同文档可以有不同的字段集合 Row(数据行)
    Field(字段) Column(数据列)
    Mapping(映射) Schema(模式)

    ES API

    以下示例使用curl演示。

    查看健康状态

    curl -X GET 127.0.0.1:9200/_cat/health?v
    
    curl -X GET 127.0.0.1:9200/_cat/health?json
    

    输出:

    
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   296  100   296    0     0  98666      0 --:--:-- --:--:-- --:--:-- 98666epoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
    1632699488 23:38:08  elasticsearch yellow          1         1     10  10    0    0        7             0                  -                 58.8%
    
    
    

    image-20210927074543291

    查询当前es集群中所有的indices

    curl -X GET 127.0.0.1:9200/_cat/indices?v
    

    输出:

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  1320  100  1320    0     0  19130      0 --:--:-- --:--:-- --:--:-- 19411health status index                    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
    yellow open   randy                    ltl9E0XgR3WtInUhDcx9GA   1   1          5            0     28.3kb         28.3kb
    yellow open   ik11                     i2gTEKs5QwCldwODjDWNqQ   1   1          1            0      4.6kb          4.6kb
    yellow open   books                    OkR6vZwGRFKrv8os9yYHxQ   1   1          1            0      4.9kb          4.9kb
    green  open   .kibana_task_manager_1   eAgjs3JIRWyIT9tvPGKEbQ   1   0          2            0     12.4kb         12.4kb
    yellow open   w10                      pwaV4V5hTBaAXgNtNJWUoA   1   1          2            0      3.6kb          3.6kb
    green  open   .apm-agent-configuration sSyQ5UK8QDKrREHSCEes0w   1   0          0            0       283b           283b
    green  open   .kibana_1                uxM7qzpdT8eIiyLWjB-P4g   1   0         18            8     23.9kb         23.9kb
    yellow open   t1                       X4fm77UvQ4WDvvzhHKDWGw   1   1          3            0     10.6kb         10.6kb
    yellow open   ik1                      ZMORXL_kQcOpbMBg1XVfAQ   1   1          3            0      3.9kb          3.9kb
    yellow open   t3                       iQl41PUsRMeRB64nE7VpKA   1   1          2            0      4.7kb          4.7kb
    
    

    image-20210927074732174

    创建索引

    curl -X PUT 127.0.0.1:9200/randysun
    

    输出:

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100    67  100    67    0     0    109      0 --:--:-- --:--:-- --:--:--   109{"acknowledged":true,"shards_acknowledged":true,"index":"randysun"}
    
    

    image-20210927074957683

    删除索引

    curl -X DELETE 127.0.0.1:9200/randysun
    

    输出:

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100    21  100    21    0     0    138      0 --:--:-- --:--:-- --:--:--   138{"acknowledged":true}
    
    

    image-20210927075130500

    插入记录

    # 创建人
    curl -X PUT 127.0.0.1:9200/person
    
    # 插入数据
    curl -H "Content-type:application/json" -X POST 127.0.0.1:9200/user/person -d '
    {"name": "randysun", "age": 18, "married": false}'
    

    输出:

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   223  100   173  100    50    714    206 --:--:-- --:--:-- --:--:--   921{"_index":"user","_type":"person","_id":"X8SLJHwBe1myfLoa0OfX","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1}
    
    

    image-20210927080120572

    也可以使用PUT方法,但是需要传入id

    curl -H "Content-type:application/json" -X PUT 127.0.0.1:9200/user/person/4 -d '
    {
    	"name": "abc",
    	"age": 9,
    	"married": false
    }'
    

    检索

    Elasticsearch的检索语法比较特别,使用GET方法携带JSON格式的查询条件。

    全检索:

    curl -X GET 127.0.0.1:9200/user/person/_search
    
    {
        "took": 1121,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": {
                "value": 3,
                "relation": "eq"
            },
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "user",
                    "_type": "person",
                    "_id": "XcSKJHwBe1myfLoaducg",
                    "_score": 1.0,
                    "_source": {
                    }
                },
                {
                    "_index": "user",
                    "_type": "person",
                    "_id": "X8SLJHwBe1myfLoa0OfX",
                    "_score": 1.0,
                    "_source": {
                        "name": "randysun",
                        "age": 18,
                        "married": false
                    }
                }
            ]
        }
    }
    
    

    image-20210927080047060

    按条件检索:

    curl -H "ContentType:application/json" -X PUT 127.0.0.1:9200/user/person/4 -d '
    {
    	"query":{
    		"match": {"name": "sb"}
    	}	
    }'
    

    ElasticSearch默认一次最多返回10条结果,可以像下面的示例通过size字段来设置返回结果的数目。

    curl -H "ContentType:application/json" -X PUT 127.0.0.1:9200/user/person/4 -d '
    {
    	"query":{
    		"match": {"name": "sb"},
    		"size": 2
    	}	
    }'
    

    Go操作Elasticsearch

    elastic client

    我们使用第三方库https://github.com/olivere/elastic来连接ES并进行操作。

    注意下载与你的ES相同版本的client,例如我们这里使用的ES是7.2.1的版本,那么我们下载的client也要与之对应为github.com/olivere/elastic/v7

    使用go.mod来管理依赖:

    require (
        github.com/olivere/elastic/v7 v7.0.4
    )
    

    简单示例:

    package main
    
    import (
    	"context"
    	"fmt"
    
    	"github.com/olivere/elastic/v7"
    )
    
    // Elasticsearch demo
    
    type Person struct {
    	Name    string `json:"name"`
    	Age     int    `json:"age"`
    	Married bool   `json:"married"`
    }
    
    func main() {
    	client, err := elastic.NewClient(elastic.SetURL("http://192.168.1.7:9200"))
    	if err != nil {
    		// Handle error
    		panic(err)
    	}
    
    	fmt.Println("connect to es success")
    	p1 := Person{Name: "rion", Age: 22, Married: false}
    	put1, err := client.Index().
    		Index("user").
    		BodyJson(p1).
    		Do(context.Background())
    	if err != nil {
    		// Handle error
    		panic(err)
    	}
    	fmt.Printf("Indexed user %s to index %s, type %s\n", put1.Id, put1.Index, put1.Type)
    }
    

    更多使用详见文档:https://godoc.org/github.com/olivere/elastic

    image-20210927082758818

    image-20210928085706523

    在当下的阶段,必将由程序员来主导,甚至比以往更甚。
  • 相关阅读:
    仓位管理 – 1.理论篇
    作为首席架构师,我是如何选择并落地架构方案的?
    asp.net MVC 应用程序的生命周期
    微服务架构优缺点
    一位同事对 Rafy 框架的一些建议及我的回复
    .NET 版本区别,以及与 Windows 的关系
    MIS性能优化常见问题与方案(辅助项目组性能优化的总结贴)
    何时使用静态 API
    2011奥斯卡最佳纪录片《监守自盗(Inside Job)》小结
    Rafy 框架
  • 原文地址:https://www.cnblogs.com/randysun/p/15676137.html
Copyright © 2011-2022 走看看