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代码创建索引参考demo中OperData.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. queryData和OperData.queryDataSql两种搜索方法。
queryData方法中采用的是es的QueryBuilder类实现的搜索,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-bigdesk是es一个集群监控工具,可以通过它来查看ES集群的各种状态;
4) elasticsearch-servicewrapper插件是ElasticSearch的服务化插件。
6.ES与关系型数据库相比
1) 全文检索时进行各种操作,比如任意维度的字段查询,过滤掉某些无效的信息,然后根据某个字段排序,再取topN的结果集返回,普通关系型数据库都有这些功能,在es中,这些操作都是支持的,而且还非常高效,它能满足我们大部分的需求;
2) 在es中,可以查询多个index,以及多个type,可以一次组装两个毫无关系的查询,发送到es服务端进行检索,然后获取结果;
3) es中,通过了scorll的方式,支持深度分页查询,在数据库里使用的是一个cursor游标来记录读取的偏移量,同样的在es中也支持,这样的查询方式,它通过一个scrollid记录了上一次查询的状态,能轻而易举的实现深度翻页,本质上是对了Lucene的SearchAfter的封装;
4) es中提供了对聚合函数的支持,比如一些max,min,avg,count,sum等支持,除此之外还支持group,facet等操作
7.Demo
8.ES注意点
1)es脑裂情况
比如集群了5个es节点,其他3个节点在一个实验室,另2个节点在其他实验室,2节点所在实验室出现网络故障,2节点环境会自动推选一个节点作为master,3节点环境es也会推选一个节点最为master,过会网络恢复,这时出现2个master,这种情况叫脑裂。
2)文档写入控制
当两个并发请求要修改文档的时候,es使用的是乐观锁。
在es中,更新请求实际上是分为两个阶段,获取文档,修改文档,然后保存文档。
那么当两个更新请求同时要修改文档的时候,系统乐观的认为不会有两个并发请求对一个系统操作。
文档原本的版本为1,请求A获取了version为1的文档,请求B也获取了version为1的文档,然后请求A修改完文档后,并且先执行了保存操作,这个时候,系统中的文档version变为了2。
这个时候,B再执行保存操作的时候,告诉系统我要修改version为1的文档。系统就会抛出一个错误,说文档版本不匹配。然后这个错误由应用程序自己来进行控制。