ElasticSearch大数据分布式弹性搜索引擎使用,
阅读目录:
1.背景
两年前有机会接触过elasticsearch,但是未做深入学习,只是工作中用到了。越来越发现es是个不错的好东西,所以花了点时间好好学习了下。在学习过程中也发现了一些问题,网上大多资料都很零散,大部分都是实验性的demo,很多问题并没有讲清楚也并没有系统的讲完整一整套方案,所以耐心的摸索和总结了一些东西分享出来。
毕竟当你用生产使用的标准来使用es时会有很多问题,这对你的学习提出来了新的标准。
比如,使用elasticsearch servicewrapper进行自启动的时候难道就没发现它的配置中有一个小bug导致load不了elasticsearch jar包中的class吗。
还有es不同版本之间的差异巨大,比如,1.0中的分布式routing在2.0中进行了巨大差异的修改。原本routing是跟着mapping一起配置的,到了2.0却跟着index动态走了。这个调整的本质目的是好的,让同一个index的不同type都有机会选择shard的片键。如果是跟着mapping走的话就只能限定于当前index的所有type。
es是个好东西,现在越来越多的分布式系统都需要用到它来解决问题。从ELK这种系统层的工具到电商平台的核心业务交易系统的设计都需要它来支撑实时大数据搜索分析。比如,商品中心的上千万的sku需要实时搜索,再到海量的在线订单实时查询都需要用到搜索。
在一些DevOps的工具中都需要es来提供强大的实时搜索功能。值得花点时间好好研究学习下。
作为电商架构师,所以没有什么理由不去学习和使用它来提高系统的整体服务水平。本篇文章将自己这段时间学习的经验总结出来分享给大家。
2.安装
首先你需要几台linux机器,你跑虚机也行。你可以在一台虚拟机上完成安装和配置,然后将当前虚拟机clone出多份修改下IP、HWaddr、UUID即用,这样方便你使用,而不需要再重复的安装配置。
1.我本地是三台Linux centos6.5,IP分别是,192.168.0.10、192.168.0.20、192.168.0.30。
(我们先在192.168.0.10上执行安装配置,然后一切就绪之后我们将这个节点clone出来修改配置,然后再配置集群参数,最后形成可以工作的以三个node组成的集群实例。)
2.由于ElasticSearch是java语言开发的,所以我们需要预先安装好java相关环境。我使用的是JDK8,直接使用yum安装即可,yum仓库有最新的源。
先查看你当前机器是否安装了java环境:
yum info installed |grep java*
<dependencies>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.3.5</version>
</dependency>
</dependencies>
JestClientFactory factory = new JestClientFactory();
List<String> nodes = new LinkedList<String>();
nodes.add("http://192.168.0.10:9200");
nodes.add("http://192.168.0.20:9200");
nodes.add("http://192.168.0.30:9200");
HttpClientConfig config = new HttpClientConfig.Builder(nodes).multiThreaded(true).build();
factory.setHttpClientConfig(config);
JestHttpClient client = (JestHttpClient) factory.getObject();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.queryStringQuery("中华人名共和国"));
searchSourceBuilder.field("name");
Search search = new Search.Builder(searchSourceBuilder.toString()).build();
JestResult rs = client.execute(search);
System.out.println(rs.getJsonString());
{
"took": 71,
"timed_out": false,
"_shards": {
"total": 45,
"successful": 45,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 0.6614378,
"hits": [
{
"_index": "posts",
"_type": "post",
"_id": "1",
"_score": 0.6614378,
"fields": {
"name": [
"王清培"
]
}
},
{
"_index": "posts",
"_type": "post",
"_id": "5",
"_score": 0.57875806,
"fields": {
"name": [
"王清培"
]
}
},
{
"_index": "posts",
"_type": "post",
"_id": "2",
"_score": 0.57875806,
"fields": {
"name": [
"王清培"
]
}
},
{
"_index": "posts",
"_type": "post",
"_id": "AVaKENIckgl39nrAi9V5",
"_score": 0.57875806,
"fields": {
"name": [
"王清培"
]
}
},
{
"_index": "class",
"_type": "student",
"_id": "1",
"_score": 0.17759356
},
{
"_index": "posts",
"_type": "post",
"_id": "3",
"_score": 0.17759356,
"fields": {
"name": [
"王清培"
]
}
}
]
}
}
返回的数据横跨多个索引。你可以通过不断的debug来查看链接IP是不是会启动切换,是不是会起到可用性的作用。
4.2.index开发
索引开发一般步骤比较简单,首先建立对应的mapping映射,配置好各个type中的field的特性。
4.2.1.mapping 配置
mapping是es实例用来在index的时候,作为各个字段的操作依据。比如,username,这个字段是否要索引、是否要存储、长度大小等等。虽然elasticsearch可以动态的处理这些,但是出于管理和运维的目的还是建议建立对应的索引映射,这个映射可以保存在文件里,以便将来重建索引用。
POST /demoindex
{
"mappings": {
"demotype": {
"properties": {
"contents": {
"type": "string",
"index": "analyzed"
},
"name": {
"store": true,
"type": "string",
"index": "analyzed"
},
"id": {
"store": true,
"type": "long"
},
"userId": {
"store": true,
"type": "long"
}
}
}
}
}
这是一个最简单的mapping,定义了索引名称为demoindex,类型为demotype的mapping。各个字段分别是一个json对象,里面有类型有索引是否需要。
这个在sense里编辑,然后直接post提交。
{
"acknowledged": true
}
{
"mq_template" : {
"order" : 10,
"template" : "mq*",
"settings" : {
"index" : {
"number_of_shards" : "5",
"number_of_replicas" : "2"
}
},
"mappings" : {
"_default_" : {
"_source_" : {
"enable" : false
}
}
},
"aliases" : { }
},
"log_template" : {
"order" : 10,
"template" : "log_*",
"settings" : {
"index" : {
"number_of_shards" : "5",
"number_of_replicas" : "2"
}
},
"mappings" : {
"_default_" : {
"_source_" : {
"enable" : false
}
}
},
"aliases" : { }
},
"error_template" : {
"order" : 10,
"template" : "error_*",
"settings" : {
"index" : {
"number_of_shards" : "5",
"number_of_replicas" : "2"
}
},
"mappings" : {
"_default_" : {
"_source_" : {
"enable" : false
}
}
},
"aliases" : { }
}
}
这通常用于一些业务不想关的存储中,比如日志、消息、重大错误预警等等都可以设置,只要这些重复的mapping是有规律的。
4.2.3.index routing索引路由配置
在es对数据进行分片的时候是采用hash取余的方式进行的,所以你可以传递一个固定的key,那么这个key将作为你固定的路由规则。在创建mappings的时候可以设置这个_routing参数。这在1.0的版本中是这样的设置的,也就是说你当前type下的所有document都是只能用着这个路由key进行。但是在es2.0之后routing跟着index元数据走,这样可以控制单个index的路由规则,在提交index的时候可以单独制定_routing参数,而不是直接设置mappings上。
在2.0之后已经不再支持mappings配置_routing参数了。
https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_20_mapping_changes.html#migration-meta-fields
在1.0里,比如,你可以将userid作为routing key,这样就可以将当前用户的所有数据都在一个分片上,当查询的时候就会加快查询速度。
{
"mappings": {
"post": {
"_routing": {
"required": true,
"path":"userid"
},
"properties": {
"contents": {
"type": "string"
},
"name": {
"store": true,
"type": "string"
},
"id": {
"store": true,
"type": "long"
},
"userId": {
"store": true,
"type": "long"
}
}
}
}
}
这个_routing是设置在mapping上的,作用于所有type。会使用userid作为sharding的key。但是在2.0里,是必须明确指定routing path的。

在你添加好mappings之后,创建当前索引的时候必须指定&routing=xxx,参数。这有个很大的好处就是你可以根据不同的业务维度自由调整分片策略。
5.总结
孰能生巧,分布式的东西还是有很多比较特殊和挑战的地方,尤其是他的分布性,同时还要解决很多一致性问题、可用性问题等等。我对elasticsearch的使用也只是个简单的皮毛而已,它的分布式特性深深的吸引了我,期待下篇文章更加深入的分享。比如,routing的内部原理,复制平衡算法等等。这篇文章是我对elasticsearch使用的一个简单的总结,希望能对各位博友有点帮助,谢谢阅读,谢谢支持。
参考书籍《ElasticSearch 可扩展的开源弹性搜索解决方案》、《ElastcSearch权威指南》。
作者:王清培
出处:http://www.cnblogs.com/wangiqngpei557/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面