zoukankan      html  css  js  c++  java
  • 大数据-es(elasticsearch)

    elasticsearch

    elasticsearch是lucene作为核心的实时分布式检索,底层使用倒排索引实现。

    倒排索引原理

    索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。倒排索引用存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射

    原始数据
    id 数据值
    1 你好杯子东西
    2 中国我爱
    3 你杯子我

    通过分词创建倒排索引
    你   1[0] 3[0]
    杯子 1[2] 3[1]
    中国 2[0]
    我   2[2] 3[3]
    上述主键词也是有序的,值为主键词所在原始数据的id,[]内为词所在位置

    检索时:提供检索词,基于主键词的有序性二分法进行定位,通过倒排索引的结果知道检索词对应的id,最终定位到原始数据中的数据值

    安装

    • 修改jdk1.8环境

      安装jdk1.8

      /ect/profile中的JAVA_HOME

      修改以下配置文件中的JAVA_HOME

      /opt/sxt/hbase-0.98/conf/hbase-env.sh

      /opt/sxt/hadoop-2.6.5/etc/hadoop/hadoop-env.sh

      /opt/sxt/hadoop-2.6.5/etc/hadoop/mapred-env.sh(直接注释)

      /opt/sxt/hadoop-2.6.5/etc/hadoop/yarn-env.sh(直接注释)

    • 安装es软件 tar -zxvf elasticsearch-2.4.5.tar.gz

    • 配置集群 vim /opt/sxt/elasticsearch-2.4.5/config/elasticsearch.yml

      Cluster.na (集群名)

      Node.name:node1 (定义本节点名称)

      Network.Host: 192.168.163.201 (本节点ip)

      另外插入防脑裂配置(关闭多播,连接超时,单播配置)

      discovery.zen.ping.multicast.enabled: false

      discovery.zen.ping_timeout: 120s

      client.transport.ping_timeout: 60s

      discovery.zen.ping.unicast.hosts: ["192.168.163.201","192.168.163.202", "192.168.163.203"]

    • 复制到其他节点

      scp -r /opt/sxt/elasticsearch-2.4.5 root@node1:/opt/sxt/

      修改elasticsearch.yml文件,节点名与ip地址

    • 修改elasticsearch的权限

      useradd es

      passwd es 在设置密码位123456

      chown es:es -R /opt/sxt/elasticsearch-2.4.5

    • 启动测试

      不支持root启动,内部插件需要修改权限

      切换用户 su es

      切换至bin目录下 cd /opt/sxt/elasticsearch-2.4.5/bin

      运行 ./elasticsearch -d (后台运行-d参数)

      启动集群后需要等待一段时间,集群需要选举出主节点

      注意时间同步

      在非后台运行 ctrl + c 停止es运行

      网络访问

      http://node1:9200 或者 (http://node1:9200/_cluster/health?pretty

    命令

    支持基于restful风格的http请求,返回json格式数据

    请求地址192.168.163.201:9200/

    使用curl命令 模拟http请求

    普通命令

    curl -XPUT http://192168.163.201:9200/索引库/类型/文档 -d 要传输的数据

    请求的类型包括 GET(查询),PUT(修改),POST(创建),DELETE(删除),HADE(头信息)

    查询需要扩大范围则去掉小范围的uri即可

    DSL查询命令

    Domain Specific Language 特定领域查询

    curl -XGET http://192.168.78.101:9200/shsxt/employee/_search -d '{内容}'

    参数说明

    • query 查找

    • match完全匹配 ;must_not 相当于NOT

    • should相当于OR

    • multi_match 多字段匹配

    • bool 多条件查询

    • range范围

    例子说明

    • 定值查询

      curl -XGET http://localhost:9200/shsxt/employee/_search?pretty -d '{
      "query":
      {"match":
      {"last_name":"smith"}
      }
      }'
    • 多字段匹配值

      curl -XGET http://localhost:9200/shsxt/employee/_search?pretty -d '{
      "query":
      {"multi_match":
        {"query":"bin",
          "fields":["last_name","first_name"]
        }
      }
      }'
    • 复合查询

      curl -XGET http://localhost:9200/shsxt/employee/_search?pretty -d '{
      "query":{
      "bool":{
      "must" :{"match":{"name":"bin"} },
      "must" :{"match":{"age":37} }
      }
      }
      }'
    • 范围查询

      curl -XGET http://localhost:9200/shsxt/employee/_search?pretty -d '{
      "query":{
      	"bool":{
      		"must" :{"match":{"name":"bin"} },
      		"must" : {"range": 
      			        {"age":{ "from":30,"to":40}} 
      			}
      		}
      	}
      }'
      

    DSL配置命令

    配置分词规则

    index是否建立索引,参数:analyzed(建立索引),no(不建立索引,无法通过该字段进行检索)

    analyzer(插入分词)和search_analyzer(检索分词),参数:ik_max_word细粒度,ik_min_word粗粒度,一般插入分词和检索分词使用相同分词粒度以便于检索。

    _mappings用于定义字段名称及其数据类型

    curl -XPOST http://localhost:9200/ik/ikType/_mapping -d'{
            "properties": {
                "content": {
                    "type": "string",
                    "index":"analyzed",
                    "analyzer": "ik_max_word",
                    "search_analyzer": "ik_max_word"
                }
           }
    }'
    _mapping 设置相关信息
    设置content字段的属性:type(数据类型),index(是否建立索引),analyzer(插入分词),search_analyzer(检索分词)
    

    settings

    _settings用于修改索引库默认配置

    curl -XPUT '192.168.78.101:9200/shsxt101/_settings' -d '{
        	 "index":{
                "number_of_replicas": "2"
             }
    }'
    

    插件

    head插件

    安装

    单机安装即可

    cd /opt/sxt/elasticsearch-2.4.5/bin/

    自动安装: ./plugin install mobz/elasticsearch-head (github网速慢不推荐)

    手动安装:将安装包复制到/opt/sxt/elasticsearch-2.4.5/plugins目录下

    说明: plugin -h 和plugin install -h 能够得到命令帮助提示

    在bin目录下执行:./plugin install file:/opt/sxt/elasticsearch-analysis-ik-1.10.5.zip

    注意修改插件的权限:chown -R es:es /opt/sxt/elasticsearch-2.4.5

    访问

    192.168.163.201:9200/_plugin/head

    • 基本查询 使用鼠标直接选择查询

    • 复合查询 使用url执行查询

    kibana插件

    安装

    1. 在每个es节点上安装license和marvel-agent

      • cd /opt/sxt/elasticsearch-2.4.5/bin

      • 本地插件安装

        • ./plugin install file:/opt/sxt/marvel-agent-2.4.5.zip

        • ./plugin install file:/opt/sxt/license-2.4.5.zip

        • 这两个插件能够直接复制到其他节点中

        • cd /opt/sxt/elasticsearch-2.4.5/plugins

          scp -r license marvel-agent node2:pwd

      • 远程安装

        • ./plugin install marvel-agent

        • ./plugin install license

    2. 安装kibana

      • tar -zxvf kibana-4.6.2-linux-x86_64.tar.gz 将文件移动到/opt/sxt

      • 本地安装kibana的marvel 插件

        cd /opt/sxt/kibana-4.6.2-linux-x86_64/bin

        ./kibana plugin --install marvel --url file:///opt/sxt/marvel-2.4.6.tar.gz

      • 配置kibana

        vim /opt/sxt/kibana-4.6.2-linux-x86_64/config/kibana.yml

        elasticsearch.url: "http://node1:9200" 任意配置一个es节点连接

    3. 时间同步

    4. 启动es集群,并启动kibana

      cd /opt/sxt/elasticsearch-2.4.5/bin

      ./elasticsearch

      cd /opt/sxt/kibana-4.6.2-linux-x86_64/bin

      ./kibana

    5. 查看监控效果

      192.168.163.201:5601(kbana安装在哪个机器选择哪个IP) 选择点击进入Marvel

    分词器IK

    将ik安装包放到新建ik目录下(mkdir ik) 执行unzip ik.zip

    将ik目录移动到es的plugins目录下,并拷贝值其他节点中下

    mv ik /opt/sxt/elasticsearch-2.4.5/plugins
    cd /opt/sxt/elasticsearch-2.4.5/plugins
    scp -r ik node2:`pwd`
    scp -r ik node3:`pwd`
    

    在plugins目录下执行chown es:es -R * 修改插件的权限

    架构概念

    • 索引结构

      index索引库,type类型,document文档,field字段。对应关系型数据库的库,表,行,列

      document的id唯一标识一个文档数据(若干个字段整体)

    • cluster 集群

      • 内部设置主节点选举机制,主节点管理分片与副本,节点发现与删除

      • recovery 有节点加入或退出时,数据恢复,数据重新分布

      • 外部可以连接任意节点执行任务(无视主从)

    • shaeds 索引分片

      • 索引库被拆分为若干分片(默认5片)

      • 根据doucment的值,hash计算后取余分配到不同分片中

      • 分片数量只能在定义索引库时定义,之后无法修改

        curl -XPUT 'localhost:9200/test1/' -d'{"settings":{"number_of_shards":3}}'

    • replicas

      • 每个分片具备一个主分片,n个副本分片。

      • 副本数就是n,可以随时修改

      • 副本有助于提高查询效率(向不同节点请求数据),提高数据安全(避免单机故障)。缺点:数据存储量大,存数据时压力大

      • curl -XPUT 'localhost:9200/my_index/' -d'{"settings":{"number_of_replicas":2}}'

    • gateway

      • es的数据先存储在内存中,达到阈值后,内存数据持久化到硬盘中

      • 为了数据安全设置gateway 相当于日志,用于恢复故障节点的内存

      • 磁盘文件的路径:/opt/sxt/elasticsearch-2.4.5/data/

    • discovery.zen节点的发现机制:

      • 多播:自动发现局域网中es节点,通过9300端口通讯和验证节点

      • 单播:关闭自动发现,指定集群各节点的IP

      discovery.zen.ping.multicast.enabled 是否允许多波,默认ture

      discovery.zen.ping.unicast.hosts 指定集群IP

    • Transport

      集群内执行tcp协议,外部支持:HTTP,servlet...可以后续插件集成

    • 对于需要将数据存储在hdfs上,需要安装插件elasticsearch/elasticsearch-hadoop

    重要概念

    索引库设计

    • index:字段是否创建索引

      analyzed创建

      no 不创建(该字段数据不能够执行检索,但获取数据时能够拿到值)一般这样的字段都是:id,序号,url 等不需要被检索的字段

    • 分词

      analyzer:存储时的分词方式

      search_analyzer:检索时的分词方式

      一般两个相同,不同的粗细粒度匹配结果不同

    • dynamic参数:true(默认值。动态添加字段),false(忽略新字段)strict(如果碰到陌生字段,抛出异常)

    curl -XPOST '192.168.78.101:9200/qiandu' -d '{
         "settings":{
            "number_of_replicas": "1",
            "number_of_shards": "3"
         },
    	
    "mappings":{
        "web":{
        "dynamic":"strict",
        "properties":{
            "title":{"type":"string","index":"analyzed","analyzer": "ik_max_word","search_analyzer": "ik_max_word"},
            "content":{"type":"string","index":"analyzed","analyzer": "ik_max_word","search_analyzer": "ik_max_word"},
            "url":{"type":"string","index":"no"}
            }
        }				
    }
    }'
    

    关于不存储数据

    指定content字段不存储数据 "_source": {"excludes": [ "content"]}

    若不存储的字段设置的检索索引,则能够通过检索该字段的数据得到,对应的文档id中其他执行了存储的数据,但该字段的数据时查不到的(单有检索作用)。

    进一步的,若存储的数据是其他数据库的id,那么能够建立二级索引

    curl -XPOST '192.168.78.101:9200/test3' -d '{
    	"mappings":{
         "web":{
             "_source": {"excludes": [ "content"]},
    		   
    		    "dynamic":"strict",
    			"properties":{
    				"title":{"type":"string","index":"no"},
    				"content":{"type":"string","index":"analyzed","analyzer": "ik_max_word","search_analyzer": "ik_max_word"}
    				}
               }			
    	}
    }'
    

     

    es搜索类型

    • query and fetch (最快)(次IO)

      向所有分片发送检索请求,各分片返回各自的计算结果数据。

      对于指定分页的情况,可能返回数倍于请求的数据

      请求前10个数据,每个分片返回前10个计算结果数据,IO压力大

    • query then fetch (默认) (2次IO)

      向所有分片发送检索请求,各分片返回各自的计算的结果分数,client排序后选择后,向各分片请求所需的数据

      请求前10个数据,每个分片返回各自前10的打分数,client所有接收到的打分数排序,取出前10,再向对应分片请求数据

    • DFS query and fetch(2次IO)

      DFS query then fetch(3次IO)

      基本同上,前面增加一步:向所有分片发送检索请求,各分片返回各自的检索到的总记录数,client汇总后,将汇中的总数返回各分片,各分片依据返回的总记录数打分处理,后续相同。

    分页

    – GET xxxx/_search?size=5&from=10

    • from

      • 设置检索结果的起始位置的索引,从第几个结果开始显示(0开始)

      • 默认0

    • size

      • 设置检索到的记录数(每页显示几个)

      • 默认10

    分片查询

    • 默认随机分片查询randomize across shards

    • 优先本地节点查询 _local

    • 只查询主分片 _primary

    • 优先查询主分片 _primary_first

    • 指定节点中查询 _only_node

    • 指定分片索引查找 _shards:0,1,2,5

    脑裂处理

    原因:网络故障,主节点同时执行master与data任务过多

    使得主节点只执行监控分配任务,并分配多个备用主节点

    • 设置主节点不存储数据

      node.master: true

      node.data: false

    • 设置从节点只执行存储,不参加主节点选举

      node.master: false

      node.data: true

    • 所有节点设置

      关闭多波

      discovery.zen.ping.multicast.enabled: false

      指定及节点的ip/主机名

      discovery.zen.ping.unicast.hosts: [“slave1”, “master” , “slave2"]

    API(java)

    配置代码

    用户获取es集群连接,为后续操作提供es连接对象

    import org.elasticsearch.common.settings.Settings;
    //通过集群名,创建客户端连接
    Map<String, String> map = new HashMap<String, String>();
    map.put("cluster.name", "sxt-es");
    client = TransportClient.builder().settings(Settings.builder().put(map)).build();
    
    //设置集群路径,配置至少一个节点地址(ip/主机名),内部连接端口为9300
     client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.78.101"), 9300));
    client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("node3"), 9300));
    

    索引库操作

    主要对象IndicesAdminClient(索引库层面连接)

    其3个主要方法

    • prepareCreate() 创建

    • prepareDelete() 删除

    • prepareExists() 判断存在

    import org.elasticsearch.client.IndicesAdminClient;
    //获取索引库层面连接
    IndicesAdminClient indices = client.admin(). indices();
    //执行索引库存在判断,其中prepareExists可传入可变参数,执行索引查询
    IndicesExistsResponse actionGet = indices.prepareExists("test").execute().actionGet();
    if (actionGet.isExists()) {System.out.print("test索引库已存在");}
    //索引库删除操作,可以进一步获取响应数据
    indices.prepareDelete("test").execute();
    
    //使用map设置创建数据库的参数,分片数和备份数
    Map<String, String> setMap = new HashMap<>();
    setMap.put("number_of_replicas", "0");
    setMap.put("number_of_shards", "3");
    //执行索引库创建,设置索引库名与参数
    indices.prepareCreate("test").setSettings(setMap).execute();
    

    索引操作

    1. 创建索引(数据插入)

      //通过map准备数据,存入字段名与字段值
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("name", "binbin");
      map.put("age", 30);
      //设置文档id方式(索引库为test,type为ttt,文档id为80)
      IndexResponse r1 = client.prepareIndex("test","ttt","80").setSource(hashMap).execute().actionGet();
      //自动创建文档id方式
      IndexResponse r2 = client.prepareIndex("test","ttt").setSource(hashMap).execute().actionGet();
      //获取文档id
      String id1=r1.getId();
      String id2=r2.getId();
      
      //另一种插入对象
      IndexRequest indexRequest = new IndexRequest("test", "tweet", "333").source(
                      XContentFactory.jsonBuilder()
                              .startObject()
                              .field("user", "kimchy")
                              .field("postDate", new Date())
                              .field("message", "trying out Elasticsearch")
                              .endObject());
      

       

    2. 直接获取数据

      通过document的id直接获取数据

      import org.elasticsearch.action.get.GetResponse;
      //执行数据获取
      GetResponse response =client.prepareGet("test","ttt","70").execute().actionGet();
      //从结果中获取数据
      long version=response.getVersion();//获取数据版本
          //获取数据字段,并遍历map
      Map<String, Object> source = response.getSource();
      for (String key : source.keySet()){System.out.print(key + "+" + source.get(key));}
      
    3. 检索索引

      索引库查询对象:SearchRequestBuilder。通过该对象设置检索参数

      //获取索引库查询对象,参数为可变参数,可传入多个索引库
      SearchRequestBuilder builder = client.prepareSearch("test");
      //设置检索的type,可变参数可传入多个
      builder.setTypes("ttt");
      //设置分页
      builder.setFrom(0);//设置设置检索结果的起始位置,从0开始(从第几个结果开始显示)
      builder.setSize(5);//设置检索到的记录数(每页显示几个)
      //设置结果排序,根据指定字段的值排序及排序顺序
      //若不设置则默认按照TF-IDF打分并排序;若自定义排序则不再打分
      builder.addSort("age",SortOrder.DESC);
      
      //设置具体检索内容builder.setQuery(),通过通过QueryBuilders对象的方法构建不同的查询
      
      //关键词查询
      String key="ccc";//自定义的关键词
      //设置关键词和执行查找的字段(在name字段中查找匹配ccc的结果)
      builder.setQuery(QueryBuilders.multiMatchQuery(key,"name"));
      //设置范围查询(匹配15-20之间的结果)
      builder.setQuery(QueryBuilders.rangeQuery("age").from(15).to(20));
      
      //执行查询,获取结果对象
      SearchResponse searchResponse=builder.get();
      

      解析SearchResponse对象的查询结果数据

      //解析返回对象,获取命中结果
      SearchHits hits = searchResponse.getHits();
      //解析命中条数(long)
      hits.getTotalHits()
      //将命中结果解析为数组对象,元素为单条命中元素
      SearchHit[] array_hits = hits.getHits();
      //遍历数组,解析命中的每条元素
      for(SearchHit hit:array_hits){
          hit.getScore();//获取打分结果
          hit.getId();//获取document的id
          hit.index();//获取结果的需要
          
          //解析document中的每个字段
          Map<String, Object> source = hit.getSource();
          for(String s: source.keySet()){
              //遍历得到key,再获取值
              System.out.println(s);
              System.out.println(source.get(s));
          }
      }
      
    4. 更新索引

      UpdateRequest对象构建更新,以下均为局部更新

      • 单更新

      • 结构1

        import org.elasticsearch.action.update.UpdateRequest;
        //获取更新对象
        UpdateRequest ur=new UpdateRequest();
        //设置参数
        ur.index("text");//索引库
        ur.type("ttt");//索引type
        ur.id("80");//document的id
        //存入字段
        Map<String, Object> map = new HashMap<>();
        map.put("age", "25");
        map.put("date", "2018-01-01");
        ur.doc(map);
        //执行插入
        client.update(ur);
        
      • 结构2(不同的字段设置格式)

        UpdateRequest ur=new UpdateRequest();
        ur.index("text");
        ur.type("ttt");
        ur.id("80");
        updateRequest.doc(
            XContentFactory.jsonBuilder()
                    .startObject()
                    .field("age", "26")
                    .field("city", "shanghai")
                    .endObject());
        client.update(ur);
        
      • 更新插入(若id没有则插入,有则更新字段,局部更新)

        //数据准备
        Map<String, Object> map = new HashMap<>();
        map.put("name", "lyp");
        map.put("age", "25");
        //插入对象
        IndexRequest indexRequest = new IndexRequest("test", "employee", "70").source(map);
        //更新对象
        UpdateRequest updateRequest = new UpdateRequest("test", "employee", "70").doc(map);
        //将插入对象放在更新对象中
        updateRequest.upsert(indexRequest);
        //执行
        client.update(updateRequest);
        
    5. 删除索引

      //根据document的id值,删除数据
      DeleteResponse response = client.prepareDelete("test", "employee", "80").execute().actionGet();
      System.out.print(response.isFound());
      
    6. 批量操作,能够批量执行不同的操作

      BulkRequestBuilder批处理对象,一次性执行

      import org.elasticsearch.action.bulk.BulkRequestBuilder;
      BulkRequestBuilder br = new BulkRequestBuilder();
      //插入操作对象
      IndexRequest ir= new IndexRequest("test","tweet","333").source(XContentFactory.jsonBuilder().startObject().field("user", "kimchy").field("postDate", new Date()).endObject());
      //删除操作对象
      DeleteResponse dr = client.prepareDelete("test", "aaa", "80");
      //将操作对象置入批处理对象中
      br.add(ir);
      br.add(dr);
      //执行批处理,返回批处理结果对象
      BulkResponse bulkResponse = bulkRequest.get();
      //判断结果是否存在,失败
      boolean hasfail=bulkResponse.hasFailures();
      

    测试数据爬取

    使用liunx的wget命令执行爬虫,具体如下

    wget -o /tmp/wget.log -P /root/data  --no-parent --no-verbose -m -D  www.shsxt.com -N --convert-links --random-wait -A html,HTML,shtml,SHTML http://www.shsxt.com
    # 日志位置:/tmp/wget.log ,数据存放位置:/root/data
    # 爬虫爬取范围: -D www.shsxt.com
    # 爬取文件类型: -A html,HTML,shtml,SHTML
    # 爬取起始页面: 最后一个 http://www.shsxt.com
    

    py的爬虫框架Scrapy,java的爬虫框架Nutch,c语言的爬虫框架wget

    网页解析

    • 使用第三方jar包jericho-html-3.3.jar解析网页。

    • 使用net.htmlparser.jericho.Source类,对爬取到的html进行数据清洗(ETL),得到第一个title(网页标题)和文本数据。再根据html所在目录和指定的域名获取url

    import net.htmlparser.jericho.Source;
    //file就是html文件的Flie对象
    Source source = new Source(file);
    //解析第一个title标签中的文本
    String title = source.getFirstElement("title").getTextExtractor().toString();
    //解析html文件中的
    String content = source.getTextExtractor().toString();
    //获取url:在文件系统中的路径为D:datawww.shsxt.com2017
    ecoll676.html。截取到的url为www.shsxt.com2017
    ecoll676.html
    int index = file.getAbsolutePath().indexOf("www.shsxt.com");
    String url = file.getAbsolutePath().substring(index);
    
    //递归获取指定路径的文件对象,包括子文件.
    import org.apache.commons.io.FileUtils;
    public static final String FILE_PATH = "G:\teach\doc\elasticsearch\data";
    Collection<File> files = FileUtils.listFiles(new File(FILE_PATH), TrueFileFilter.INSTANCE,TrueFileFilter.INSTANCE);
    

    es检索高亮

    es支持高亮检索

    //设置查询指定索引库与type
    SearchRequestBuilder builder = getClient().prepareSearch("test");
    builder.setTypes("ttt");
    // 设置高亮字段名称
    builder.addHighlightedField("title");
    builder.addHighlightedField("content");
    //设置每个结果最多显示3个碎片段,每个碎片段之间用...隔开 
    //片段就是包含高亮关键字的一小段文本,从总文本中截取而来
    builder.setHighlighterNumOfFragments(3);
    // 设置高亮前缀
    builder.setHighlighterPreTags("<font color='red'  >");
    // 设置高亮后缀
    builder.setHighlighterPostTags("</font>");
    //执行查找,设置查找的信息域,从title和content里找
    builder.setQuery(QueryBuilders.multiMatchQuery(key, "title", "content"));
    //结果解析
    SearchResponse searchResponse = builder.get();
    SearchHits hits = searchResponse.getHits();
    SearchHit[] hits2 = hits.getHits();
    for (SearchHit hit : hits2) {
    //源数据,不包含高亮(aaabbbccc);结果数据,含高亮( aaa<font color='red' >bbb</font>ccc  )
        if(hit.getHighlightFields().get("title")==null){
            //title中没有包含关键字,打印原先的title
            System.out.print(hit.getSource().get("title").toString());
        }else{
            //打印第一个具备高亮的title
            HighlightField titleField = hit.getHighlightFields().get("title");
            Text[] fragments = titleField.getFragments();
            String highlightTitle= fragments[0].toString();
            System.out.print(highlightTitle);
        }
        if(hit.getHighlightFields().get("content")==null){
            //content中没有包含关键字,答应原有数据
            System.out.print(hit.getSource().get("content").toString());
        }else{
            //打印具备高亮的碎片段
            StringBuilder sb =new StringBuilder();
            for(Text text: hit.getHighlightFields().get("content").getFragments()){
                sb.append(text.toString()+"...");
            }
            System.out.print(sb.toString());
        }
    }
    page.setList(list);
    

    优化

    • 分片数量

      分片多,检索时打开文件多;分片少,单片数据检索任务大

      优化:分片最多存储约20G

    • 副本数量

      建议2-3个

      可以提高检索效率(提高使用空闲节点的可能,单节点降低访问压力)与数据安全(备份多)

      服务器造成额外的存储压力和数据同步压力

    • 大量数据存入优化

      存入数据时副本数设为0,存好后修改副本数。降低数据存储时的压力

    • 调大系统的"最大打开文件数",建议32K甚至是64K

      – ulimit -a (查看)

      – ulimit -n 32000(设置)

    • JVM调优,修改bin/elasticsearch.in.sh中ES_MIN_MEM和ES_MAX_MEM

      建议设置一样大,避免频繁的分配内存。一般设置总内存的60%

    • 锁定物理内存地址,避免内存swapped

      修改文件conf/elasticsearch.yml

      bootstrap.mlockall: true

    • segment优化

    • 手动清理删除数据

      方式1:curl -XPOST 'http://localhost:9200/elasticsearch/_optimize?only_expunge_deletes=true'

      方式2:client.admin().indices().prepareOptimize("elasticsearch").setOnlyExpungeDeletes(true).get();

    • all域

      索引库中会额外存一个all的字段,存储一个document的中一个或者多个域(字段)的内容,检索时直接从all域中取全部数据,提高查询效率,但加大了存储与CPU压力

      禁用命令: "_all" : {"enabled":false}

    es配合HBase

    es作为hbase的二级索引,es索引库同步存储hbase的rowkey和部分需要检索的字段。

    解决hbase的rowkey查询不灵活的问题

    • 数据存储hbase时,将rowkey与数据存入es

    • es对数据建立索引,但不执行存储数据;es存储rowkey,但不建立rowkey的索引

    • 通过es对数据的检索得到rowkey,进而对从hbase中根据rowkey获取数据

    •  

     

  • 相关阅读:
    解决xcode5升级后,Undefined symbols for architecture arm64:问题
    第8章 Foundation Kit介绍
    app 之间发送文件 ios
    iphone怎么检测屏幕是否被点亮 (用UIApplication的Delegate)
    CRM下载对象一直处于Wait状态的原因
    错误消息Customer classification does not exist when downloading
    How to resolve error message Distribution channel is not allowed for sales
    ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼
    有了Debug权限就能干坏事?小心了,你的一举一动尽在系统监控中
    SAP GUI和Windows注册表
  • 原文地址:https://www.cnblogs.com/javaxiaobu/p/11703008.html
Copyright © 2011-2022 走看看