Elastic_Stack

搜索引擎基础

倒排索引

  • 常见搜索引擎

    • 网页搜索引擎:百度、谷歌
    • 业务搜索引擎:商品搜索、订单搜索
    • 日志搜索引擎:运维查看日志
  • 应用:用户给定关键词,搜索引擎返回与关键词相关的结果

  • 关系:大数据与搜索引擎工程师之间的联系

    • 搜索引擎中的数据一般由大数据工程师实现存储
  • 过程

    • step1:用户提交搜索词

      大数据分析
      
    • step2:搜索引擎对用户的搜索词做分词

      • 搜索引擎会获取用户的输入,调用分词器对用户的搜索词进行分词
      • 大数据
      • 分析
    • step3:将爬取到的所有网页构建倒排索引,构建倒排索引库

      • 将每个网页中的每句话进行分词:将一个网页中所有词拆分出来

        网页编号网页的内容分词
        1大数据工业化应用大数据、工业化、应用
        2大数据与人工智能的关系大数据、人工智能、关系
        3大数据的应用场景大数据、应用、场景
      • 构建倒排索引

        网页 的id
        大数据1,2,3
        应用1,3
        人工智能2
      • 假设用户搜索:大数据分析

        • 根据用户查询的分词从倒排索引中返回所有相关的网页的id
        • 根据算法对所有网页进行评分排名
        • 3:90
        • 2:85
        • 1:70
    • 倒排索引概念

      • 传统索引:根据id查询内容
      • 倒排索引:根据内容查id
    • step4:根据用户的关键词分词的结果到索引库中进行匹配,返回所有相关的词对应的所有网页

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lr4QSWlb-1625579351303)(Elastic_Stack.assets/image-20210601113134425.png)]

实现框架

  • 传统的存储检索工具
    • 如果搜索引擎通过MySQL或者Oracle来实现能不能满足需求?

      • 答案:不能
    • 查询的条件:走索引的问题

      • 需求:不论用户查询的是什么内容,都要走索引返回
      • SQL:like %keyword%
    • 数据量的负载:关系型数据库的负载量很小

    • 需求:专业的搜索引擎工具

  • 专业的搜索引擎工具
    • Lucene:最早的搜索引擎工具
      • 优点:奠定了整个搜索索引的框架和核心思想
      • 缺点:不好用,接口比较复杂,学习和使用成本比较高,现在几乎看不到
    • Solr:基于Lucene封装的一个工具
      • 优点:接口相对变的好用了
      • 缺点:数据量大的情况,性能会差一些,高度依赖于ZK
    • ElasticSearch:吸收了前两代工具的特点,解决了对应的缺点问题
      • 接口【JSON】友好,主攻搜索引擎实现,其他所有的功能都通过插件来实现,自己实现集群管理
      • 自己实现了类似于ZK的分布式管理机制:Zen-discovery机制

ElasticSearch

介绍

  • 基本介绍
    • ELK官网:https://www.elastic.co/
    • ELK官网文档:https://www.elastic.co/guide/index.html
    • ELK中文手册:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
    • ELK中文社区:https://elasticsearch.cn/
  • Elastic Stack
    • ElasticSearch:搜索引擎工具
      • 分布式存储、分布式分析计算
    • Logstash:用于实现数据采集
      • 重量级数据采集,功能比Flume多:文件、数据流、数据库
      • 采集的功能非常完善,后来更新发展侧重数据ETL
    • Kibana:可视化工具
      • 专门为ES设计的可视化工具,搭配ES使用
    • Beats:轻量级数据采集
      • 功能相对来说单一化,简单并且性能很好
  • 应用
    • 所有搜索引擎的场景都可以使用Elastic Stack来实现
    • 主要的应用场景:日志搜索引擎
  • 特点
    • 分布式:高可用、扩展性、高性能的
    • NRT:近实时的分布式存储系统,数据从写入到读取之间会有1s延迟
    • 全文索引:任何东西写入ES以后,都会自动创建索引
  • 区别
    • Redis:实时、内存、NoSQL数据库、大数据量缓存
    • Hbase:实时、内存+磁盘、NoSQL数据库、大数据量持久性
    • Kafka:实时、内存+磁盘、消息队列、大数据量缓存
    • ES:近实时,内存+磁盘、全文索引、大数据量持久化

存储概念

  • Index:索引库

    • 所有数据都是存储在index中,用于构建索引的
    • 类似于:数据库或者命名空间的概念
      • Redis:数据库
      • Hbase:命名空间
  • Type:索引类型/索引表

    • 注意:ES从7.0开始取消了这个Type结构

      • 6.0开始:每个Index库只允许有一个Type
    • 问题:ES中的所有数据在物理上是直接存储在index中,但是逻辑上数据写入某个Index的某个Type中

      • 对于index而言,如果列名相同,会被认为是同一列数据

      • index:索引库:person

        • type:索引表:Sudent

          sid		sname		age[string]
          
        • type:索引表:Teacher

          tid		tname		age[int]
          
  • Document:文档

    • 就是ES中存储的一条数据,每一条数据就是一个document
    • 构成:documentId + data【每一列构成】
      • docuementId:可以自己指定,唯一标识一行,如果不给,ES会自动生成一个
        • 功能
          • 作为主键,唯一标识一行,有主键索引
          • 决定分区的规则:按照documentID的Hash值取余分区个数
    • 类比于Hbase
      • document = Rowkey的数据
      • documentID = rowkey
      • data【fields】 = Cell[]
    • document作为ES中的存储/索引的最小单元
      • 写:按照整个document写入
      • 读:索引返回的是整个document的数据
  • Fields:数据列

    • 就是以前讲的column,每一列的数据
    • 构建索引的最小单元:列,可以指定哪些列构建索引,哪些列不构建索引
  • Shard:分片

    • 就是分区,shards是index级别的,一个index可以有多个shard分区,不同的shard分区分布在不同的节点上
    • 默认每个index有1个分片
  • Replicas:副本

    • 为了保证分片高可用性,默认每个分片有1个副本,分片 + 副本不允许超过机器个数
    • 注意:副本的个数不包含分片,如果1个分片有2个副本,总共存储了3份
    • 角色
      • leader:对外提供读写
      • follower:与leader同步数据,如果leader故障,follower会选举新的leader
  • Mapping:列的映射

    • 用于实现对于整个Index的列的管理:实现列的定义
    • 列:名称、类型、是否构建索引、是否进行分词
  • Setting:配置管理

    • 用于管理index的架构配置管理

    • 管理分片和副本

      • 默认:一个分片、一个副本
      • 实现:多个分片多个副本
概念HDFSHbaseKafkaES
第一层划分目录NameSpace-Index
第二层划分文件TableTopicType【7.0开始没有这个结构】
存储分区分块:Block范围:Region分区:PartitionShard
分区安全副本机制WAL+副本机制【就近原则】副本机制【leader+Follower】副本机制:Replicas【leader+Follower】
存储单元-【行】Rowkey+Store【列】Segment【行:offset】docld+ data[fields]
架构主从架构:NN、DN主从架构:Master、RegionServer主从架构:Crontroler、Broker主从架构:Master + Worker
HA两个NN + ZK两个Master+ZKZKZen-discovery

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7nPaVAZt-1625579351313)(Elastic_Stack.assets/image-20210601140315727.png)]

小结

  • index :索引库 (类似于数据库的概念)
  • Type:索引类型/索引表
  • Document:文档 (ES中存储的一条数据) = documentld(唯一标识符)+date
  • Fields :数据列 (构建索引的最小单元:列)
  • Shard :分片(分区,它是index级别的,一个index可以有多个shard分区)
  • Repliacs :副本
  • Mapping : 列的映射 (用于实现对整个index的列的管理 列 : 名称,类型,是否构建索引,是否进行分词)
  • Setting :配置管理 (用于管理index的架构)

ES部署

需求及环境准备

  • 安装需求

    • ElasticSearch:分布式搜索引擎,三台都有,先装一台,然后分发
      • 没有可视化界面
    • ElasticSearch-Head:可视化ES工具,第一台机器安装即可
      • 类似于Kafka-eagle
    • IK分词器:中文解析分词器 ,三台都有
      • 默认只带英文分词器,普通中文分词器比较鸡肋,使用IK中文分词器
  • 环境准备

    • 严禁使用root用户
    • 先用root用户在三台机器创建ES的用户

      useradd itcast
      passwd itcast
      
      • 设置密码:itcast
    • 三台机器创建ES的目录

      mkdir -p /export/server/es
      chown -R itcast:itcast /export/server/es
      
    • 三台机器配置itcast用户的sudo权限

      visudo
      
      100行左右添加: 
      itcast    ALL=(ALL)       NOPASSWD: ALL
      
      • 以后使用管理员的命令时要加上sudo

        sudo vim /etc/profile
        
    • 三台机器使用itcast用户连接登录

    • 三台机器配置免秘钥

      ssh-keygen -t rsa
      ssh-copy-id node1
      ssh-copy-id node2
      ssh-copy-id node3
      
    • 修改三台资源配置

      sudo vi /etc/security/limits.conf
      #在文件的末尾添加以下内容,*号不能去掉
      
      * soft nofile 65536
      * hard nofile 131072
      * soft nproc 4096
      * hard nproc 4096
      
      sudo sed -i '/^#DefaultLimitNOFILE=/aDefaultLimitNOFILE=4096' /etc/systemd/system.conf 
      sudo sed -i '/^#DefaultLimitNPROC=/aDefaultLimitNPROC=4096' /etc/systemd/system.conf 
      
      #临时设置
      sudo  sysctl -w vm.max_map_count=262144
      #永久设置
      sudo vim /etc/sysctl.d/99-sysctl.conf
      #添加这一行
      vm.max_map_count=262144
      #检查是否成功
      sudo sysctl -a | grep "vm.max_map_count"
      
    • 断开重连所有会话

ES的分布式安装

  • 上传安装包到第一台机器的家目录下

    cd ~
    rz
    tar -zxvf elasticsearch-7.6.1-linux-x86_64.tar.gz -C /export/server/es/
    cd /export/server/es/
    
  • 修改核心配置文件

    cd /export/server/es/elasticsearch-7.6.1/
    vim config/elasticsearch.yml
    
    cluster.name: itcast-es
    node.name: node1
    path.data: /export/server/es/elasticsearch-7.6.1/data
    path.logs: /export/server/es/elasticsearch-7.6.1/log
    network.host: node1
    http.port: 9200
    discovery.seed_hosts: ["node1", "node2", "node3"]
    cluster.initial_master_nodes: ["node1", "node2"]
    bootstrap.system_call_filter: false
    bootstrap.memory_lock: false
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    
  • 修改JVM配置文件

    vim config/jvm.options 
    
    #22-23行:根据虚拟机的情况,给一半内存
    -Xms2g
    -Xmx2g
    
  • 分发

    cd /export/server/es/
    scp -r elasticsearch-7.6.1/ node2:$PWD
    scp -r elasticsearch-7.6.1/ node3:$PWD
    
  • 修改node2和node3的配置文件中的主机名

  • 启动三台ES

    cd /export/server/es/elasticsearch-7.6.1/
    /export/server/es/elasticsearch-7.6.1/bin/elasticsearch >>/dev/null 2>&1 &
    
    访问端口:9200
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G8Dl6lhg-1625579351313)(Elastic_Stack.assets/image-20210201115259345.png)]

es-head的安装

  • 安装依赖环境

    • 下载node js

      cd ~
      wget https://npm.taobao.org/mirrors/node/v8.1.0/node-v8.1.0-linux-x64.tar.gz
      tar -zxvf node-v8.1.0-linux-x64.tar.gz -C /export/server/es/
      
    • 创建链接

      sudo ln -s /export/server/es/node-v8.1.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
      sudo ln -s /export/server/es/node-v8.1.0-linux-x64/bin/node /usr/local/bin/node
      
    • 修改环境变量

      sudo vim /etc/profile
      
      export NODE_HOME=/export/server/es/node-v8.1.0-linux-x64
      export PATH=:$PATH:$NODE_HOME/bin
      
      source /etc/profile
      
    • 检查是否安装成功

      node -v
      npm -v
      
  • 上传到第一台机器解压

    cd ~
    rz
    tar -zxvf elasticsearch-head-compile-after.tar.gz -C /export/server/es/
    
  • 修改配置文件

    • 修改Gruntfile.js

      cd /export/server/es/elasticsearch-head
      vim Gruntfile.js
      
      #93行:ES-head的服务地址和端口
      hostname: 'node1',
      
    • 修改app.js

      cd /export/server/es/elasticsearch-head/_site
      vim app.js
      
      #4354行
      this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://node1:9200";
      
  • 启动

    cd /export/server/es/elasticsearch-head/node_modules/grunt/bin/
    #后台启动
    ./grunt server >/dev/null 2>&1 &
    #查看进程
    netstat -atunlp | grep 9100
    
  • 访问:http://node1:9100/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grgFyfYb-1625579351315)(Elastic_Stack.assets/image-20210129223141542.png)]

IK分词器的安装

  • 创建插件目录

    mkdir -p /export/server/es/elasticsearch-7.6.1/plugins/ik
    
  • 上传解压

    cd /export/server/es/elasticsearch-7.6.1/plugins/ik/
    rz
    unzip elasticsearch-analysis-ik-7.6.1.zip 
    rm -rf elasticsearch-analysis-ik-7.6.1.zip 
    
  • 分发

    cd /export/server/es/elasticsearch-7.6.1/plugins
    scp -r ik/ node2:$PWD
    scp -r ik/ node3:$PWD
    
  • 重启ES

    • 直接Kill

      /export/server/es/elasticsearch-7.6.1/bin/elasticsearch >>/dev/null 2>&1 &
      

VSCode集成ES插件

创建一个文件,要以.es结尾,用VScode打开这个文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88hTKXaT-1625579351315)(Elastic_Stack.assets/image-20210601140827567.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56aBinvK-1625579351316)(Elastic_Stack.assets/wps1.jpg)]

配置一下ES服务端地址

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fMuFpZPo-1625579351317)(Elastic_Stack.assets/image-20210201120848826.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbVf269W-1625579351317)(Elastic_Stack.assets/image-20210201120920639.png)]

  • 测试分词器

    --标准分词
    post _analyze 
    {
        "analyzer":"standard", 
        "text":"我爱你中国"
    }
    --IK分词
    post _analyze 
    {
        "analyzer":"ik_max_word", 
        "text":"我爱你中国"
    }
    

RESTful API

背景及索引构建

  • 背景

    • 基于招聘网站中招聘信息的数据检索
    • 需求:用户可以根据地区、经验、岗位名称、岗位描述等信息快速的检索用户想要的招聘数据
    • RestFul API
      • 主要应用于DDL
        • 创建、删除、修改索引库
      • ES基于基于HTTP请求方式来实现的
        • PUT:插入或者更新数据
        • POST:可以做各种写入操作请求
        • GET:读取数据
        • DELETE:用于删除
        • 都以JSON形式来实现数据的请求管理
  • 索引库管理

    • 列举

      GET _cat/indices
      
      • 查询当前所有的索引库

        • SQL:show databases
    • 创建job_idx索引库

      PUT /job_idx
      {
          "mappings": {
              "properties" : {
                  "area": { "type": "text", "store": true, "analyzer": "ik_max_word"},
                  "exp": { "type": "text", "store": true, "analyzer": "ik_max_word"},
                  "edu": { "type": "keyword", "store": true},
                  "salary": { "type": "keyword", "store": true},
                  "job_type": { "type": "keyword", "store": true},
                  "cmp": { "type": "text", "store": true, "analyzer": "ik_max_word"},
                  "pv": { "type": "keyword", "store": true},
                  "title": { "type": "text", "store": true, "analyzer": "ik_max_word"},
                  "jd": { "type": "text", "store": true, "analyzer": "ik_max_word"}
              }
          },
        "settings" : {
              "number_of_shards":5,
            "number_of_replicas" : 1
          }
      }
      
    • 运行结果

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R4ErvTrV-1625579351318)(Elastic_Stack.assets/image-20210602114014125.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCETO9p5-1625579351318)(Elastic_Stack.assets/image-20210602114130306.png)]

    • 查看

      GET /job_idx/_mapping
      GET /job_idx/_settings
      
    • 删除

      delete /job_idx
      

插入/更新/删除 DDL操作

  • 插入

    put /index/_doc/doc_id
    {
    	JSON:每一列的数据
    }
    
    PUT /job_idx/_doc/29097
    {
        "area": "深圳-南山区",
        "exp": "1年经验",
        "edu": "大专以上",
        "salary": "6-8千/月",
        "job_type": "实习",
        "cmp": "乐有家",
        "pv": "61.6万人浏览过  / 14人评价  / 113人正在关注",
        "title": "桃园 深大销售实习 岗前培训",
        "jd": "薪酬待遇】 本科薪酬7500起 大专薪酬6800起 以上无业绩要求,同时享有业绩核算比例55%~80% 人均月收入超1.3万 【岗位职责】 1.爱学习,有耐心: 通过公司系统化培训熟悉房地产基本业务及相关法律、金融知识,不功利服务客户,耐心为客户在房产交易中遇到的各类问题; 2.会聆听,会提问: 详细了解客户的核心诉求,精准匹配合适的产品信息,具备和用户良好的沟通能力,有团队协作意识和服务意识; 3.爱琢磨,善思考: 热衷于用户心理研究,善于从用户数据中提炼用户需求,利用个性化、精细化运营手段,提升用户体验。 【岗位要求】 1.18-26周岁,自考大专以上学历; 2.具有良好的亲和力、理解能力、逻辑协调和沟通能力; 3.积极乐观开朗,为人诚实守信,工作积极主动,注重团队合作; 4.愿意服务于高端客户,并且通过与高端客户面对面沟通有意愿提升自己的综合能力; 5.愿意参加公益活动,具有爱心和感恩之心。 【培养路径】 1.上千堂课程;房产知识、营销知识、交易知识、法律法规、客户维护、目标管理、谈判技巧、心理学、经济学; 2.成长陪伴:一对一的师徒辅导 3.线上自主学习平台:乐有家学院,专业团队制作,每周大咖分享 4.储备及管理课堂: 干部训练营、月度/季度管理培训会 【晋升发展】 营销【精英】发展规划:A1置业顾问-A6资深置业专家 营销【管理】发展规划:(入职次月后就可竞聘) 置业顾问-置业经理-店长-营销副总经理-营销副总裁-营销总裁 内部【竞聘】公司职能岗位:如市场、渠道拓展中心、法务部、按揭经理等都是内部竞聘 【联系人】 黄媚主任15017903212(微信同号)"
    }
    
    {
        "_index": "job_idx",
        "_type": "_doc",
        "_id": "29097",
        "_version": 1,
        "result": "created",
        "_shards": {
            "total": 2,
            "successful": 2,
            "failed": 0
        },
        "_seq_no": 0,
        "_primary_term": 1
    }
    
  • 更新

    POST /job_idx/_update/29097
    {
        "doc": {
            "salary": "15-20千/月"
        }
    }
    
  • 删除

    DELETE /job_idx/_doc/29097
    
  • BulkLoad

    • 上传文件到Linux中

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uzcwRkRh-1625579351319)(Elastic_Stack.assets/image-20210702144435776.png)]

    • 执行批量加载

      curl -H "Content-Type: application/json" -XPOST "node1:9200/job_idx/_bulk?pretty&refresh" --data-binary "@job_info.json"
      

查询 DML操作

  • 查询方式

    • 根据doc_id进行查询:类似于MySQL中根据主键进行查询
      • 类似于Hbase中基于rowkey查询
    • 使用查询器进行查询:各种查询器满足各种查询需求
      • QueryBuilder:Match、Term、Range
  • doc_id查询

    GET /job_idx/_search
    {
        "query": {
            "ids": {
                "values": ["46313"]
            }
        }
    }
    
  • 关键词查询

    • 职位描述中包含销售的数据

      GET  /job_idx/_search 
      {
          "query": {
              "match": {
                  "jd": "销售"
              }
          }
      }
      
    • 默认只显示10条,如果要显示多条,可以通过size标签实现

      GET  /job_idx/_search 
      {
          "query": {
              "match": {
                  "jd": "销售"
              }
          },
          "size":"100"
      }
      
    • 职位描述及岗位名称中包含销售

      GET  /job_idx/_search
      {
          "query": {
              "multi_match": {
                  "query": "销售",
                  "fields": ["title", "jd"]
              }
          }
      }
      
      • multi_match:多列字符串匹配查询器
  • 分页查询

    • from and size

      GET  /job_idx/_search
      {
          "from": 0,
          "size": 5,
          "query": {
              "multi_match": {
                  "query": "销售",
                  "fields": ["title", "jd"]
              }
          }
      }
      
      • 浅分页:类似于SQL中的limit M,N
        • from:从第几条开始显示,第一条的值为0
        • size:每一页的显示几条
      • 每次必须手动修改from的值
    • scroll

      • 深分页:第一次查询,会将整个所有数据放在内存中,从第二次开始就从内存中来自动遍历每页的数据

        • scroll = 1m :做深分页,将查询的结果保存在内存中1分钟
      • size:每一页显示多少条

      • 优点:自动进行翻页

      • 第一次

        GET /job_idx/_search?scroll=1m
        {
            "query": {
                "multi_match": {
                  "query": "销售",
                    "fields": ["title", "jd"]
              }
            },
            "size": 100
        }
        
      • 第二次开始

        GET _search/scroll?scroll=1m
        {
            "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAdFmZSaUhmZWJvVHphVTA0VWFXWGctLUEAAAAAAAAAGhZ2ZmYya3k4ZVNuNnAzbDBOTEttUV9BAAAAAAAAAB4WZlJpSGZlYm9UemFVMDRVYVdYZy0tQQAAAAAAAAAbFnZmZjJreThlU242cDNsME5MS21RX0EAAAAAAAAAHBZ2ZmYya3k4ZVNuNnAzbDBOTEttUV9B"
        }
        

Java API

环境准备

  • JobDetail:Java Bean对象,用于存储每一个职位的信息

    • 整个ES的读写都是以JSON形式实现的,不方便处理
    • 将数据封装在JobDetail对象,方便处理数据
  • JobFullTextService:封装的所有增删改查的接口,定义所有方法以及返回值

  • JobFullTextServiceImpl:真正的实现类,实现了所有增删改查的方法

  • JobFullTextServiceTest:测试工具类,用于测试实现类的方法是否可用

插入数据

  • 构建连接对象 RestHighLevelClient
restHighLevelClient = new RestHighLevelClient(RestClient.builder(
                new HttpHost("node1", 9200, "http")
                , new HttpHost("node2", 9200, "http")
                , new HttpHost("node3", 9200, "http")
        ));
  • 写入数据*

    • 调用index方法来写入ES

    • 构建IndexRequest对象

      • IndexRequest:写入数据必须构建的对象
        • .id:设置写入的doc_id
        • .source:设置写入的数据列
      //往ES中写入一条数据:JSON格式的数据
          @Override
          public void add(JobDetail jobDetail)  {
              //构建了一个索引请求器对象,用于写入,制定了请求器请求的索引库的名称
              IndexRequest indexRequest = new IndexRequest(JOB_IDX_NAME);
              //封装数据到请求器中:doc_Id + JSON数据
              //从参数的对象中获取id作为docId
              indexRequest.id(jobDetail.getId() +"");
              //将JavaBean对象转换为JSON字符串
              String jsonString = JSON.toJSONString(jobDetail);
              //将JSON数据加载到请求器中,指定数据为JSON格式
              indexRequest.source(jsonString, XContentType.JSON);
              try {
                  //客户端连接调用index方法实现写入:第一个参数是索引请求器
                  restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      }
      

小结

  • RestHighLevelClient :客户端连接对象

    • .index:写入方法 (第一个参数是索引请求器,RequestOptions.DEFAULT)
  • IndexRequst :写入请求器对象 new该对象的时候里面放索引库名称

    • .id (里面放docid,类型为string )
    • .source (指定数据格式 ,数据 )

查询数据

  • 调用get方法来查询某个docid对应的数据

  • 构建GetRequest对象

    • GetRequest:根据DOCID进行请求,读取某个Doc的数据
    //用于通过docId来查找数据
        @Override
        public JobDetail findById(long id) throws IOException {
            //构建一个Get请求器对象
            GetRequest getRequest = new GetRequest(JOB_IDX_NAME);
            //指定get请求器的docid
            getRequest.id(id+"");
            //客户端连接对象调用get方法来获取某个docId对应的数据:传递get请求器
            GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
            //将每一列对应的数据取出转换为JSON String
            String sourceAsString = documentFields.getSourceAsString();
            //将JSONString转换为JavaBean独享
            JobDetail jobDetail = JSON.parseObject(sourceAsString, JobDetail.class);
            return jobDetail;
        }
    

小结

  • GetRequest :get请求器对象,new的时候里面放索引库名称
    • .id :指定请求器的docid
  • RestHighLevelClient :客户端连接对象
    • .get :按照docId进行查询(第一个参数为get请求器,RequestOptions.DEFAULT)返回的对象类型为GetResponse
    • 在使用GetResponse对象的getSourceAsString方法,将数据转换为Json数据
  • 使用JSON的parseObject方法把json数据转为javebean对象

更新与删除

  • 更新数据

    • 调用update方法来实现

    • 构建UpdateRequest对象

      • UpdateRequest:用于构建一个更新的请求
      //实现更新,将新的数据替换老的数据
          @Override
          public void update(JobDetail jobDetail) throws IOException {
              //todo:1-先判断是否存在
              GetRequest getRequest = new GetRequest(JOB_IDX_NAME);
              getRequest.id(jobDetail.getId()+"");
              //判断是否存在
              boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
              //如果不存在,方法调用结束
              if(!exists) return;
              //构建更新请求器:索引库名 + 指定更新的docid
              UpdateRequest updateRequest = new UpdateRequest(JOB_IDX_NAME,jobDetail.getId()+"");
              //更新请求器加载新数据
              updateRequest.doc(JSON.toJSONString(jobDetail),XContentType.JSON);
              //调用客户端连接中的更新方法
              restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
          }
      
  • 删除数据

    • 调用delete方法来实现

    • 构建DeleteRequeset对象

      • DeleteRequest:用于实现删除请求
      //定义删除功能
          @Override
          public void deleteById(long id) throws IOException {
              //构建删除请求器
              DeleteRequest deleteRequest = new DeleteRequest(JOB_IDX_NAME);
              //添加指定删除的docid
              deleteRequest.id(id+"");
              //调用删除方法
              restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
          }
      

小结:

  • 更新 :更新得先判断是否存在该数据,
    • GetRequest :请求器对象 (索引库名称)
      • .id :(指定请求器的docid )
    • RestHighLevelClient:客户端连接对象
      • .exists : 判断是否存在的方法 (第一参数是GetRequest对象,RequestOptions.DEFAULT)返回一个布尔值
      • .update(UpdateRequest):实现更新操作
    • UpdateRequest:更新请求器对象 (索引库名称,更新的docId要string类型)
      • .doc(JSON字符串的更新数据)
  • 删除
    • RestHighLevelClient:客户端连接对象
      • .delete(DeleteRequest):实现删除操作
    • DeleteRequest:删除请求器
      • .id(docId)

关键词查询

  • 调用search方法

       @Override
        public List<JobDetail> searchByKeywords(String keywords) throws IOException {
            //todo:1-构建返回值对象
            List<JobDetail> lists = new ArrayList<>();
            //todo:2-根据搜索词查询符合的数据
            //构建Search的请求器
            SearchRequest searchRequest = new SearchRequest();
            //构建条件的建造器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            //构建一个符合需求的查询器
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "jd", "title");
    //        MatchQueryBuilder c1 = QueryBuilders.matchQuery(keywords, "jd");//关键词单列查询器,模糊查询,做分词
    //        TermQueryBuilder c2 = QueryBuilders.termQuery(keywords, "jd");//关键词单列查询器,精准查询,不做分词
    //        RangeQueryBuilder c3 = QueryBuilders.rangeQuery("age").gt("18").lt("30");//范围查询
    //        QueryBuilders.boolQuery().must(c2).must(c3).should(c1); //must代表并列,should表示或者,多条件组合查询
            //条件建造器加载查询器
            searchSourceBuilder.query(multiMatchQueryBuilder).size(100);
            //加载查询的条件
            searchRequest.source(searchSourceBuilder);
            //调用客户端连接的search方法,实现查询
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = search.getHits().getHits();
            for (SearchHit hit : hits) {
                //获取每一条数据,将数据的内容转换为JAVA Bean
                JobDetail jobDetail = JSON.parseObject(hit.getSourceAsString(), JobDetail.class);
                //将docId设置为id
                jobDetail.setId(Long.parseLong(hit.getId()));
                lists.add(jobDetail);
            }
          //todo:3-实现返回
            return lists;
        }
    
  • 重点内容:查询器的构建

    • QueryBuilders

小结

  • 构建返回值对象 List

  • RestHighLevelClient:客户端连接对象

  • SearchRequset :构建Search 请求器

  • SearchSourceBuilder : 构建条件的建造器

  • QueryBuilders.multiMatchQuery :构建一个符合需求的查询器

    • 查询器构建

      QueryBuilders.multiMatchQuery:多列模糊匹配查询
      QueryBuilders.matchQuery:单列模糊匹配
      QueryBuilders.termQuery:单列精准匹配
      QueryBuilders.rangeQuery:范围匹配
      QueryBuilders.boolQuery:条件查询器
      
  • 条件建造器加载查询器 => 建造器对象.query(查询器).size(查询显示数)

  • 加载查询条件 => 请求器对象.source(建造器对象)

  • 调用客户端的search方法 => 客户端对象.search(请求器对象,RequestOptions.DEFAULT) =>返回值为SearchResponse对象

  • 在调用SearchResponse对象的getHits方法,在调用getHits方法,得到所有数据内容为hit

  • 使用for循环遍历,使用JSON的parseObject方法 (在使用hit.getSourceAsString,javabean.class)

  • 在添加到List集合里

分页查询

浅分页查询

  • from and size

    /**
         * 实现浅分页查询
         * @param keywords :查询的关键词
         * @param pageNum : 就是从第几条开始查询,from
         * @param pageSize :每页显示几条,size
         * @return
         * @throws IOException
         */
        @Override
        public Map<String, Object> searchByPage(String keywords, int pageNum, int pageSize) throws IOException {
            SearchRequest searchRequest = new SearchRequest();
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "jd", "title");
            //建造器中指定查询器,指定from和size
            searchSourceBuilder.query(multiMatchQueryBuilder)
                    .from(pageNum)
                    .size(pageSize);
            searchRequest.source(searchSourceBuilder);
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //取的是第一层hits
            SearchHits hits = search.getHits();
            List<JobDetail> lists = new ArrayList<>();
            for (SearchHit hit : hits) {
                JobDetail jobDetail = JSON.parseObject(hit.getSourceAsString(), JobDetail.class);
                jobDetail.setId(Long.parseLong(hit.getId()));
                lists.add(jobDetail);
            }
            //构建返回值:返回值为Map集合
            Map<String, Object> result = new HashMap<>();
            //第一条数据:Key:total,Value:返回值的总条数
            result.put("total", hits.getTotalHits().value);
            //第二条数据:Key:content,Value:每条数据的List集合
            result.put("content", lists);
    
            return result;
        }
    
  • 深分页查询

    • 分为两步
    • step1:第一次运行
    • step2:第二次开始
    /**
         * 测试深分页
         * @param keywords :查询关键词
         * @param scrollId : 内存数据的id,第一次是没有,第二次开始根据这个id进行自动分页查询
         * @param pageSize :每页的大小
         * @return
         * @throws IOException
         */
        @Override
        public Map<String, Object> searchByScrollPage(String keywords, String scrollId, int pageSize) throws IOException {
            //构建返回值
            Map<String, Object> result = new HashMap<>();
            List<JobDetail> jobList = new ArrayList<>();
    
            try {
                SearchResponse searchResponse = null;
                //如果为null,这是第一次请求
                if(scrollId == null) {
                    // 1. 创建搜索请求
                    SearchRequest searchRequest = new SearchRequest(JOB_IDX_NAME);
                    // 2. 构建查询条件
                    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                    searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keywords, "title", "jd"));
                    // 3. 设置分页大小
                    searchSourceBuilder.size(pageSize);
                    // 4. 设置查询条件、并设置滚动快照有效时间
                    searchRequest.source(searchSourceBuilder);
                    //指定数据在内存中放置时间
                    searchRequest.scroll(TimeValue.timeValueMinutes(1));
                    // 5. 发起请求
                    //提交查询器
                    searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
                }
                //不是第一次,直接根据scrollid来查询
                else {
                    //构建深分页查询器,传递scrollid
                    SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
                    searchScrollRequest.scroll(TimeValue.timeValueMinutes(1));
                    //调用scroll实现深分页
                    searchResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
                }
    
                // 6. 迭代响应结果
                SearchHits hits = searchResponse.getHits();
                for (SearchHit hit : hits) {
                    JobDetail jobDetail = JSONObject.parseObject(hit.getSourceAsString(), JobDetail.class);
                    jobDetail.setId(Long.parseLong(hit.getId()));
                    jobList.add(jobDetail);
                }
                //第一条数据:数据的呃逆荣
                result.put("content", jobList);
                //第二条数据;scrollid
                result.put("scroll_id", searchResponse.getScrollId());
    
            }
            catch (IOException e) {
                e.printStackTrace();
            }
    
            return result;
    
        }
    

总结

插入:

  • RestHighLevelClient :客户端连接对象
    • .index:写入方法 (第一个参数是索引请求器,RequestOptions.DEFAULT)
  • IndexRequst :写入请求器对象 new该对象的时候里面放索引库名称
    • .id (里面放docid,类型为string )
    • .source (指定数据格式 ,数据 )

查询:

  • GetRequest :get请求器对象,new的时候里面放索引库名称
    • .id :指定请求器的docid
  • RestHighLevelClient :客户端连接对象
    • .get :按照docId进行查询(第一个参数为get请求器,RequestOptions.DEFAULT)返回的对象类型为GetResponse
    • 在使用GetResponse对象的getSourceAsString方法,将数据转换为Json数据
  • 使用JSON的parseObject方法把json数据转为javebean对象

更新 :更新得先判断是否存在该数据,

  • GetRequest :请求器对象 (索引库名称)
    • .id :(指定请求器的docid )
  • RestHighLevelClient:客户端连接对象
    • .exists : 判断是否存在的方法 (第一参数是GetRequest对象,RequestOptions.DEFAULT)返回一个布尔值
    • .update(UpdateRequest):实现更新操作
  • UpdateRequest:更新请求器对象 (索引库名称,更新的docId要string类型)
    • .doc(JSON字符串的更新数据)

删除:

  • RestHighLevelClient:客户端连接对象
    • .delete(DeleteRequest):实现删除操作
  • DeleteRequest:删除请求器
    • .id(docId)

关键词查询:(别人)

  • RestHighLevelClient:客户端连接对象

    • .search(SearchRequest)
  • SearchRequest:查询请求器

    • .source(SearchSourceBuilder):设置查询建造器
  • SearchSourceBuilder:查询建造器

    • .query(查询器):根据不同的需求设置不同的查询器
  • 查询器构建

    QueryBuilders.multiMatchQuery:多列模糊匹配查询
    QueryBuilders.matchQuery:单列模糊匹配
    QueryBuilders.termQuery:单列精准匹配
    QueryBuilders.rangeQuery:范围匹配
    QueryBuilders.boolQuery:条件查询器
    

    (自己总结)

  • 构建返回值对象 List

  • RestHighLevelClient:客户端连接对象

  • SearchRequset :构建Search 请求器

  • SearchSourceBuilder : 构建条件的建造器

  • QueryBuilders :查询器

    • .multiMatchQuery :构建一个符合需求的查询器

    • 查询器构建

      QueryBuilders.multiMatchQuery:多列模糊匹配查询
      QueryBuilders.matchQuery:单列模糊匹配
      QueryBuilders.termQuery:单列精准匹配
      QueryBuilders.rangeQuery:范围匹配
      QueryBuilders.boolQuery:条件查询器
      
  • 条件建造器加载查询器 => 建造器对象.query(查询器).size(查询显示数)

  • 加载查询条件 => 请求器对象.source(建造器对象)

  • 调用客户端的search方法 => 客户端对象.search(请求器对象,RequestOptions.DEFAULT) =>返回值为SearchResponse对象

  • 在调用SearchResponse对象的getHits方法,在调用getHits方法,得到所有数据内容为hit

  • 使用for循环遍历,使用JSON的parseObject方法 (在使用hit.getSourceAsString,javabean.class)

  • 在添加到List集合里

存储原理

基本角色

  • Master:主节点,负责接收客户端请求,实现集群管理和数据存储的功能

  • Worker:从节点,负责存储数据,接收客户端请求

  • Coordinator Node:中心调度节点

    • 谁接收的客户端请求,谁就是中心调度节点
    • 负责接收请求,转发处理请求,返回结果给客户端
  • 举例

    • 三台机器:node1,node2,node3
    • index:两个分区,每个分区有两个副本
      • shard0:p0 , r0 ,r0
      • shard1:p1,r1,r1

写入流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LqKMU1XS-1625579351319)(Elastic_Stack.assets/image-20210601142836253.png)]

  • step1:客户端请求第一条提交写入一条数据,第一台机器作为中心调度节点
    • 解析这个请求,判断是否是一个DDL请求,如果是,转发给Master
    • 如果不是,就根据分片规则,查询元数据,将这个请求转发给对应分区所在的primary shard【Leader副本】的节点
  • step2:中心调度节点发现这条数据要写入0分区,0分区的主副本在第三台,转发给第三台机器
  • step3:第三台机器接受写入请求,将数据写入p0,p0会将这个写入广播给所有r0,超过半数的r0写入成功,就直接返回写入成功
  • step4:第三台机器将写入结果返回给中心调度节点,中心调度节点将结果返回给客户端

读取流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3ZCK9sn-1625579351320)(Elastic_Stack.assets/image-20210601142857520.png)]

  • step1:客户端请求第三台提交读取一条数据,第三台机器作为中心调度节点

  • 读的方式一:直接读取某个docid的数据

    • 中心调度节点根据分片规则,将这个请求转发给对应的分区所在的节点
    • 对应分区查询这个docid对应的数据进行返回
  • 读到方式二:根据search来做query查询

    • 查询这个索引库所有分区的数据,将符合条件的结果全部返回到中心调度节点
    • 中心调度节点根据评分降序排序返回给客户端

物理存储

  • step1:先将数据写入分区对应buffer,内存区域,用于缓冲,这时候没有索引,数据不能被读取
  • step2:每隔1s,会将每个分区的buffer数据写入os cache
    • 会构建索引
    • 写入操作会记录在translog:也是存储在内存中,每隔一段时候同步磁盘
    • 现在的数据可以被读取到
  • step3:每隔半小时,将数据flush到磁盘文件:segment文件中
  • step4:将segment进行合并,将所有被标记删除和更新的数据真正的删除,产生新的segment

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PBsVabWo-1625579351320)(Elastic_Stack.assets/image-20210602154853697.png)]

ES SQL

需求

需求

对于所有ES中存储的数据,需要进行增删改查的处理的需求,使用SQL最方便能快速的进行开发和上手

设计

  • 所有ES的概念可以映射一张分布式的表的概念
  • 缺点
    • 没有免费或者开源的SQL开发工具
    • SQL语法支持的并不全面

测试

  • 查询所有职位信息

    GET /_sql?format=txt
    {
        "query": "SELECT * FROM job_idx limit 1"
    }
    
  • 转换为DSL

    • DSL:将SQL语法转换成每个独立的关键字
    GET /_sql/translate
    {
        "query": "SELECT * FROM job_idx limit 1"
    }
    
  • scroll分页

    --第一次
    GET /_sql?format=json
    {
        "query": "SELECT * FROM job_idx",
        "fetch_size": 10
    }
    --第二次开始
    GET /_sql?format=json
    {
        "cursor": "5/WuAwFaAXPkAURuRjFaWEo1VkdobGJrWmxkR05vQlFBQUFBQUFBQUF5RmpoSGVUUnZhWHBQVW5BMlpVbEhkV1JqVDNKYVdtY0FBQUFBQUFBQVB4WjZiM2xXTlhrNWIxRkVWMHR6ZVhGNVZsWlpNMmhSQUFBQUFBQUFBREVXT0VkNU5HOXBlazlTY0RabFNVZDFaR05QY2xwYVp3QUFBQUFBQUFCQUZucHZlVlkxZVRsdlVVUlhTM041Y1hsV1Zsa3phRkVBQUFBQUFBQUFNeFpYWTBWclRFaENTVkk1ZVVKYVNFeE5aR1ZKY1hKbv8PCQFmBGFyZWEBBGFyZWEBBHRleHQAAAABZgNjbXABA2NtcAEEdGV4dAAAAAFmA2VkdQEDZWR1AQdrZXl3b3JkAQAAAWYDZXhwAQNleHABBHRleHQAAAABZgJqZAECamQBBHRleHQAAAABZghqb2JfdHlwZQEIam9iX3R5cGUBB2tleXdvcmQBAAABZgJwdgECcHYBB2tleXdvcmQBAAABZgZzYWxhcnkBBnNhbGFyeQEHa2V5d29yZAEAAAFmBXRpdGxlAQV0aXRsZQEEdGV4dAAAAAL/AQ=="
    }
    --关闭
    POST /_sql/close
    {
        "cursor": "5/WuAwFaAXPkAURuRjFaWEo1VkdobGJrWmxkR05vQlFBQUFBQUFBQUF5RmpoSGVUUnZhWHBQVW5BMlpVbEhkV1JqVDNKYVdtY0FBQUFBQUFBQVB4WjZiM2xXTlhrNWIxRkVWMHR6ZVhGNVZsWlpNMmhSQUFBQUFBQUFBREVXT0VkNU5HOXBlazlTY0RabFNVZDFaR05QY2xwYVp3QUFBQUFBQUFCQUZucHZlVlkxZVRsdlVVUlhTM041Y1hsV1Zsa3phRkVBQUFBQUFBQUFNeFpYWTBWclRFaENTVkk1ZVVKYVNFeE5aR1ZKY1hKbv8PCQFmBGFyZWEBBGFyZWEBBHRleHQAAAABZgNjbXABA2NtcAEEdGV4dAAAAAFmA2VkdQEDZWR1AQdrZXl3b3JkAQAAAWYDZXhwAQNleHABBHRleHQAAAABZgJqZAECamQBBHRleHQAAAABZghqb2JfdHlwZQEIam9iX3R5cGUBB2tleXdvcmQBAAABZgJwdgECcHYBB2tleXdvcmQBAAABZgZzYWxhcnkBBnNhbGFyeQEHa2V5d29yZAEAAAFmBXRpdGxlAQV0aXRsZQEEdGV4dAAAAAL/AQ=="
    }
    
  • 条件检索

    GET /_sql?format=txt
    {
        "query": "select * from job_idx where MATCH(title, 'hadoop') or MATCH(jd, 'hadoop') limit 10"
    }
    

订单统计实现

  • 创建索引

    PUT /order_idx/
    {
        "mappings": {
            "properties": {
                "id": {
                    "type": "keyword",
                    "store": true
                },
                "status": {
                    "type": "keyword",
                    "store": true
                },
                "pay_money": {
                    "type": "double",
                    "store": true
                },
                "payway": {
                    "type": "byte",
                    "store": true
                },
                "userid": {
                    "type": "keyword",
                    "store": true
                },
                "operation_date": {
                    "type": "date",
                    "format": "yyyy-MM-dd HH:mm:ss",
                    "store": true
                },
                "category": {
                    "type": "keyword",
                    "store": true
                }
            }
        }
    }
    
    
  • 上传并导入测试数据

    curl -H "Content-Type: application/json" -XPOST "node1:9200/order_idx/_bulk?pretty&refresh" --data-binary "@order_data.json"
    
  • 基于DSL:统计每种支付方式的订单个数

    GET /order_idx/_search
    {
        "size": 0,
        "aggs": {
            "group_by_state": {
                "terms": {
                    "field": "payway"
                }
            }
        }
    }
    
  • 基于SQL:统计每种支付方式的订单个数

    GET /_sql?format=txt
    {
        "query": "select payway, count(*) as order_cnt from order_idx group by payway"
    }
    
  • 基于SQL:统计每个用户的订单个数和订单总金额

    GET /_sql?format=txt
    {
        "query": "select userid, count(1) as cnt, sum(pay_money) as total_money from order_idx group by userid"
    }
    

FileBeat

介绍

介绍:Beats:Elastic Stack中的一个组件,轻量级的数据采集的工具

  • FileBeat:专门用于实现数据文件采集的工具
    • 采集文件数据,类似于Flume:exec、taildir
  • PackageBeat:专门用于实现网络监听流量采集工具
    • 对网络数据传输的采集
  • MetricBeat:专门用于收集服务器性能指标的采集工具
    • CPU利用率、内存利用率
  • HeartBeat:专门用于监听服务可用性的信息采集工具
  • WindowsBeat:专门用于监听windows系统中产生的事件信息的采集工具

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Irx6fLJD-1625579351320)(Elastic_Stack.assets/image-20210603092851398.png)]

应用:专门用于实现轻量级的文件采集

功能:实现基于文件的数据采集

特点FileBeatFlumeLogstash
功能只能采集文件采集文件和网络端口文件、数据库、HDFS、Redis、网络
组件Input、OutputSource、Channel、SInkInput、Filter、Output
语言GoJavaJruby
优点轻量级,消耗资源最少对于大数据开发接口的完美支持,性能比较好全场景
缺点功能比较少特殊需求需要自定义开发,占用的资源比较多性能比价差,占用资源非常多,设计关注于数据的过滤处理
应用专门用于文件采集大数据系统中的网络和文件采集专门用于ES的数据采集,实现ETL,搭配Beats使用

对于大数据工程而言

  • 如果只采集文件,需要低消耗高性能:filebeat
  • 如果采集分布式网络端口或者文件比较多,比较复杂:Flume

安装以及开发规则

  • 安装

    • 使用文档:https://www.elastic.co/guide/en/beats/filebeat/current/index.html

    • 上传

      cd ~
      rz
      
    • 解压

      tar -zxvf filebeat-7.6.1-linux-x86_64.tar.gz -C /export/server/es/
      
  • 开发规则

    • 基本组件:所有的FileBeat的程序都有两个部分Input和Output组成

    • step1:开发一个配置文件

      • 定义Input:读取哪些文件的数据

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aIiEuBCa-1625579351321)(Elastic_Stack.assets/image-20210603095755427.png)]

      • 定义Output:将读取到的数据发送到哪个目标地中
        在这里插入图片描述

    • step2:运行文件即可

      • filebeat运行开发的配置文件即可

案例

  • 需求
    • 采集/home/itcast目录下所有以server.log开头的日志文件数据写入ES中

    • 数据源

[

  • 开发

    • 创建配置文件

      cd /export/server/es/filebeat-7.6.1-linux-x86_64/
      mkdir apps
      vim apps/logfile_to_es.filebeat
      
    • 定义input和output

      filebeat.inputs:
      - type: log
        enabled: true
        paths:
          - /home/itcast/server.log.*
      
      output.elasticsearch:
          hosts: ["node1:9200", "node2:9200", "node3:9200"]
      
  • 上传数据

    • 上传测试文件到/home/itcast目录下
  • 测试运行

    • 修改权限

      chmod go-w /export/server/es/filebeat-7.6.1-linux-x86_64/apps/logfile_to_es.filebeat 
      
    • 运行

      ./filebeat -c apps/logfile_to_es.filebeat -e
      
      • -c:指定要运行的配置文件
      • -e:表示执行
  • 查看结果

  • 查看数据

    GET /filebeat-7.6.1-2021.07.03-000001/_search
    
  • 实时导入数据:添加新的文件,观察是否能实时的采集

小结

  • 实现FileBeatas案例的测试开发
  • 注意:filebeat会自动记录采集的偏移量

解决多行合并问题

导入错误数据

  • 导入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0KigGZEY-1625579351323)(Elastic_Stack.assets/image-20210703102356129.png)]

  • 查看

    GET /filebeat-7.6.1-2021.07.03-000001/_search
    {
        "query": {
            "match": {
                "log.file.path": "/home/itcast/server.log.error"
            }
        }
    }
    
  • 问题

    • 错误日志被拆分为多行记录在ES中

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3TNLeY2-1625579351324)(Elastic_Stack.assets/image-20210603102101286.png)]

    • 原因:filebeat将文件中每一行作为ES中的一行

    • 实际需求:需要将错误日志的多行作为一条错误信息存储在ES中

  • 解决

    • 将多行错误日志解析时合并为一行
  • 开发

    vim apps/logfile_regex_to_es.filebeat
    
    filebeat.inputs:
    - type: log
      enabled: true
      paths:
        - /home/itcast/server.log.*
      multiline.pattern: '^\['
      multiline.negate: true
      multiline.match: after
    
    output.elasticsearch:
        hosts: ["node1:9200", "node2:9200", "node3:9200"]
    
    • multiline.pattern: ‘^[’:中括号开头的数据作为新的一行
    • multiline.negate: true:不符合的行进行合并
    • multiline.match: after:合并在上一行的后面
  • 测试运行

    • 删除FileBeat的元数据

      rm -rf data/registry/filebeat/*
      
    • 删除之前的数据ES中的数据

      delete /filebeat-7.6.1-2021.07.03-000001
      
    • 运行

      chmod go-w /export/server/es/filebeat-7.6.1-linux-x86_64/apps/logfile_regex_to_es.filebeat
      
      ./filebeat -c apps/logfile_regex_to_es.filebeat -e
      
    • 查看ES

      GET /filebeat-7.6.1-2021.06.03-000001/_search
      {
          "query": {
              "match": {
                  "log.file.path": "/home/itcast/server.log.error"
              }
          }
      }
      

Logstash

介绍

  • 介绍:ELK中的L组件:用于实现各种场景下数据采集的功能
  • 功能:全场景下的数据采集:核心特点,注重于数据的转换处理
  • 应用
    • FileBeat:对数据进行采集
    • |
    • Logstash:对FileBeat传递过来的数据进行处理,ETL
    • |
    • ElasticSearch:实现数据的存储和分析
    • |
    • Kibana:实现可视化报表和可视化分析
  • 特点
    • 优点:功能全面,可以实现数据的预处理,支持全场景的数据采集
    • 缺点:侧重于数据处理,性能较差,开发接口不友好,现在一般不用于做数据采集工具

安装及开发规则

  • 安装

    • 上传

      cd ~
      rz
      
    • 解压

      unzip logstash-7.6.1.zip -d /export/server/es/
      cd /export/server/es/logstash-7.6.1/
      
  • 开发规则

    • 文档:https://www.elastic.co/guide/en/logstash/current/index.html
    • 基本规则:所有的Logstash的程序都可以有三个部分Input、Filter【可选】、Output组成
    • step1:先开发一个文件,定义Input、Filter、Output
      • Input:定义从什么地方读取
        • https://www.elastic.co/guide/en/logstash/current/input-plugins.html
      • Filter:可选的,实现对Input的数据进行预处理
        • https://www.elastic.co/guide/en/logstash/current/filter-plugins.html
      • Output:定义将数据保存到什么地方
        • https://www.elastic.co/guide/en/logstash/current/output-plugins.html
    • step2:提交运行文件即可

采集stdin输出到stdout (监听用户的输入)

  • 需求:监听用户的输入,将用户的输入在命令行直接输出

  • 开发

    • 编辑文件

      cd /export/server/es/logstash-7.6.1/
      mkdir apps
      vim apps/stdin-stdout.json
      
    • 写入配置

      input { 
          stdin { } 
      } 
      
      output {
          stdout {} 
      }
      
  • 测试

    bin/logstash -f apps/stdin-stdout.json 
    
    • 选项:三个选项只能使用一个
      • -f:指定运行某个文件
      • -e:在命名行执行代码
      • -t:测试代码的语法是否正确
  • 结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdZMqThc-1625579351324)(Elastic_Stack.assets/image-20210603104331618.png)]

采集文件输出搭配stdout

  • 需求:实现Logstash采集文件输出到stdout

  • 开发

    vim apps/input-file-test.json 
    
    input{
        file{
            path => "/home/itcast/tomcat.log"
            type => "log"
            start_position => "beginning"
        }
    }
    output{
            stdout{
    			codec=>rubydebug
            }
    }
    
  • 测试

    bin/logstash -f apps/input-file-test.json
    
  • 结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJvTrUUh-1625579351325)(Elastic_Stack.assets/image-20210603104848220.png)]

采集MySQL输出到stdout

  • 需求:Logstash采集MySQL输出到stdout

    • 创建MySQL数据表

      create database test;
      use test;
      CREATE TABLE `wcresult` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `word` varchar(100) NOT NULL,
        `number` int(11) NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
    • 插入数据

      insert into wcresult values(null,'hadoop',8);
      insert into wcresult values(null,'hive',16);
      
  • 全量开发

    vim apps/input-jdbc1.json
    
    input {
      jdbc {
        jdbc_driver_library => "/home/itcast/mysql-connector-java-5.1.38.jar"
        jdbc_driver_class => "com.mysql.jdbc.Driver"
        jdbc_connection_string => "jdbc:mysql://node3:3306/test"
        jdbc_user => "root"
        jdbc_password => "123456"
        schedule => "*/1 * * * *"
        statement => "SELECT * from wcresult where number > 10;"
      }
    }
    
    output{
            stdout{
            codec=>rubydebug
            }
    }
    
  • 全量测试

    bin/logstash -f apps/input-jdbc1.json 
    
  • 增量开发

    vim apps/input-jdbc2.json
    
    input {
      jdbc {
        jdbc_driver_library => "/home/itcast/mysql-connector-java-5.1.38.jar"
        jdbc_driver_class => "com.mysql.jdbc.Driver"
        jdbc_connection_string => "jdbc:mysql://node3:3306/test"
        jdbc_user => "root"
        jdbc_password => "123456"
        use_column_value => true
        tracking_column => "id"
        schedule => "*/1 * * * *"
        statement => "SELECT * from wcresult where number > 10 and id > :sql_last_value;"
      }
    }
    
    output{
            stdout{
            codec=>rubydebug
            }
    }
    
  • 增量测试

    rm -rf /home/itcast/.logstash_jdbc_last_run
    bin/logstash -f apps/input-jdbc2.json 
    

采集FileBeats输出到ES

  • 需求:先用fileBeat采集文件,写入Logstash,再用Logstash写入ES

    • 数据格式

      90.224.57.84 						--ip地址
      - 
      - 
      [15/Apr/2020:00:27:19 +0800] 		--访问时间
      "POST 								--请求类型
      /report 							--请求页面路径
      HTTP/1.1" 							--协议
      404 								--返回状态
      21 									--返回字节大小
      "www.baidu.com" 					--请求地址
      "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4549.400 QQBrowser/9.7.12900"  --浏览器信息
      
  • 开发

    • step1:使用filebeat采集数据到Logstash

      cd /export/server/es/filebeat-7.6.1-linux-x86_64/
      vim apps/logfile_to_logstash.filebeat
      
      filebeat.inputs:
      - type: log
        enabled: true
        paths:
          - /home/itcast/access.*
        multiline.pattern: '^\d+\.\d+\.\d+\.\d+ '
        multiline.negate: true
        multiline.match: after
      
      output.logstash:
        enabled: true
        hosts: ["node1:45454"]
      
      chmod go-w apps/logfile_to_logstash.filebeat
      
    • step2:使用Logstash将数据采集到ES

      cd /export/server/es/logstash-7.6.1/
      vim apps/beats_to_es.json
      
      input {
          beats {
          port => 45454
      }
      }
      
      output {
          elasticsearch {
          hosts => [ "node1:9200","node2:9200","node3:9200"]
        }
      }
      
  • 测试

    • 删除元数据

      rm -rf /export/server/es/filebeat-7.6.1-linux-x86_64/data/registry/filebeat/*
      
    • 启动Logstash

      bin/logstash -f apps/beats_to_es.json
      
    • 启动Beats

      ./filebeat -c apps/logfile_to_logstash.filebeat -e
      
    • 上传测试数据access.log

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ea1eiWR8-1625579351325)(Elastic_Stack.assets/image-20210603112354181.png)]

  • 结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCB6r2kG-1625579351325)(Elastic_Stack.assets/image-20210603112342267.png)]

实现数据解析

  • Logstash插件

    • 列举所有插件

      bin/logstash-plugin list
      
    • GROK插件

      • 功能:正则匹配,从原始数据中将字段提取出来

      • 语法

        %{SYNTAX:SEMANTIC}
        
  • 需求:匹配日志中的所有常见字段,将每个字段提取写入ES

  • 开发

    vim apps/beats_grokall_console.json
    
    input {    beats {        port => 45454    }}filter {    grok {        match => {             "message" => "%{IP:ip} - - \[%{HTTPDATE:date}\] \"%{WORD:method} %{PATH:uri} %{DATA}\" %{INT:status} %{INT:length} \"%{DATA:reference}\" \"%{DATA:browser}\""         }    }   }output {    stdout {        codec => rubydebug  }}
    
  • 测试

    • 启动Logstash

      bin/logstash -f apps/beats_grokall_console.json
      
    • 删除元数据

      rm -rf /export/server/es/filebeat-7.6.1-linux-x86_64/data/registry/filebeat/*
      
    • 启动Filebeat

      ./filebeat -c apps/logfile_to_logstash.filebeat -e
      
  • 结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E54VMCYG-1625579351326)(Elastic_Stack.assets/image-20210603113021364.png)]

实现数据转换

  • 插件

    • mutate插件功能:实现字段添加、处理、重命名等
    • date插件功能:实现日期转换处理
  • 需求:转换日期格式并保留需要的字段写入ES

  • 开发

    vim apps/beats_mutate_date_es.json
    
    input {    beats {        port => 45454    }}filter {    grok {        match => {             "message" => "%{IP:ip} - - \[%{HTTPDATE:date}\] \"%{WORD:method} %{PATH:uri} %{DATA}\" %{INT:status:int} %{INT:length:int} \"%{DATA:reference}\" \"%{DATA:browser}\""         }    }    mutate {        enable_metric => "false"        remove_field => ["message", "log", "tags", "@timestamp", "input", "agent", "host", "ecs", "@version"]    }    date {        match => ["date","dd/MMM/yyyy:HH:mm:ss Z","yyyy-MM-dd HH:mm:ss"]        target => "date"    }}output {    stdout {        codec => rubydebug    }    elasticsearch {        hosts => ["node1:9200" ,"node2:9200" ,"node3:9200"]        index => "apache_web_log"    }}
    
  • 测试

    • 启动Logstash

      bin/logstash -f apps/beats_mutate_date_es.json
      
    • 删除元数据

      rm -rf /export/server/es/filebeat-7.6.1-linux-x86_64/data/registry/filebeat/*
      
    • 启动Filebeat

      ./filebeat -c apps/logfile_to_logstash.filebeat -e
      
  • 结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vR1Qn53T-1625579351326)(Elastic_Stack.assets/image-20210603113853249.png)]

其他案例

  • 采集用户输入输出到文件中

    • 编辑文件

      vim apps/output-file.json
      
      input {stdin{}}output {    file {        path => "/export/servers/es/logstash-6.0.0/usercase/datas/%{+YYYY-MM-dd}-%{host}.txt"        codec => line {            format => "%{message}"        }        flush_interval => 0    }}
      
    • 运行

      bin/logstash -f apps/output-file.json 
      
  • 采集用户输入输出到ES中

    • 编辑文件

      vim apps/output-es.json
      
      input {stdin{}}output {    elasticsearch {        hosts => ["node1:9200"]        index => "logstash-%{+YYYY.MM.dd}"    }}
      
    • 运行

      bin/logstash -f apps/output-es.json 
      
  • 采集文件的数据到Kafka中

    • 编辑文件

      vim apps/output-kafka.json
      
      input {        file{        path => "/home/es/tomcat.log"        type => "log"        start_position => "beginning"    }}output {    kafka {        topic_id => "bigdata"        bootstrap_servers => "node1:9092,node2:9092,node3:9092"        batch_size => 5   }}
      
    • 运行

      bin/logstash -f apps/output-kafka.json
      
  • 采集kafka数据到Es

    • 编辑文件

      vim apps/kafka-es.json
      
      input{
          kafka {
              group_id => "testLogstash"
              auto_offset_reset => "earliest"
              topics => ["bigdata"]
              bootstrap_servers => "node1:9092,node2:9092,node3:9092"
         }
      }
      output {
          elasticsearch {
              hosts => ["node1:9200"]
              index => "kakfatoes"
          }
      }
      
    • 运行

      bin/logstash -f apps/kafka-es.json
      

Kibana

介绍

  • 介绍:专门为ES设计的可视化工具

  • 功能:实现ES的可视化开发、查询、分析及数据报表的可视化

  • 应用:固定搭配ES来使用

安装

安装

  • 上传

    cd ~
    rz
    
  • 解压

    tar -zxvf kibana-7.6.1-linux-x86_64.tar.gz -C /export/server/es/
    cd /export/server/es/kibana-7.6.1-linux-x86_64/
    
  • 配置

    cd /export/server/es/kibana-7.6.1-linux-x86_64/
    vim config/kibana.yml
    
    # 7行:Kibana服务地址
    server.host: "node1"
    # 25行:修改显示名称
    server.name: "itcast-kibana"
    # 28行:修改es地址
    elasticsearch.hosts: ["http://node1:9200"]
    
  • 启动

    cd /export/server/es/kibana-7.6.1-linux-x86_64/
    bin/kibana >>/dev/null 2>&1 &
    
  • 查看

    #查看进程
    ps -ef | grep node
    #页面访问
    node1:5601
    

添加数据源及数据检索

添加数据源

[

指定条件检索

#查询包含zhihu的请求
*zhihu*
#查询页面不存在的请求
status : 404
#查询请求成功和不存在的请求
status: (404 or 200)
#查询方式为POST请求,并请求成功的日志
status: 200 and method: post
#查询方式为GET成功的请求,并且响应数据大于512的日志
status: 200 and method: get and length > 512
#查询请求成功的且URL为「/itcast.cn」开头的日志:注意:因为/为特殊字符,需要使用反斜杠进行转义
uri: "\/itcast.cn\/*"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvccFxdI-1625579351328)(Elastic_Stack.assets/image-20210202145857708.png)]

构建可视化报表

附录一:Maven依赖

<repositories>
    <repository>
        <id>aliyun</id>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
            <updatePolicy>never</updatePolicy>
        </snapshots>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.14.3</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <target>1.8</target>
                <source>1.8</source>
            </configuration>
        </plugin>
    </plugins>
</build>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This book teaches you how to install, configure and implement the Elastic Stack (Elasticsearch, Logstash and Kibana) – the invaluable tool for anyone deploying a centralized log management solution for servers and apps. Supported by Puppet and available with various plugins, Elastic Stack is the best option for your server log management. You will learn how to use and configure Elastic Stack independently and alongside Puppet. Each chapter includes real-world examples and practical troubleshooting tips, enabling you to get up and running with Elastic Stack in record time. Fully customizable and easy to use, Elastic Stack enables you to be on top of your servers all the time, and resolve problems for your clients as fast as possible. Get started with it using this book today. What You Will Learn How to install and configure Logstash How to use Logstash with Elasticsearch and Kibana How to use Logstash with Puppet and Foreman How to centralize data processing Who This Book Is For Beginning Elastic Stack is for anyone working on multiple servers who needs to search their logs using a web interface. It is ideal for server administrators who have just started their job and need to look after multiple servers efficiently. Table of Contents Chapter 1: Getting Started with Logstash Chapter 2: Getting Started with Elasticsearch Chapter 3: Getting Started with Kibana Chapter 4: Working with Remote Servers Chapter 5: Configuring Logstash for Services and System Logs Chapter 6: Graphite Monitoring and Graphs Chapter 7: Configuring Elasticsearch Watcher Chapter 8: Securing the ELK Stack with Shield Chapter 9: Logstash Plug-ins Chapter 10: Managing the ELK Stack with Puppet and Foreman

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值