• ElasticSearch安装及使用


    ElasticSearch安装及使用

    ELK由Elasticsearch、Logstash和Kibana三部分组件组成。

    Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

    Logstash 是一个完全开源的工具,它可以对你的日志进行收集、分析,并将其存储供以后使用。

    kibana 是一个开源和免费的工具,它可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。

    本文将用本地安装模式安装集群, 如果有条件,请使用云平台如AWS上的服务。

    我的环境是Ubuntu16.04, 并且安装了Java环境, ElasticSearch是由Java开发的哦。

    一.安装ElasticSearch

    1.1 单机运行

    官网下载tar包:

    # 解压
    tar -zxvf elasticsearch-6.1.0.tar.gz
    
    # 新建文件夹
    mkdir -p $HOME/escluster
    
    # 移动到我们的新文件夹中
    mv elasticsearch-6.1.0 $HOME/escluster/es1
    
    # 尝试单机运行
    cd $HOME/escluster/es1
    ./bin/elasticsearch -V
    
    ./bin/elasticsearch
    

    打开http://127.0.0.1:9200 可以观察是否成功.

    测试:

    curl -XPUT 'http://localhost:9200/twitter/doc/1?pretty' -H 'Content-Type: application/json' -d '
    {
        "user": "kimchy",
        "post_date": "2009-11-15T13:12:00",
        "message": "Trying out Elasticsearch, so far so good?"
    }'
    
    curl -XGET 'http://localhost:9200/twitter/doc/1?pretty=true'
    

    1.2 Docker安装老版本

    Dockerfile

    FROM elasticsearch:2.3
    RUN plugin install mobz/elasticsearch-head
    EXPOSE 9200
    EXPOSE 9300
    
    docker build -t es-me .
    docker run -d --name es --restart always  -v $PWD/data:/usr/share/elasticsearch/data:rw -p 9200:9200 -p 9300:9300 es-me
    

    打开http://127.0.0.1:9200/_plugin/head/

    1.2 Docker安装新版本

    Dockerfile:

    FROM elasticsearch:5.6
    EXPOSE 9200
    EXPOSE 9300
    

    docker-compose.yaml

    version: '2'
    services:
      elas:
        restart: always
        image: elasticsearch:5.5
        ports:
          - "9200:9200"
          - "9300:9300"
        volumes:
          - "/home/superpika/data:/usr/share/elasticsearch/data:rw"
    
    docker-compose up
    

    现在可以请求127.0.0.1:9200

    1.3 集群安装

    简单使用请参见上面。

    ElasticSearch ELK日志分析。

    我们要搭建集群, 因为ElasticSearch是分布式全文搜索引擎。

    安装包下有很多目录:

    目录 作用
    bin 主要是各种启动命令
    config 主要存放配置文件
    data 该节点的索引存放目录, 可改
    lib es依赖的一些依赖包
    logs 日志存放目录, 可改
    plugins es强大的插件系统

    我们在本机装个两个节点的集群.

    我们修改elasticsearch.yml来做集群, 相关解释已经在注释中, 部分参考ElasticSearch单机双实例的配置方法.

    cd $HOME/escluster/es1
    vim config/elasticsearch.yml 
    
    # ---------------------------------- Cluster -----------------------------------
    #
    # Use a descriptive name for your cluster: 标明了整个集群的名字,只有节点在相同的集群在能互相发现。
    #
    cluster.name: my-application
    #
    # ------------------------------------ Node ------------------------------------
    #
    # Use a descriptive name for the node: 当前节点名称的标识,各个节点的名称不能重复, 切记!
    #
    node.name: node-1
    #
    # Add custom attributes to the node:
    #
    #node.attr.rack: r1
    #
    # ----------------------------------- Paths ------------------------------------
    #
    # Path to directory where to store the data (separate multiple locations by comma):
    # 新建文件夹, 将数据和日志定位到$HOME/testes中
    # sudo mkdir /app/testes
    # 将该文件夹赋予执行ES的用户 
    # sudo chown superpika testes
    # sudo chgrp superpika testes
    # 不同节点node的保存路径应该不一样
    # mkdir /app/testes/node1
    # mkdir /app/testes/node2
    # 下面必须写全路径
    path.data: /app/testes/node1/data
    #
    # Path to log files:
    #
    path.logs: /app/testes/node1/logs
    #
    # ----------------------------------- Memory -----------------------------------
    #
    # Lock the memory on startup:
    #
    #bootstrap.memory_lock: true
    #
    # Make sure that the heap size is set to about half the memory available
    # on the system and that the owner of the process is allowed to use this
    # limit.
    #
    # Elasticsearch performs poorly when the system is swapping the memory.
    #
    # ---------------------------------- Network -----------------------------------
    #
    # Set the bind address to a specific IP (IPv4 or IPv6): 指定为本机IP, 否则可能导致外部无法访问
    #
    network.host: 127.0.0.1
    #
    # Set a custom port for HTTP: 节点间通信端口, 节点在不同机器可以一样, 但单机模拟集群, 不能一样
    #
    http.port: 9200
    transport.tcp.port: 9300
    
    # 本地集群必须设置, 切记!!!
    # 这个配置限制了单节点上可以开启的ES存储实例的个数,我们需要开多个实例,因此需要把这个配置写到配置文件中,并为这个配置赋值为2或者更高。
    node.max_local_storage_nodes: 2
    #
    # For more information, consult the network module documentation.
    #
    # --------------------------------- Discovery ----------------------------------
    #
    # Pass an initial list of hosts to perform discovery when new node is started:
    # The default list of hosts is ["127.0.0.1", "[::1]"]
    #
    # 由于到了2.x版本之后,ES取消了默认的广播模式来发现master节点,需要使用该配置来指定发现master节点。这个配置在单机双实例的配置中需要特别注意下,因为习惯上我们配置时并未指定master节点的tcp端口,如果实例的transport.tcp.port配置为9301,那么实例启动后会认为discovery.zen.ping.unicast.hosts中指定的主机tcp端口也是9301,可能导致这些节点无法找到master节点。因此在该配置中需要指定master节点提供服务的tcp端口。
    #discovery.zen.ping.unicast.hosts: ["host1", "host2"]
    discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9301"]
    
    # es配置当前集群中最少的主节点数,对于多于两个节点的集群环境,建议配置大于1。我们的节点目前没有多于两个, 所以不设置
    # discovery.zen.minimum_master_nodes: 2
    #
    # Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):
    #
    #discovery.zen.minimum_master_nodes: 
    #
    # For more information, consult the zen discovery module documentation.
    #
    # ---------------------------------- Gateway -----------------------------------
    #
    # Block initial recovery after a full cluster restart until N nodes are started:
    #
    #gateway.recover_after_nodes: 3
    #
    # For more information, consult the gateway module documentation.
    #
    # ---------------------------------- Various -----------------------------------
    #
    # Require explicit names when deleting indices:
    #
    #action.destructive_requires_name: true
    

    我们再拷贝一份:

    cp -r $HOME/escluster/es1 $HOME/escluster/es2
    

    将另一份的配置改为:

    path.data: /app/testes/node1/data改为path.data: /app/testes/node2/data,
    path.logs: /app/testes/node1/logs改为path.logs: /app/testes/node2/logs,
    node.name: node-1改为node.name: node-2,
    http.port: 9200改为http.port: 9201,
    transport.tcp.port: 9300改为transport.tcp.port: 9301

    跑起来(跑起来后关掉一个再连, 集群还会保持):

    $HOME/escluster/es1/bin/elasticsearch -d
    $HOME/escluster/es2/bin/elasticsearch -d
    

    访问: http://127.0.0.1:9200http://127.0.0.1:9201

    GET 127.0.0.1:9200/_cluster/health
    

    PS: 也可以不复制整个安装包成两份, 只需复制两份配置, 然后更改配置, 运行:

    $HOME/escluster/es1/bin/elasticsearch -Des.path.conf=config/instance1 -d -p /tmp/elasticsearch_1.pid
    $HOME/escluster/es1/bin/elasticsearch -Des.path.conf=config/instance2 -d -p /tmp/elasticsearch_2.pid
    

    更多参考: ElasticSearch源码地址

    1.4 脑裂问题

    参考: http://blog.csdn.net/cnweike/article/details/39083089

    正常情况下,集群中的所有的节点,应该对集群中master的选择是一致的,这样获得的状态信息也应该是一致的,不一致的状态信息,说明不同的节点对master节点的选择出现了异常——也就是所谓的脑裂问题。这样的脑裂状态直接让节点失去了集群的正确状态,导致集群不能正常工作。

    可能导致的原因:

    1. 网络:由于是内网通信,网络通信问题造成某些节点认为master死掉,而另选master的可能性较小;进而检查Ganglia集群监控,也没有发现异常的内网流量,故此原因可以排除。
    2. 节点负载:由于master节点与data节点都是混合在一起的,所以当工作节点的负载较大(确实也较大)时,导致对应的ES实例停止响应,而这台服务器如果正充当着master节点的身份,那么一部分节点就会认为这个master节点失效了,故重新选举新的节点,这时就出现了脑裂;同时由于data节点上ES进程占用的内存较大,较大规模的内存回收操作也能造成ES进程失去响应。所以,这个原因的可能性应该是最大的。

    应对问题的办法:

    1.对应于上面的分析,推测出原因应该是由于节点负载导致了master进程停止响应,继而导致了部分节点对于master的选择出现了分歧。为此,一个直观的解决方案便是将master节点与data节点分离。为此,我们添加了三台服务器进入ES集群,不过它们的角色只是master节点,不担任存储和搜索的角色,故它们是相对轻量级的进程。可以通过以下配置来限制其角色:

    node.master: true  
    node.data: false  
    

    当然,其它的节点就不能再担任master了,把上面的配置反过来即可。这样就做到了将master节点与data节点分离。当然,为了使新加入的节点快速确定master位置,可以将data节点的默认的master发现方式由multicast修改为unicast, 这两种是ES的默认自动发现(Disovery):

    discovery.zen.ping.multicast.enabled: false  
    discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"]
    

    2.还有两个直观的参数可以减缓脑裂问题的出现:

    discovery.zen.ping_timeout(默认值是3秒):默认情况下,一个节点会认为,如果master节点在3秒之内没有应答,那么这个节点就是死掉了,而增加这个值,会增加节点等待响应的时间,从一定程度上会减少误判。

    discovery.zen.minimum_master_nodes(默认是1):这个参数控制的是,一个节点需要看到的具有master节点资格的最小数量,然后才能在集群中做操作。官方的推荐值是(N/2)+1,其中N是具有master资格的节点的数量(我们的情况是3,因此这个参数设置为2,但对于只有2个节点的情况,设置为2就有些问题了,一个节点DOWN掉后,你肯定连不上2台服务器了,这点需要注意)

    二.安装Kibana

    官网下载tar包.

    解压并修改配置

    tar -zxvf kibana-6.1.0-linux-x86_64.tar.gz 
    cd kibana-6.1.0-linux-x86_64
    vim config/kibana.yml
    
    elasticsearch.url: "http://127.0.0.1:9200"
    

    运行:

    bin/kibana
    
    # 后台运行
    
    nohup bin/kibana &
    

    打开: http://127.0.0.1:5601 即可.

    三.使用Logstash

    Logstash是一个数据分析软件,主要目的是分析log日志。整一套软件可以当作一个MVC模型,logstash是controller层,Elasticsearch是一个model层,kibana是view层。

    首先将数据传给logstash,它将数据进行过滤和格式化(转成JSON格式),然后传给Elasticsearch进行存储、建搜索的索引,kibana提供前端的页面再进行搜索和图表可视化,它是调用Elasticsearch的接口返回的数据进行可视化。logstash和Elasticsearch是用Java写的,kibana使用node.js框架。

    这里是全文重点.

    3.1 安装

    官网下载tar包.

    tar -zxvf logstash-6.1.0.tar.gz 
    cd logstash-6.1.0
    

    3.2 运行

    定义一个简单的示例日志收集处理配置logstash.conf:

    input { stdin { } }
    output {
      elasticsearch { hosts => ["127.0.0.1:9200"] }
      stdout { codec => rubydebug }
    }
    

    这里input从标准输入stdin接收日志, output将日志输出到elasticsearch, stdout.codecs是基于数据流的过滤器,它可以作为input,output的一部分配置。Codecs可以帮助你轻松的分割发送过来已经被序列化的数据。流行的codecs包括 json,msgpack,plain(text)。

    开始跑:

    bin/logstash -f logstash.conf
    
    > 随便打
    

    打开kibana来分析: http://127.0.0.1:5601/app/kibana#/management/kibana/index?_g=()

    接着可以打开Discover进行日志查看:

    也可以进Visualize进行Create a visualization操作:

    四. 笔记

    Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。

    在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:

    Relational DB -> Databases -> Tables -> Rows -> Columns
    Elasticsearch -> Indices   -> Types  -> Documents -> Fields
    

    Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。

    为了创建员工目录,我们将进行如下操作:

        为每个员工的文档(document)建立索引,每个文档包含了相应员工的所有信息。
        每个文档的类型为employee。
        employee类型归属于索引megacorp。
        megacorp索引存储在Elasticsearch集群中。
    

    实际上这些都是很容易的(尽管看起来有许多步骤)。我们能通过一个命令执行完成的操作(参见ES权威指南):

    PUT /megacorp/employee/1
    {
        "first_name" : "John",
        "last_name" :  "Smith",
        "age" :        25,
        "about" :      "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }
    
    
    GET /megacorp/employee/1
    HEAD /megacorp/employee/1
    GET /megacorp/employee/_search
    GET /_cluster/health
    

    在Elasticsearch中,每一个字段的数据都是默认被索引的。也就是说,每个字段专门有一个反向索引用于快速检索。而且,与其它数据库不同,它可以在同一个查询中利用所有的这些反向索引,以惊人的速度返回结果。

    文档在Elasticsearch中是不可变的——我们不能修改他们。

    在内部,Elasticsearch已经标记旧文档为删除并添加了一个完整的新文档。旧版本文档不会立即消失,但你也不能去访问它。Elasticsearch会在你继续索引更多数据时清理被删除的文档。

    update API。这个API似乎允许你修改文档的局部,但事实上Elasticsearch遵循与之前所说完全相同的过程,这个过程如下:

    1. 从旧文档中检索JSON
    2. 修改它
    3. 删除旧文档
    4. 索引新文档

    当使用 index API更新文档的时候,我们读取原始文档,做修改,然后将整个文档(wholedocument)一次性重新索引。最近的索引请求会生效——Elasticsearch中只存储最后被索引的任何文档。如果其他人同时也修改了这个文档,他们的修改将会丢失。

    比如:

    一天,老板决定做一个促销。瞬间,我们每秒就销售了几个商品。想象两个同时运行的web进程,两者同时处理一件商品的订单.

    web_1让stock_count 失效是因为web_2没有察觉到stock_count 的拷贝已经过期(译者注: web_1取数据,减一后更新了stock_count。可惜在web_1更新stock_count前它就拿到了数据,这个数据已经是过期的了,当web_2再回来更新stock_count时这个数字就是错的。这样就会造成看似卖了一件东西,其实是卖了两件,这个应该属于幻读。)。结果是我们认为自己确实还有更多的商品,最终顾客会因为销售给他们没有的东西而失望。

    变化越是频繁,或读取和更新间的时间越长,越容易丢失我们的更改。在数据库中,有两种通用的方法确保在并发更新时修改不丢失:

    悲观并发控制(Pessimistic concurrency control)

    这在关系型数据库中被广泛的使用,假设冲突的更改经常发生,为了解决冲突我们把访问区块化。典型的例子是在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行数据。

    乐观并发控制(Optimistic concurrency control):

    被Elasticsearch使用,假设冲突不经常发生,也不区块化访问,然而,如果在读写过程中数据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中,可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。

    Elasticsearch是分布式的。当文档被创建、更新或删除,文档的新版本会被复制到集群的其它节点。Elasticsearch即是同步的又是异步的,意思是这些复制请求都是平行发送的,并无序(out of sequence)的到达目的地。这就需要一种方法确保老版本的文档永远不会覆盖新的版本。上文我们提到index/get/delete 请求时,我们指出每个文档都有一个version号码,这个号码在文档被改变时加一。Elasticsearch使用这个 _version保证所有修改都被正确排序。当一个旧版本出现在新版本之后,它会被简单的忽略。

    409冲突:

    PUT	/website/blog/1?version=1
    

    更多查看https://www.gitbook.com/book/looly/elasticsearch-the-definitive-guide-cn

  • 相关阅读:
    有价值的终会被人发现和承认
    Sql中存在斜杠“/”怎么办?
    JSONObject和JSONArray(json-lib-2.4)的基本用法
    如何设定linux系统时间
    动态创建的文本框想要加上jQuery的datepicker功能变成日期选择控件该怎么办?
    如果$.ajax函数迟迟得不到响应,那么最有可能出错的地方是请求参数写错了
    Notepad2替代系统自带的记事本Notepad
    css属性与js中style对象的属性对应表
    day02_js学习笔记_01_js的简介、js的基本语法
    Eclipse/MyEclipse的快捷键以及文档注释、多行注释的快捷键
  • 原文地址:https://www.cnblogs.com/nima/p/11750999.html
Copyright © 2020-2023  润新知