ELK分页、分词器、分片交互、sql插件

文章目录

  • 9、分页解决方案
    • 1、导入数据
    • 2、size+from浅分页
    • 3、scroll深分页
  • 10、三台机器安装IK分词器
    • 1、安装
    • 2、配置
    • 3、查看分词效果
    • 4、插入测试数据
    • 5、热词更新
      • 1、node03配置Tomcat
      • 2、 三台机器修改配置文件
      • 3、 三台机器修改JDK权限
      • 4、三台机器重新启动es
  • 11、分片交互过程
    • 1、创建索引
    • 2、删除索引
    • 3、查询索引
  • 13、elasticsearch 的sql插件使用
    • 第一种方式:通过rest风格实现数据的查询
    • 第二种方式:使用sql脚本的方式进入sql客户端进行查询
    • 第三种方式:通过jdbc连接的方式

9、分页解决方案

1、导入数据

DELETE us
POST /_bulk
{ "create": { "_index": "us", "_type": "tweet", "_id": "1" }}
{ "email" : "[email protected]", "name" : "John Smith", "username" : "@john" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "2" }}
{ "email" : "[email protected]", "name" : "Mary Jones", "username" : "@mary" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "3" }}
{ "date" : "2014-09-13", "name" : "Mary Jones", "tweet" : "Elasticsearch means full text search has never been so easy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "4" }}
{ "date" : "2014-09-14", "name" : "John Smith", "tweet" : "@mary it is not just text, it does everything", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "5" }}
{ "date" : "2014-09-15", "name" : "Mary Jones", "tweet" : "However did I manage before Elasticsearch?", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "6" }}
{ "date" : "2014-09-16", "name" : "John Smith",  "tweet" : "The Elasticsearch API is really easy to use", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "7" }}
{ "date" : "2014-09-17", "name" : "Mary Jones", "tweet" : "The Query DSL is really powerful and flexible", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "8" }}
{ "date" : "2014-09-18", "name" : "John Smith", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "9" }}
{ "date" : "2014-09-19", "name" : "Mary Jones", "tweet" : "Geo-location aggregations are really cool", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "10" }}
{ "date" : "2014-09-20", "name" : "John Smith", "tweet" : "Elasticsearch surely is one of the hottest new NoSQL products", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "11" }}
{ "date" : "2014-09-21", "name" : "Mary Jones", "tweet" : "Elasticsearch is built for the cloud, easy to scale", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "12" }}
{ "date" : "2014-09-22", "name" : "John Smith", "tweet" : "Elasticsearch and I have left the honeymoon stage, and I still love her.", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "13" }}
{ "date" : "2014-09-23", "name" : "Mary Jones", "tweet" : "So yes, I am an Elasticsearch fanboy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "14" }}
{ "date" : "2014-09-24", "name" : "John Smith", "tweet" : "How many more cheesy tweets do I have to write?", "user_id" : 1 }

2、size+from浅分页

按照一般的查询流程来说,如果我想查询前10条数据:
•1 客户端请求发给某个节点
•2 节点转发给个个分片,查询每个分片上的前10条
•3 结果返回给节点,整合数据,提取前10条
•4 返回给请求客户端
from定义了目标数据的偏移值,size定义当前返回的事件数目

GET /us/_search?pretty
{
  "from" : 0 , "size" : 5
}

GET /us/_search?pretty
{
  "from" : 5 , "size" : 5
}

这种浅分页只适合少量数据,因为随from增大,查询的时间就会越大,而且数据量越大,查询的效率指数下降
优点:from+size在数据量不大的情况下,效率比较高
缺点:在数据量非常大的情况下,from+size分页会把全部记录加载到内存中,这样做不但运行速递特别慢,而且容易让es出现内存不足而挂掉

3、scroll深分页

对于上面介绍的浅分页,当Elasticsearch响应请求时,它必须确定docs的顺序,排列响应结果。
如果请求的页数较少(假设每页20个docs), Elasticsearch不会有什么问题,但是如果页数较大时,比如请求第20页,Elasticsearch不得不取出第1页到第20页的所有docs,再去除第1页到第19页的docs,得到第20页的docs。
解决的方式就是使用scroll,scroll就是维护了当前索引段的一份快照信息–缓存(这个快照信息是你执行这个scroll查询时的快照)。
可以把 scroll 分为初始化和遍历两步:
1、初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照;
2、遍历时,从这个快照里取数据;
初始化

GET us/_search?scroll=3m
{ 
"query": {"match_all": {}},
 "size": 3
}

初始化的时候就像是普通的search一样
其中的scroll=3m代表当前查询的数据缓存3分钟
Size:3 代表当前查询3条数据
遍历
在遍历时候,拿到上一次遍历中的scrollid,然后带scroll参数,重复上一次的遍历步骤,知道返回的数据为空,就表示遍历完成

GET /_search/scroll
{
  "scroll" : "1m",
  "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAPXFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIxZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlBAAAAAAAAA9oWTVZOdHJ2cXBSOU9wN3c1dk5vcWd4QQAAAAAAAAPYFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIhZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlB"
}

【注意】:每次都要传参数scroll,刷新搜索结果的缓存时间,另外不需要指定index和type(不要把缓存的时时间设置太长,占用内存)
对比
浅分页,每次查询都会去索引库(本地文件夹)中查询pageNum*page条数据,然后截取掉前面的数据,留下最后的数据。 这样的操作在每个分片上都会执行,最后会将多个分片的数据合并到一起,再次排序,截取需要的。
深分页,可以一次性将所有满足查询条件的数据,都放到内存中。分页的时候,在内存中查询。相对浅分页,就可以避免多次读取磁盘。

10、三台机器安装IK分词器

我们在搜索的时候,都会对数据进行分词,英文的分词很简单,我们可以直接按照空格进行切分即可,但是中文的分词太过复杂,例如:夏天太热,能穿多少穿多少,冬天太冷,能穿多少穿多少。下雨地滑,还好我一把把车把把住了,才没有摔倒。人要是行,干一行行一行,一行行行行行等等的分词都是非常麻烦的,所以针对中文的分词,专门出了一个叫做IK的分词器来解决对中文的分词问题。

1、安装

每台机器都要配置。配置完成之后,需要重启ES服务
将安装包上传到node01机器的/home/es路径下

cd /home/es
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.7.0/elasticsearch-analysis-ik-6.7.0.zip
# 将ik分词器的插件,上传到/home/es目录下 
cd /home/es 
mkdir  /export/servers/es/elasticsearch-6.7.0/plugins/analysis-ik/
unzip elasticsearch-analysis-ik-6.0.0.zip -d /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/

将安装包分发到其他机器上
node01机器执行以下命令进行安装包的分发

cd /export/servers/es/elasticsearch-6.0.0/plugins
scp -r analysis-ik/ node02:$PWD
scp -r analysis-ik/ node03:$PWD
# 三台机器都配置完成
# 配置完成之后,需要重启ES服务。

三台机器重启es服务
三台机器执行以下命令停止es服务


nohup /export/servers/es/elasticsearch-6.0.0/bin/elasticsearch >/dev/null 2>&1 &

2、配置

delete iktest
PUT /iktest?pretty
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "ik" : {
                    "tokenizer" : "ik_max_word"
                }
            }
        }
    },
    "mappings" : {
        "article" : {
            "dynamic" : true,
            "properties" : {
                "subject" : {
                    "type" : "text",
                    "analyzer" : "ik_max_word"
                }
            }
        }
    }
}

说明:ik带有两个分词器:
•ikmaxword :会将文本做最细粒度的拆分;尽可能多的拆分出词语
句子:我爱我的祖国
结果: 我|爱|我的|祖|国|祖国
•ik_smart:会做最粗粒度的拆分;已被分出的词语将不会再次被其它词语占有
句子:我爱我的祖国
结果: 我|爱|我|的|祖国

3、查看分词效果

  GET _analyze?pretty
  {
    "analyzer": "ik_max_word",
    "text": "希拉里是个妹子"
  }

4、插入测试数据

POST /iktest/article/_bulk?pretty
{ "index" : { "_id" : "1" } }
{"subject" : ""闺蜜"崔顺实被韩检方传唤 韩总统府促彻查真相" }
{ "index" : { "_id" : "2" } }
{"subject" : "韩举行"护国训练" 青瓦台:决不许国家安全出问题" }
{ "index" : { "_id" : "3" } }
{"subject" : "媒体称FBI已经取得搜查令 检视希拉里电邮" }
{ "index" : { "_id" : "4" } }
{"subject" : "村上春树获安徒生奖 演讲中谈及欧洲排外问题" }
{ "index" : { "_id" : "5" } }
{"subject" : "希拉里团队炮轰FBI 参院民主党领袖批其”违法”" }

查看分词器
对"希拉里和韩国"进行分词查询
ikmaxword分词后的效果:希|拉|里|希拉里|和|韩国
POST /iktest/article/_search?pretty
{
“query” : { “match” : { “subject” : “希拉里和韩国” }},
“highlight” : {
“pre_tags” : [""],
“post_tags” : ["
"],
“fields” : {
“subject” : {}
}
}
}

5、热词更新

查看分词效果

  GET _analyze?pretty
  {
    "analyzer": "ik_max_word",
    "text": "传智播客在哪里"
  }

1、node03配置Tomcat

使用es用户来进行配置tomcat,此处我们将tomcat装在node03机器上面即可

cd /home/es
tar -zxvf apache-tomcat-8.5.34.tar.gz -C /export/servers/es/

tomcat当中添加配置hot.dic

cd /export/servers/es/apache-tomcat-8.5.34/webapps/ROOT/
vi hot.dic 
传智播客
#启动tomcat
/export/servers/es/apache-tomcat-8.5.34/bin/startup.sh 

浏览器访问
wget http://node03:8080/hot.dic

2、 三台机器修改配置文件

三台机器都要修改es的配置文件(使用es用户来进行修改即可)
第一台机器node01修改es的配置

cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config
vim IKAnalyzer.cfg.xml


<properties>
        <comment>IK Analyzer 扩展配置comment>
        
        <entry key="ext_dict">entry>
         
        <entry key="ext_stopwords">entry>
        
        <entry key="remote_ext_dict">http://node03:8080/hot.dicentry>
        
        
properties>

修改完成之后拷贝到node02与node03机器上面去
node01执行以下命令进行拷贝

cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config
sudo scp IKAnalyzer.cfg.xml  node02:$PWD
sudo scp IKAnalyzer.cfg.xml  node03:$PWD

3、 三台机器修改JDK权限

三台机器修改jdk的权限问题
第一台机器执行以下命令修改jdk的权限问题

#修改JDK安全设置
cd /export/servers/jdk1.8.0_141/jre/lib/security
sudo vim java.policy

添加以下四行配置

 permission java.net.SocketPermission "192.168.52.120:8080","accept";
 permission java.net.SocketPermission "192.168.52.120:8080","listen";
 permission java.net.SocketPermission "192.168.52.120:8080","resolve";
 permission java.net.SocketPermission "192.168.52.120:8080","connect";

修改完成之后拷贝到第二台和第三台机器
node01执行以下命令拷贝到第二台和第三台

cd /export/servers/jdk1.8.0_141/jre/lib/security
sudo scp java.policy  node02:$PWD
sudo scp java.policy  node03:$PWD

http://mahilion.blog.163.com/blog/static/1830872952012101225243655/

4、三台机器重新启动es

三台机器重新启动es服务,三台机器先使用kill -9杀死es的服务,然后再执行以下命令进行重启

cd /export/servers/es/elasticsearch-6.0.0/
nohup bin/elasticsearch >/dev/null 2>&1 &

查看我们的分词过程

  GET _analyze?pretty
  {
    "analyzer": "ik_max_word",
    "text": "传智播客在哪里"
  }

11、分片交互过程

1、创建索引

首先:发送一个索引或者删除的请求给node1
其次:node1介绍到请求之后,会根据请求中携带的参数“文档id”判断出该文档应该存储在具体哪一个shard中
shard = hash(routing) % numberofprimary_shards
,比如shard0;其次就是node1通过元数据信息可以知道shard0在具体哪一个节点,于是node1会把请求转发给node3
最后:node3接收到请求之后会将请求并行的分发给shard0的所有replica shard之上,也就是存在于node 1和node 2中的replica shard;如果所有的replica shard都成功地执行了请求,那么将会向node 3回复一个成功确认,当node 3收到了所有replica shard的确认信息后,则最后向用户返回一个Success的消息。

2、删除索引

该过程可以分为四个阶段来描述:
阶段1:客户端向node 1发送一个文档删除的请求。
阶段2:同样的node 1通过请求中文档的 _id 值判断出该文档应该被存储在shard 0 这个分片中,并且node 1知道shard 0的primary shard位于node 3这个节点上。因此node 1会把这个请求转发到node 3。
阶段3:node 3接收到请求后,在主分片上面执行删除请求
阶段4:如果node 3成功地删除了文档,node 3将会请求并行地发给其余所有的replica shard所在node中。这些node也同样操作删除,执行后则向node 3确认成功,当node 3接收到所有的成功确认之后,再向客户端发送一个删除成功的信息。

3、查询索引

检索文档的时候,我们并不知道文档在集群中的哪个位置,所以一般情况下不得不去询问index中的每一个shard,然后将结果拼接成一个大的已排好序的汇总结果列表;
(1):客户端发送一个检索请求给node3,此时node3会创建一个空的优先级队列并且配置好分页参数from与size。
(2):node3将检所请求发送给index中的每一个shard(primary 和 replica),每一个在本地执行检索,并将结果添加到本地的优先级队列中;
(3):每个shard返回本地优先级序列中所记录的_id与score值,并发送node3。Node3将这些值合并到自己的本地的优先级队列中,并做全局的排序(node 3将它们合并成一条汇总的结果),返回给客户端。

13、elasticsearch 的sql插件使用

对于这些复杂的查询,es使用javaAPI都可以实现,但是相较于sql语句来说,我们更加熟悉sql语句,所以es也提供了sql语句的开发,让我们通过sql语句即可实现ES的查询,接下来我们就来安装并学习sql的插件的使用方法吧!
在es版本6.3之前都不支持sql语句的开发,如果需要使用sql语句来开发es的数据查询,那么我们需要手动的自己安装插件,插件下载地址如下,
https://github.com/NLPchina/elasticsearch-sql/
但是在6.3版本之后,es自带就安装了sql的插件,我们可以直接通过sql语句的方式实现es当中的数据查询
对于sql语句的使用,es给我们提供了三种方式,接下来我们分别看看三种方式如何实现es数据的查询

第一种方式:通过rest风格实现数据的查询

第一步:使用rest方式向索引库当中添加数据
使用kibana向索引库当中添加数据

PUT /library/book/_bulk?refresh
{"index":{"_id": "Leviathan Wakes"}}
{"name": "Leviathan Wakes", "author": "James S.A. Corey", "release_date": "2011-06-02", "page_count": 561}
{"index":{"_id": "Hyperion"}}
{"name": "Hyperion", "author": "Dan Simmons", "release_date": "1989-05-26", "page_count": 482}
{"index":{"_id": "Dune"}}
{"name": "Dune", "author": "Frank Herbert", "release_date": "1965-06-01", "page_count": 604}

第二步:使用rest风格方式查询数据

curl -X POST "node01:9200/_xpack/sql?format=txt" -H 'Content-Type: application/json' -d'
{
    "query": "SELECT * FROM library WHERE release_date < \u00272000-01-01\u0027"
}

第二种方式:使用sql脚本的方式进入sql客户端进行查询

我们也可以使用sql脚本的方式,进入sql客户端,通过sql语句的方式实现数据的查询
第一步:node01进入sql脚本客户端
node01执行以下命令进入sql脚本客户端

cd /export/servers/es/elasticsearch-6.7.0
bin/elasticsearch-sql-cli node01:9200

第二步:执行sql语句

sql> select * from library;
     author     |     name      |  page_count   |      release_date      
----------------+---------------+---------------+------------------------
Dan Simmons     |Hyperion       |482            |1989-05-26T00:00:00.000Z
James S.A. Corey|Leviathan Wakes|561            |2011-06-02T00:00:00.000Z
Frank Herbert   |Dune           |604            |1965-06-01T00:00:00.000Z

第三种方式:通过jdbc连接的方式

当然了,我们也可以通过jdbc连接的方式,通过java代码来实现ES当中数据的查询操作
官网介绍操作连接
https://www.elastic.co/guide/en/elasticsearch/reference/6.7/sql-jdbc.html

使用javaAPI访问数据库当中的数据,会产生一个错误,参见这篇文章
https://www.cnblogs.com/hts-technology/p/9282421.html

第一步:导入jar包
在我们的maven依赖中添加以下坐标,导入es-sql的jar包

<repositories>
        <repository>
            <id>elastic.coid>
            <url>https://artifacts.elastic.co/mavenurl>
        repository>
    repositories>

	<dependency>
            <groupId>org.elasticsearch.plugingroupId>
            <artifactId>x-pack-sql-jdbcartifactId>
            <version>6.7.0version>
        dependency>

第二步:开发java代码,实现查询
通过java代码,使用jdbc连接es服务器,然后查询数据

@Test
    public void esJdbc() throws SQLException {
        EsDataSource dataSource = new EsDataSource();
        String address = "jdbc:es://http://node01:9200" ;
        dataSource.setUrl(address);
        Properties connectionProperties = new Properties();
        dataSource.setProperties(connectionProperties);
        Connection connection = dataSource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from library");
        while(resultSet.next()){
            String string = resultSet.getString(0);
            String string1 = resultSet.getString(1);
            int anInt = resultSet.getInt(2);
            String string2 = resultSet.getString(4);
            System.out.println(string + "\t" +  string1 + "\t" +  anInt + "\t" + string2);
        }
        connection.close();
    }

你可能感兴趣的:(ELK,elk)