了解elasticsearch搜索引擎

时间:2021-08-15 17:31:47

1.ES简介

ElasticSearch是基于Lucene的提供了一个分布式多用户能力的全文搜索引擎。

ElasticSearch集群可以包含多个索引(indices),每一个索引可以包含多个类型(types),每一个类型包含多个文档(documents),然后每个文档包含多个字段(Fields),与传统型关系数据库不一样,它是面向文档型的储存。

ElasticSearch知识比较多,本文档简单介绍一下代码开发的应用。

2.ES安装与启动

ES采用java开发,安装时需要安装JDK1.7以上。

解压elasticsearch-1.7.1.tar文件;

进入bin目录,运行./elasticsearch start即可,启动es

3.ES集群

ES集群搭建,可以把索引进行分片存储,一个索引可以分成若干个片,分别存储到集群里面,ES自己内部完成对于集群里面的负载均衡,副本分配,索引动态均衡。

         集群中的每个es表示一个节点,由多个节点组成了es的集群。集群的主节点可以手工设置,也可以有es内存自动产生。

         集群的好处是当集群中某台机器异常时,ES会自动从副本中操作数据,不影响数据的正常使用。

集群配置如下:

1)  搭建一个ES的环境,配置config/elasticsearch.yml参数,一般配置如下:

cluster.name:test_es

node.name:"node_1"

node_master:true

node.data:true

index.number_of_shards:5

index.number_of_replicas:1

netword.host:10.40.93.157

transport.tcp.port:9300

http.port:9200

discovery.zen.ping.timeout:30s

discovery.zen.ping.multicast.enable:true

参数说明:

cluster.name表示集群名称,一个集群中每个ES节点设置相同的名称,ES会自动寻找网络中相同名称组成一个集群;

node.name表示ES节点名称;

node.master表示该ES节点是否设置为主节点;

node.data表示该ES节点是否存储数据,即存储索引片段;

index.number_of_shards表示分片数;

index.number_of_replicas表示副本数;

network.host表示ES所在主机的IP

transport.tcp.port表示该节点与其他节点交互的端口;

http.port表示Http传输监听定制端口;

discovery.zen.ping.timeout表示自动发现节点超时时间;

discovery.zen.ping.multicast.enabled表示禁止当前节点发现多个集群节点。

2)  搭建另一个ES环境,可以放在同一台机器,或者网络中的另一台机器环境上。

集群中的cluster.name名称一样,es会自动寻找相同的cluster.name名称组成集群。

示例是放在同一个机器中的。

cluster.name:test_es

node.name:"node_1"

node.master:true

node.data:true

index.number_of_shards:5

index.number_of_replicas:1

network.host:10.40.93.157

transport.tcp.port:9300

http.port:9200

discovery.zen.ping.timeout:30s

discovery.zen.ping.multicast.enabled:true

4.ES操作

1)连接ES

创建TransportClient进行连接

Map<String, String> setting = new HashMap<String, String>();
  setting.put("client.transport.ping_timeout", "600s");
  setting.put("client.transport.sniff", "true");
  setting.put("cluster.name", "test_es");
  Settings settings = ImmutableSettings.settingsBuilder().put(setting)
    .build();

  System.out.println("start");
  try {
   TransportClient client = new TransportClient(settings);
   String ss = "127.0.0.1:9300,127.0.0.1:9303,127.0.0.1:9302";
   if (ss == null){
    System.out.println("err: exceptipon");
    throw new IllegalArgumentException(
      "cms.es.clusterlist cannot be empty, configure in system.properties");

   }
/*   client.addTransportAddress(new InetSocketTransportAddress("127.0.0.1",9300))
   .addTransportAddress(new InetSocketTransportAddress("127.0.0.1",9303))
   .addTransportAddress(new InetSocketTransportAddress("127.0.0.1",9302));
   */
   // 集群地址
   for (String item : ss.split(",")) {
    String ip = item.split("[:]")[0];
    int port = Integer.parseInt(item.split("[:]")[1]);
    System.out.println("before addTransportAddress");
    client.addTransportAddress(new InetSocketTransportAddress(ip,
      port));
    System.out.println("after addTransportAddress, ip: " + ip + " port: " + port);

   }
  

2)创建索引

ES命令建表使用curl -XPUT http://127.0.0.1:9200/{index}/{type}/_mapping -d ''方式创建索引映射。

Java代码创建索引参考demoOperData.createType方法。

3)插入索引数据

索引数据插入支持一次插入一条或一次插入多条数据。

ES命令插入一条数据格式为

curl -XPUT 'http://127.0.0.1:9200/dailyvalue/101/' -d '{"aa":"dddd","value":"100.9"}'

4)搜索数据

ES搜索支持模糊匹配和精确匹配,匹配时支持与或非等条件组合,可以对搜索数据结果进行排序,取指定数量topn的数据等功能。

搜索数据量很大时,一次性全部提取数据会很慢,一般每次提取指定数据量的数据,或者采用分页方式提取数据。

ES命令搜索格式为:

curl -XGET 'http://localhost:9200/dailyvalue/_search?q=MoTypeId:102'

java代码实现搜索参考demo中的OperData. queryDataOperData.queryDataSql两种搜索方法。

queryData方法中采用的是esQueryBuilder类实现的搜索,queryDataSql方法中采用的是es的插件采用sql方式实现搜索,SearchRequestBuilder搜索时支持sql语句。验证过两种搜索数据方法,进行相同条件搜索时,QueryBuilder方法搜索效率比sql方式搜索效率略快。

5)删除数据

删除数据时支持删除指定的一条数据,或模糊删除一批数据。

java删除数据参考demo中的OperData.deleteData

6)更新数据

更新数据有两种方法,一直是采用es的更新数据方法UpdateRequestBuilder实现,另一种是删除数据,再重新插入。

5.ES插件

ES提供许多插件,实现更强大的功能,下面列举了几个插件:

1)  elasticsearch-head用于集群管理;

2)  elasticsearch-sql:使用SQL语法查询elasticsearch

3)  elasticsearch-bigdeskes一个集群监控工具,可以通过它来查看ES集群的各种状态;

4)  elasticsearch-servicewrapper插件是ElasticSearch的服务化插件。

6.ES与关系型数据库相比

1)  全文检索时进行各种操作,比如任意维度的字段查询,过滤掉某些无效的信息,然后根据某个字段排序,再取topN的结果集返回,普通关系型数据库都有这些功能,在es中,这些操作都是支持的,而且还非常高效,它能满足我们大部分的需求;

2)  es中,可以查询多个index,以及多个type,可以一次组装两个毫无关系的查询,发送到es服务端进行检索,然后获取结果;

3)  es中,通过了scorll的方式,支持深度分页查询,在数据库里使用的是一个cursor游标来记录读取的偏移量,同样的在es中也支持,这样的查询方式,它通过一个scrollid记录了上一次查询的状态,能轻而易举的实现深度翻页,本质上是对了LuceneSearchAfter的封装;

4)  es中提供了对聚合函数的支持,比如一些maxminavgcountsum等支持,除此之外还支持groupfacet等操作

7.Demo

8.ES注意点

1es脑裂情况

比如集群了5es节点,其他3个节点在一个实验室,另2个节点在其他实验室,2节点所在实验室出现网络故障,2节点环境会自动推选一个节点作为master3节点环境es也会推选一个节点最为master,过会网络恢复,这时出现2master,这种情况叫脑裂。

2)文档写入控制

当两个并发请求要修改文档的时候,es使用的是乐观锁。
es中,更新请求实际上是分为两个阶段,获取文档,修改文档,然后保存文档。
那么当两个更新请求同时要修改文档的时候,系统乐观的认为不会有两个并发请求对一个系统操作。

文档原本的版本为1,请求A获取了version1的文档,请求B也获取了version1的文档,然后请求A修改完文档后,并且先执行了保存操作,这个时候,系统中的文档version变为了2
这个时候,B再执行保存操作的时候,告诉系统我要修改version1的文档。系统就会抛出一个错误,说文档版本不匹配。然后这个错误由应用程序自己来进行控制。