你的位置:首页 > Java教程

[Java教程]Elasticsearch 分享


【理论部分】

一、什么是Elasticsearch?

       首先Elasticsearch是一个基于Lucene的搜索服务器,而Lucene是一个基于java开发的全文检索引擎的架构。
       下面是官网对Elaticsearch的介绍:
            Actionable Insight at Your Fingers
                    Distributed, scalable, and highly available
                    Real-time search and analytics capabilities
                    Sophisticated RESTful API
        我们可以看到上面描述es的一些特性:具备分布式能力和相应功能,实时搜索和分析,支持现在流行的RESTful 架构风格。而分布式让他对大数据也能很好的支持,对RESTful 的支持让任何语言都可以访问。
        所以我对它的理解是:

一个采用Restful API标准的高扩展性和高可用性的实时数据分析的全文搜索工具。

 

二、Elasticsearch的用途

        上面也提到了,elasticsearch的主语是全文搜索工具,所以他就是干全文搜索用的。

        下面是一些使用案例:

i) Github

“Github使用Elasticsearch搜索20TB的数据,包括13亿的文件和1300亿行的代码”

这个不用介绍了吧,码农们都懂的,Github在2013年1月升级了他们的代码搜索,由solr转为elasticsearch,目前集群规模为26个索引存储节点和8个客户端节点(负责处理搜索请求),详情请看官方博客https://github.com/blog/1381-a-whole-new-code-search


ii) Mozilla

Mozilla公司以火狐著名,它目前使用 WarOnOrange这个项目来进行单元或功能测试,测试的结果以 json的方式索引到elasticsearch中,开发人员可以非常方便的查找bug。
Socorro是Mozilla公司的程序崩溃报告系统,一有错误信息就插入到 Hbase和Postgres 中,然后从Hbase中读取数据索引到elasticsearch中,方便查找。

http://blog.itpub.net/attachment/201403/14/16907020_1394762149yiIp.png

三、Elasticsearch 名词解释

i) 在数据层面主要有:
  • Index:Elasticsearch用来存储数据的逻辑区域,它类似于关系型数据库中的db概念。一个index可以在一个或者多个shard上面,同时一个shard也可能会有多个replicas。(必须小写
  • Document:Elasticsearch里面存储的实体数据,类似于关系数据中一个table里面的一行数据。
document由多个field组成,不同的document里面同名的field一定具有相同的类型。document里面field可以重复出现,也就是一个field会有多个值,即multivalued。(区分大小写
  • Document type:为了查询需要,一个index可能会有多种document,也就是document type,但需要注意,不同document里面同名的field一定要是相同类型的。相当于数据库里的一个表。 (区分大小写,且里面的field也区分大小写
  • Document id : 唯一,相当于数据库主键。
  • Mapping:存储field的相关映射信息,不同document type会有不同的mapping。

 

ii) 在服务层面主要有:

  • Node: 一个server实例。
  • Cluster:多个node组成cluster。
  • Shard:数据分片,一个index可能会存在于多个shards,不同shards可能在不同nodes。
  • Replica:shard的备份,有一个primary shard,其余的叫做replica shards。
 
 

 

【实践部分】

四、Elasticsearch 的安装部署启动

 
       一些基本的认识我们都有了,下面就开始实践了,由于es一般都是运行在linux里的,我们现在就在linux下部署一个elasticsearch服务(特别需要注意的,elasticsearch1.x 和 2.x 有非常大的区别,我下面讲的都是2.x的):
 
1、环境    elasticesearch依赖java环境,需要jre7以上。
 
2、下载
    https://www.elastic.co/downloads/elasticsearch
    在官网下载tar.gz格式压缩包
 
3、解压安装
    elasticesearch只需要解压就行,解压到相应目录

[boss@localhost ~]$ mkdir elasticesearch
[boss@localhost ~]$ cd elasticesearch/
[boss@localhost elasticesearch]$ tar xzf elasticsearch-2.3.5.tar.gz


 

4、启动
启动的时候最好添加jvm参数 ./elasticsearch -Xms512m -Xmx512m
[boss@localhost elasticesearch]$ cd bin/
[boss@localhost bin]$ ./elasticsearch


 

5、问题
 测试环境是在公司虚拟机上,jdk 1.7.0_45,启动报错,需要升级jdk,貌似是jvm的bug。
在官网上看到这么一句话需要java 8 update 20 for later, or java 7 update 55 or later version.否则有bug.,甚至导致数据丢失。

 
至于windows下的安装部署启动在这就不介绍了,具体请看另外一篇《Elasticesearch在Windows的安装运行》
 
关于elasticsearch集群:只要在相同是host下,且配置文件中的cluster.name相同的节点,就会组成一个集群
 

五、Elasticsearch 目录、配置信息解释

 i) 安装的目录布局如下:

 Type

 Description

 Default Location

 Setting

 home

 elasticsearch 安装目录        path.home

 bin

 二进制脚本,包括elasticsearch启动节点  {path.home}/bin  

 conf

 配置文件路径,包含elasticsearch.yml  {path.home}/config  path.conf

 data

 在节点上每个索引/碎片的数据文件的位置。可以有多个目录。  {path.home}/data  path.data

 work

 零时文件目录(工作目录)  {path.home}/work  path.work

 logs

 日志文件目录  {path.home}/logs  path.logs 

 

    如果有多个数据目录,可以允许使用数据分拆技术,将数据能够按照设置放在不同的磁盘上。这个分拆原来是很简单的,只是保证一个文件完整的存在一个地方,具体是如果选择存在那个磁盘上是通过 index.store.distributor来配置的:

  1. least_used(默认):总是选择可用空间最大的目录。
  2. random:随机选择的目录。选择一个特定的目录的概率,是与这个目录中可用空间量成正比。

 

    注意,在相同的数据上没有多个副本,在这一点上,它的类似 raid 0。 虽然简单,但是它应该提供一个好的解决方案,对于不想使用 raid的人 。
 

 ii) 配置文件
    Elasticsearch的配置文件在conf目录下,有两个.yml文件,一个是elasticsearch.yml,另一个是logging.yml。
    其中elasticsearch.yml是对elasticsearch的配置;logging.yml是对elasticsearch日志的配置,也就是对log4j的配置。
    我们这里讲elasticsearch.yml,文件中都比较详细的英文解释,所以我就说说比较重要的几个配置:

  1. cluster.name:          elasticsearch天然具备集群能力,所以这里就有一个集群名称配置,默认为elasticsearch,最好修改下。
  2. node.name:           节点名称,也就是集群中的各个节点的名称,也需要配置,方便以后管理和java api开发
  3. network.host:         允许访问的host,可以是ipv4也可以是ipv6形式,在es2.x下如果不配,那么就只能localhost访问了。
  4. http.port:           http端口号,用于restful、插件的访问端口,默认9200,不能重复
  5. transport.tcp.port:      通讯端口,java api 访问的就是这个端口,默认9300,不能重复
  6. discovery.zen.ping.unicast.hosts:    这个是集群启动的时候,默认发现的主机列表,然后通过这里的host再去发现别的节点,需要至少配置一个,不然好像有点问题,我在集群搭建的时候就因为没配置遇到一些意外情况。
  7. discovery.zen.minimum_master_nodes:   最小的master选举人数,默认为2,这种形式计算(total number of nodes /2+1)
  8. discovery.zen.ping.multicast.enabled:  自动发现节点开关,如果为false,则新加入的节点不会被发现。
  9. discovery.zen.ping.timeout:       自动发现超时时间。

 

六、Elasticsearch插件安装

1、head插件:        
        对于Elasticsearch这种为分布式集群而生的,没有一个管理工具的话,会无从下手,所以我们需要安装一些插件来辅助,经典的插件是 head插件,marvel插件。其中marvel插件是对开发者免费,另外好像要收费,而且我没安装成功过... 所以我们使用head插件。
        在杭州的同事可以访问 http://10.10.100.104:9200/_plugin/head/ 来查看, 界面如下:

alpha-application为集群名称
集群健康值:分为绿、黄、红。绿是表示正常;黄色表示部分异常,可以搜索,但是增删改备份什么的会有异常,数据会丢失;红色表示连搜索也不行了。
上面一个集群有两个节点,分别是node-alpha-0、node-alpha-1。其中node-alpha-0为master。
上面有5个index,每个index都有5个分片。
 
2、analysis-ik插件:
    首先得介绍一个概念:在检索数据中,有一个概念 analysis,中文为 分词
    比如一句话 I want to a be a bird。  如果不分词,那么每个字母都是搜索的关键词。这样就无法搜索了。es默认有分词,但是它对英文分词支持很好,对中文就很烂了。

    比如 “我国是发展中国家”,es 对他的分词就是每个汉字,这当然不行,理想的分词是 我国、是、发展、发展中、国家。
    因此我们需要 ik 插件,ik插件对中文分词有很好的支持。
安装步骤:
1、下载相应版本的ik。https://github.com/medcl/elasticsearch-analysis-ik 
2、因为下载的是源代码,使用maven编译,方法是在cd 到解压目录下 mvn package 编译
3、步骤和解压 target/releases/elasticsearch-analysis-ik-{version}.zip 到 your-es-root/plugins/ik

4、重启elasticsearch。这点很重要,我就因为没有重启折腾了一上午。

 
3、analysis-ik-pinyin插件:
    说完了中文分词插件,不可避免的需要拼音插件了,analysis-ik-pinyin这个插件是我找了很久觉得比较好的中文拼音插件。
安装插件需要将elasticsearch-analysis-lc-pinyin的源码自己maven  build出来,这样可以避免版本冲突
git 地址:http://git.oschina.net/music_code_m/elasticsearch-analysis-lc-pinyin。
 
现在网上没有找到有关2.X的插件安装和配置介绍,我摸索了很久才完成,这里记录下:
 

编译安装:

首先是build源码,使用将目录切到相应目录,我的是:
cd F:\software\elasticsearch-analysis-lc-pinyin-dev_2.2.2\elasticsearch-analysis-lc-pinyin


然后执行maven build命令(当然,前提是你安装了maven,并配置好环境变量)

mvn package


然后就等待他的编译,完成时会在..\elasticsearch-analysis-lc-pinyin\target\releases目录下生产一个zip,我们只需将这个zip解压到elasticsearch的plugin目录下即可。

配置使用:

lc 2.x是不需要在elasticsearch.yml里配置的,我们只需要重启elasticsearch实例即可。
关键就是在于使用上mapping和DSL的配置。
由于elasticsearch 1.x和2.x改动很大,所以我这里直接贴2.x的mapping配置了:
curl -XPUT http://localhost:9200/addr
curl -XPOST http://localhost:9200/addr/std/_mapping -d'
 {
  "std": {
    "properties": {
      "detail_name": {
        "type": "string",
        "analyzer": "lc_index",
        "search_analyzer": "lc_search",
        "fields": {
          "cn": {
            "type": "string",
            "analyzer": "ik_max_word",
            "search_analyzer": "ik_max_word"
          }
        }
      },
      "door_name": {
        "type": "string",
        "analyzer": "lc_index",
        "search_analyzer": "lc_search",
        "fields": {
          "cn": {
            "type": "string",
            "analyzer": "ik_max_word",
            "search_analyzer": "ik_max_word"
          }
        }
      }
    }
  }
}
'

主要问题是在于,1.x是 index_analyzer 为 lc_index ,但是2.x 没有了index_analyzer 这个参数。

接下来就和1.x差不多了。

 
4、sql插件:
        这个插件可以让不熟悉curl命令的人使用sql语句查询。
        具体方法就不介绍了,github里都有:https://github.com/NLPchina/elasticsearch-sql/ 

 


 
上面的url即 jdbc驱动的url,user 和password 是相应数据库的登录名密码。
上面的脚本是一次性同步,实时同步需要加如一些参数。
    "interval":      "1800", 这里是同步数据的频率 1800s,半小时,可以按需要设成 1s或其它    "schedule" :      "0 0/60 0-23 ? * *",  同步数据任务 60分钟一次    "flush_interval" :   "5s",  刷新间隔为5S  

 


 
具体关于这个插件的使用,请看《elasticsearch-jdbc 插件说明》