大数据技术之Elasticsearch【上】
一 概述
1.1 什么是搜索
百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜欢的电影,或者说找一本喜欢的书,或者找一条感兴趣的新闻(提到搜索的印象)。百度 != 搜索
1)互联网的搜索:电商网站,招聘网站,新闻网站,各种app
2)IT系统的搜索:OA软件,办公自动化软件,会议管理,日程管理,项目管理。
搜索,就是在任何场景下,找寻你想要的信息,这个时候,会输入一段你要搜索的关键字,然后就期望找到这个关键字相关的有些信息
1.2 用数据库做搜索
用数据库来实现搜索,是不太靠谱的。通常来说,性能会很差的。
1.3 全文检索和Lucene
1)全文检索,倒排索引
全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。全文搜索引擎数据库中的数据。
2)lucene,就是一个jar包,里面包含了封装好的各种建立倒排索引,以及进行搜索的代码,包括各种算法。我们就用java开发的时候,引入lucene jar,然后基于lucene的api进行去进行开发就可以了。
1.4 什么是Elasticsearch
Elasticsearch,基于lucene,隐藏复杂性,提供简单易用的restful api接口、java api接口(还有其他语言的api接口)。
关于elasticsearch的一个传说,有一个程序员失业了,陪着自己老婆去英国伦敦学习厨师课程。程序员在失业期间想给老婆写一个菜谱搜索引擎,觉得lucene实在太复杂了,就开发了一个封装了lucene的开源项目,compass。后来程序员找到了工作,是做分布式的高性能项目的,觉得compass不够,就写了elasticsearch,让lucene变成分布式的系统。
Elasticsearch是一个实时分布式搜索和分析引擎。它用于全文搜索、结构化搜索、分析。
全文检索:将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
结构化检索:我想搜索商品分类为日化用品的商品都有哪些,select * from products where category_id='日化用品'。
数据分析:电商网站,近7天牙膏这种商品销量排名前10的商家有哪些;新闻网站,近1个月访问量排名前3的新闻版块是哪些。
1.5 Elasticsearch适用场景
1)维基百科,类似百度百科,牙膏,牙膏的维基百科,全文检索,高亮,搜索推荐。
2)The Guardian(国外新闻网站),类似搜狐新闻,用户行为日志(点击,浏览,收藏,评论)+ 社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜)。
3)Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案。
4)GitHub(开源代码管理),搜索上千亿行代码。
5)国内:站内搜索(电商,招聘,门户,等等),IT系统搜索(OA,CRM,ERP,等等),数据分析(ES热门的一个使用场景)。
1.6 Elasticsearch特点
1)可以作为一个大型分布式集群(数百台服务器)技术,处理PB级数据,服务大公司;也可以运行在单机上,服务小公司;
2)Elasticsearch不是什么新技术,主要是将全文检索、数据分析以及分布式技术,合并在了一起,才形成了独一无二的ES;lucene(全文检索),商用的数据分析软件(也是有的),分布式数据库(mycat);
3)对用户而言,是开箱即用的,非常简单,作为中小型的应用,直接3分钟部署一下ES,就可以作为生产环境的系统来使用了,数据量不大,操作不是太复杂;
4)数据库的功能面对很多领域是不够用的(事务,还有各种联机事务型的操作);特殊的功能,比如全文检索,同义词处理,相关度排名,复杂数据分析,海量数据的近实时处理;Elasticsearch作为传统数据库的一个补充,提供了数据库所不能提供的很多功能。
1.7 Elasticsearch核心概念
1.7.1 近实时
近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级。
1.7.2 Cluster(集群)
集群包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常。
1.7.3 Node(节点)
集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群。
1.7.4 Index(索引-数据库)
索引包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。
1.7.5 Type(类型-表)
每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field,比如博客系统,有一个索引,可以定义用户数据type,博客数据type,评论数据type。
商品index,里面存放了所有的商品数据,商品document
但是商品分很多种类,每个种类的document的field可能不太一样,比如说电器商品,可能还包含一些诸如售后时间范围这样的特殊field;生鲜商品,还包含一些诸如生鲜保质期之类的特殊field
type,日化商品type,电器商品type,生鲜商品type
日化商品type:product_id,product_name,product_desc,category_id,category_name
电器商品type:product_id,product_name,product_desc,category_id,category_name,service_period
生鲜商品type:product_id,product_name,product_desc,category_id,category_name,eat_period
每一个type里面,都会包含一堆document
{
"product_id": "1",
"product_name": "长虹电视机",
"product_desc": "4k高清",
"category_id": "3",
"category_name": "电器",
"service_period": "1年"
}
{
"product_id": "2",
"product_name": "基围虾",
"product_desc": ",冰岛产",
"category_id": "4",
"category_name": "生鲜",
"eat_period": "7天"
}
1.7.6 Document(文档-行)
文档是es中的小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。
1.7.7 Field(字段-列)
Field是Elasticsearch的小单位。一个document里面有多个field,每个field就是一个数据字段。
product document
{
"product_id": "1",
"product_name": "高露洁牙膏",
"product_desc": "高效美白",
"category_id": "2",
"category_name": "日化用品"
}
1.7.8 mapping(映射-约束)
数据如何存放到索引对象上,需要有一个映射配置,包括:数据类型、是否存储、是否分词等。
这样就创建了一个名为blog的Index。Type不用单独创建,在创建Mapping 时指定就可以。Mapping用来定义Document中每个字段的类型,即所使用的 analyzer、是否索引等属性,非常关键等。创建Mapping 的代码示例如下:
client.indices.putMapping({
index : 'blog',
type : 'article',
body : {
article: {
properties: {
id: {
type: 'string',
analyzer: 'ik',
store: 'yes',
},
title: {
type: 'string',
analyzer: 'ik',
store: 'no',
},
content: {
type: 'string',
analyzer: 'ik',
store: 'yes',
}
}
}
}
});
1.7.9 elasticsearch与数据库的类比
关系型数据库(比如Mysql)
非关系型数据库(Elasticsearch)
数据库Database
索引Index
表Table
类型Type
数据行Row
文档Document
数据列Column
字段Field
约束 Schema
映射Mapping
1.7.10 ES存入数据和搜索数据机制
1)索引对象(blog):存储数据的表结构 ,任何搜索数据,存放在索引对象上 。
2)映射(mapping):数据如何存放到索引对象上,需要有一个映射配置, 包括:数据类型、是否存储、是否分词等。
3)文档(document):一条数据记录,存在索引对象上 。
4)文档类型(type):一个索引对象,存放多种类型数据,数据用文档类型进行标识。
二 快速入门
2.1 安装包下载
1)Elasticsearch官网: https://www.elastic.co/products/elasticsearch
2.2 安装Elasticsearch(单节点Linux环境)
[root@bigdata13 elasticsearch-5.2.2]# useradd bdqn
1)解压elasticsearch-5.6.1.tar.gz到/opt/module目录下
[bdqn@bigdata11 software]$ tar -zxvf elasticsearch-5.6.1.tar.gz -C /opt/module/
2)在/opt/module/elasticsearch-5.6.1路径下创建data和logs文件夹
[bdqn@bigdata11 elasticsearch-5.6.1]$ mkdir data
[bdqn@bigdata11 elasticsearch-5.6.1]$ mkdir logs
[root@bigdata13 elasticsearch-5.2.2]# chown -R bdqn:bdqn /opt/module/elasticsearch-5.2.2/
3)修改配置文件/opt/module/elasticsearch-5.2.2/config/elasticsearch.yml
[bdqn@bigdata11 config]$ pwd
/opt/module/elasticsearch-5.6.1/config
[bdqn@bigdata11 config]$ vi elasticsearch.yml
# ---------------------------------- Cluster -------------------------------------
cluster.name: Andy
# ------------------------------------ Node --------------------------------------(三个不能一样)
node.name: node-102
# ----------------------------------- Paths ---------------------------------------
path.data: /opt/module/elasticsearch-5.6.1/data
path.logs: /opt/module/elasticsearch-5.6.1/logs
# ----------------------------------- Memory -----------------------------------
bootstrap.memory_lock: false
bootstrap.system_call_filter: false
# ---------------------------------- Network ------------------------------------
network.host: 192.168.1.102
# --------------------------------- Discovery ------------------------------------
discovery.zen.ping.unicast.hosts: ["bigdata11"]
(1)cluster.name
如果要配置集群需要两个节点上的elasticsearch配置的cluster.name相同,都启动可以自动组成集群,这里如果不改cluster.name则默认是cluster.name=my-application,
(2)nodename随意取但是集群内的各节点不能相同
(3)修改后的每行前面不能有空格,修改后的“:”后面必须有一个空格
5)配置linux系统环境(参考:http://blog.csdn.net/satiling/article/details/59697916)
(1)编辑limits.conf 添加类似如下内容
[bdqn@bigdata11 elasticsearch-5.6.1]$ sudo vi /etc/security/limits.conf
添加如下内容:
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
(2)进入limits.d目录下修改配置文件。
[bdqn@bigdata11 elasticsearch-5.6.1]$ sudo vi /etc/security/limits.d/20-nproc.conf
修改如下内容:
* soft nproc 1024
#修改为
* soft nproc 2048
(3)修改配置sysctl.conf
[bdqn@bigdata11 elasticsearch-5.6.1]$ sudo vi /etc/sysctl.conf
添加下面配置:
vm.max_map_count=655360
并执行命令:
[bdqn@bigdata11 elasticsearch-5.6.1]$ sudo sysctl -p
然后,重新启动elasticsearch,即可启动成功。
6)启动elasticsearch
[bdqn@hadoop105 elasticsearch-5.6.1]$ bin/elasticsearch
后台启动方式
[bdqn@hadoop105 elasticsearch-5.6.1]$ bin/elasticsearch -d
7)测试elasticsearch
[bdqn@bigdata11 elasticsearch-5.6.1]$ crul http://bigdata11:9200
{
"name" : "node-102",
"cluster_name" : "my-application",
"cluster_uuid" : "znZfW5tGQou9rKzb6pG6vA",
"version" : {
"number" : "5.6.1",
"build_hash" : "667b497",
"build_date" : "2017-09-14T19:22:05.189Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
8)安装elasticsearch-head.crx插件
(1)Google浏览器:打开浏览器,进入“更多工具”——>“扩展程序”,将插件拖入即可完成安装
(2)360浏览器:打开浏览器,双击elasticsearch-head.crx插件即可完成安装
(3)使用插件查看节点状态
9)停止集群
kill -9 进程号
10) 如果出现Chrome把这个软件禁用的提示,点击如下链接解决:以开发者模式安装配置
11) https://jingyan.baidu.com/article/a681b0de7ddd313b19434661.html
2.3 安装Elasticsearch(多节点集群Linux环境)
1)分发Elasticsearch安装包至hadoop103和hadoop104
[bdqn@bigdata11 module]$ xsync elasticsearch-5.6.1/
2)修改bigdata11配置信息
[bdqn@bigdata11 config]$ vi elasticsearch.yml
添加如下信息:
node.master: true
node.data: true
3)修改hadoop103配置信息
(1)修改Elasticsearch配置信息
[bdqn@hadoop103 config]$ vi elasticsearch.yml
node.name: node-103
node.master: false
node.data: true
network.host: 192.168.1.103
(2)修改Linux相关配置信息(同bigdata11)
4)修改hadoop104配置信息
(1)修改Elasticsearch配置信息
[bdqn@hadoop104 config]$ vi elasticsearch.yml
node.name: node-104
node.master: false
node.data: true
network.host: 192.168.1.104
(3)修改Linux相关配置信息(同bigdata11)
5)分别启动三台节点的Elasticsearch
6)使用插件查看集群状态
7)iscovery.zen.ping.unicast.hosts 发现master节点
2.4 安装Elasticsearch容易出现的问题
elasticsearch 5.1 安装过程中遇到了一些问题做一些记录。
问题一:警告提示
[2016-12-20T22:37:28,543][INFO ][o.e.b.BootstrapCheck ] [elk-node1] bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks
[2016-12-20T22:37:28,552][ERROR][o.e.b.Bootstrap ] [elk-node1] node validation exception
bootstrap checks failed
max number of threads [1024] for user [elasticsearch] is too low, increase to at least [2048]
[2016-12-20T22:37:28,560][INFO ][o.e.n.Node ] [elk-node1] stopping ...
[2016-12-20T22:37:28,628][INFO ][o.e.n.Node ] [elk-node1] stopped
[2016-12-20T22:37:28,629][INFO ][o.e.n.Node ] [elk-node1] closing ...
[2016-12-20T22:37:28,677][INFO ][o.e.n.Node ] [elk-node1] closed
报了一大串错误,其实只是一个警告。
解决:使用心得linux版本,就不会出现此类问题了。
问题二:ERROR: bootstrap checks failed
max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
max number of threads [1024] for user [lishang] likely too low, increase to at least [2048]
解决:切换到root用户,编辑limits.conf 添加类似如下内容
vi /etc/security/limits.conf
添加如下内容:
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
问题三:max number of threads [1024] for user [lish] likely too low, increase to at least [2048]
解决:切换到root用户,进入limits.d目录下修改配置文件。
vi /etc/security/limits.d/90-nproc.conf
修改如下内容:
* soft nproc 1024
#修改为
* soft nproc 2048
问题四:max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
解决:切换到root用户修改配置sysctl.conf
vi /etc/sysctl.conf
添加下面配置:
vm.max_map_count=655360
并执行命令:
sysctl -p
然后,重新启动elasticsearch,即可启动成功。
2.5 HA问题
把#node.master: false注释
三台都配置 discovery.zen.ping.unicast.hosts: ["bigdata11","bigdata12","bigdata13"]
会自动的调节自身的master,即杀死mater节点,将会自动调节其他节点成为Master节点
三 Java API操作
Elasticsearch的Java客户端非常强大;它可以建立一个嵌入式实例并在必要时运行管理任务。
运行一个Java应用程序和Elasticsearch时,有两种操作模式可供使用。该应用程序可在Elasticsearch集群中扮演更加主动或更加被动的角色。在更加主动的情况下(称为Node Client),应用程序实例将从集群接收请求,确定哪个节点应处理该请求,就像正常节点所做的一样。(应用程序甚至可以托管索引和处理请求。)另一种模式称为Transport Client,它将所有请求都转发到另一个Elasticsearch节点,由后者来确定终目标。
3.1 API基本操作
3.1.1 操作环境准备
1)创建maven工程
2)添加pom文件
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
3)等待依赖的jar包下载完成
当直接在ElasticSearch 建立文档对象时,如果索引不存在的,默认会自动创建,映射采用默认方式
3.1.2 获取Transport Client
(1)ElasticSearch服务默认端口9300。
(2)Web管理平台端口9200。
//org.elasticsearch.transport.client.PreBuiltTransportClient@4bff2185
//org.elasticsearch.transport.client.PreBuiltTransportClient@6f099cef
private TransportClient client;
@SuppressWarnings("unchecked")
@Before
public void getClient() throws Exception {
// 1 设置连接的集群名称
Settings settings = Settings.builder().put("cluster.name", "my-application").build();
// 2 连接集群
client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("bigdata11"), 9300));
// 3 打印集群名称
System.out.println(client.toString());
}
(3)显示log4j2报错,在resource目录下创建一个文件命名为log4j2.xml并添加如下内容
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
3.1.3 创建索引
1)源代码
@Test
public void createIndex_blog(){
// 1 创建索引
client.admin().indices().prepareCreate("blog2").get();
// 2 关闭连接
client.close();
}
2)查看结果
{"blog2":{"aliases":{},"mappings":{},"settings":{"index":{"creation_date":"1507466730030","number_of_shards":"5","number_of_replicas":"1","uuid":"lec0xYiBSmStspGVa6c80Q","version":{"created":"5060299"},"provided_name":"blog2"}}}}
3.1.4 删除索引
1)源代码
@Test
public void deleteIndex(){
// 1 删除索引
client.admin().indices().prepareDelete("blog2").get();
// 2 关闭连接
client.close();
}
2)查看结果
浏览器查看http://bigdata11:9200/blog2
没有blog2索引了。
{"error":{"root_cause":[{"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"blog2","index_uuid":"_na_","index":"blog2"}],"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"blog2","index_uuid":"_na_","index":"blog2"},"status":404}
3.1.5 新建文档(源数据json串)
当直接在ElasticSearch建立文档对象时,如果索引不存在的,默认会自动创建,映射采用默认方式。
1)源代码
@Test
public void createIndexByJson() throws UnknownHostException {
// 1 文档数据准备
String json = "{" + "\"id\":\"1\"," + "\"title\":\"基于Lucene的搜索服务器\","
+ "\"content\":\"它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口\"" + "}";
// 2 创建文档
IndexResponse indexResponse = client.prepareIndex("blog", "article", "1").setSource(json).execute().actionGet();
// 3 打印返回的结果
System.out.println("index:" + indexResponse.getIndex());
System.out.println("type:" + indexResponse.getType());
System.out.println("id:" + indexResponse.getId());
System.out.println("version:" + indexResponse.getVersion());
System.out.println("result:" + indexResponse.getResult());
// 4 关闭连接
client.close();
}
2)结果查看
3.1.6 新建文档(源数据map方式添加json)
1)源代码
@Test
public void createIndexByMap() {
// 1 文档数据准备
Map<String, Object> json = new HashMap<String, Object>();
json.put("id", "2");
json.put("title", "基于Lucene的搜索服务器");
json.put("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
// 2 创建文档
IndexResponse indexResponse = client.prepareIndex("blog", "article", "2").setSource(json).execute().actionGet();
// 3 打印返回的结果
System.out.println("index:" + indexResponse.getIndex());
System.out.println("type:" + indexResponse.getType());
System.out.println("id:" + indexResponse.getId());
System.out.println("version:" + indexResponse.getVersion());
System.out.println("result:" + indexResponse.getResult());
// 4 关闭连接
client.close();
}
2)结果查看
相关文章