您的位置:首页 > 其它

ES学习2

2016-01-13 22:53 337 查看
1:es中的分页
一般搜索引擎中的分页都不会提供很大的页面查询,因为查询的页码越大,查询效率越低。
例子:
我们就先预想一下我们在搜索一个拥有5个主分片的索引。当我们请求第一页搜索的时
候,每个分片产生自己前十名,然后将它们返回给请求节点,然后这个节点会将50条
结果重新排序以产生最终的前十名。

现在想想一下我们想获得第1,000页,也就是第10,001到第10,010条结果,与之前同理,
每一个分片都会先产生自己的前10,010名,然后请求节点统一处理这50,050条结果
,然后再丢弃掉其中的50,040条!
现在你应该明白了,在分布式系统中,大页码请求所消耗的系统资源是呈指数式增长的。
这也是为什么网络搜索引擎不会提供超过1,000条搜索结果的原因。

2:es中的timeout
如果索引数据确实很多,查询速度不理想的话,可以使用超时时间,当查询的时间达
到指定的超时时间时,就直接把已经查到的那一部分数据返回给用户,这样不会
影响用户体验。但是返回的数据可能就不是非常准确了。
使用方法(10毫秒之后必须返回数据)
curl -XGET http://localhost:9200/_search?timeout=10ms 
java代码
在查询的位置添加下面代码
client.prepareSearch("crxy").setTimeout("10")

3:多索引和多类型查询
参考ppt中的代码即可。

4:ES中集成IK中文分词工具
1:下载es-ik插件,下载压缩文件为:elasticsearch-analysis-ik-master.zip https://github.com/medcl/elasticsearch-analysis-ik 2:编译插件源码
在本地windows机器解压:elasticsearch-analysis-ik-master.zip
cd elasticsearch-analysis-ik-master
mvn clean package -DskipTests
执行打包命令之后会生成对应的插件包,
位置在 elasticsearch-analysis-ik-master\target\releases下面的elasticsearch-analysis-ik-1.2.9.zip

把这个(elasticsearch-analysis-ik-1.2.9.zip)zip包上传到es服务器上的插件目录中(目录位置:/usr/local/elasticsearch-1.4.4/plugins/analysis-ik)
上传过去之后再解压
cd /usr/local/elasticsearch-1.4.4/plugins/analysis-ik
unzip elasticsearch-analysis-ik-1.2.9.zip
rm -f elasticsearch-analysis-ik-1.2.9.zip
3:把es-ik插件中的配置文件目录上上传到目录/usr/local/elasticsearch-1.4.4/conf
注意:es-ik插件中的配置文件目录是指elasticsearch-analysis-ik-master\config下面的ik目录,需要把这个目录这个上传到ES_HOME的conf目录下。

4:修改elasticsearch.yml文件
cd /usr/local/elasticsearch-1.4.4/conf
vi elasticsearch.yml(在里面添加下面一行配置)
index.analysis.analyzer.default.type: ik

5:测试分词效果
需要先创建crxy索引库
curl 'http://localhost:9200/crxy/_analyze?analyzer=ik&pretty=true' -d '{"text":"我们是中国人"}'

5:es中的settings和mappings
settings可以指定索引库的分片数量和副本数量
查看settings信息
curl -XGET http://localhost:9200/crxy/_settings?pretty 例子:
(操作不存在索引)
curl -XPUT 'localhost:9200/crxy/' -d'{"settings":{"number_of_shards":3,"number_of_replicas":2}}'
(操作已存在索引)
curl -XPUT 'localhost:9200/crxy/_settings' -d'{"index":{"number_of_replicas":2}}'

java代码操作参考Estest.java

mappings相当于solr中的schema.xml文件,也相当于mysql中的表结构信息,
通过它可以指定es中字段的一些基本属性。
当然,默认情况下,es中有自动映射的功能,不需要给未知的字段设置基本属性。

查看mappings信息
curl -XGET http://localhost:9200/crxy/emp/_mapping?pretty 注意:下面可以使用indexAnalyzer定义分词器,也可以使用index_analyzer定义分词器
操作不存在的索引
curl -XPUT 'localhost:9200/crxy1' -d'{"mappings":{"emp":{"properties":{"name":{"type":"string","indexAnalyzer": "ik","searchAnalyzer": "ik"}}}}}'
操作已存在的索引
curl -XPOST http://localhost:9200/crxy/emp/_mapping -d'{"properties":{"name":{"type":"string","indexAnalyzer": "ik","searchAnalyzer": "ik"}}}'

6:es中源码编辑打包
(不需要上传服务器,在本地windows上执行即可)
1:下载源码,下载的源码包为elasticsearch-1.4.zip https://github.com/elastic/elasticsearch/tree/1.4 2:解压源码到当前目录
3:打包
cd elasticsearch-1.4
mvn clean package -DskipTests
4:在elasticsearch-1.4\target\releases\目录下面会有如下两个文件
elasticsearch-1.4.6-SNAPSHOT.tar.gz
elasticsearch-1.4.6-SNAPSHOT.zip
这个就和我们在官网下载的es的tar包一致。

7:es中的查询查询
默认是randomize across shards
随机选取,表示随机的从分片中取数据
_local:指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。
_primary:指查询只在主分片中查询
_primary_first:指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。
_only_node:指在指定id的节点里面进行查询,如果该节点只有要dx查询索引的部分分片,就只在这部分分片中查找,所以查询结果可能不完整。如_only_node:123在节点id为123的节点中查询。
_prefer_node:nodeid 优先在指定的节点上执行查询
_shards:0 ,1,2,3,4:查询指定分片的数据

自定义查询方式:可以让用户指定查询多个节点的数据
查询方式:_only_nodes

想要自定义查询方式,需要修改源码,先把源码导入到eclipse中。
es的源码为maven项目,直接导入maven项目即可。、
导入进去之后,pom文件会报错,只有最下面的plugin中的一些配置会报错,可以忽略。
在导入到eclipse之后,会弹出窗口,直接点击canle即可。

下面就需要修改源码了、
找到这个类:-org.elasticsearch.cluster.routing.operation.plain.PlainOperationRouting
使用ctrl +o 可以弹出这个类中的所有方法,找到这个方法preferenceActiveShardIterator

点击171行代码,进入parse方法

在parse方法中的switch语句中增加判断,
case "_only_nodes":
return ONLY_NODES;

还需要这个类的61行部分,添加一个枚举参数
ONLY_NODES("_only_nodes");

返回这个类org.elasticsearch.cluster.routing.operation.plain.PlainOperationRouting

分析207行下面的代码,在这里判断了不同的查询方式
在switch语句中添加下面代码
case ONLY_NODES:
String nodeIds = preference.substring(Preference.ONLY_NODES.type().length() + 1);
String[] split = nodeIds.split(",");
for (String node : split) {
ensureNodeIdExists(nodes, node);
}
return indexShard.onlyNodesActiveInitializingShardsIt(nodeIds);

进入这个类org.elasticsearch.cluster.routing.IndexShardRoutingTable

在366行下面添加如下代码即可
public ShardIterator onlyNodesActiveInitializingShardsIt(String nodeIds) {
String[] split = nodeIds.split(",");
ArrayList<ShardRouting> ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size());
for (String nodeId : split) {
// fill it in a randomized fashion
for (int i = 0; i < activeShards.size(); i++) {
ShardRouting shardRouting = activeShards.get(i);
if (nodeId.equals(shardRouting.currentNodeId())) {
ordered.add(shardRouting);
}
}
for (int i = 0; i < allInitializingShards.size(); i++) {
ShardRouting shardRouting = allInitializingShards.get(i);
if (nodeId.equals(shardRouting.currentNodeId())) {
ordered.add(shardRouting);
}
}
}
return new PlainShardIterator(shardId, ordered);
}

到这就修改完了,参考第6步的源码编译和打包过程,

把打好的包上传到服务器上面启动即可。

[b]具体思路,可以参照:http:[/b][b]//www.cnblogs.com/cxzdy/p/5128778.html[/b]

8:es集群的脑裂问题
所谓脑裂问题(类似于精神分裂),就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。 http://bbs.superwu.cn/forum.php?mod=viewthread&tid=1161&extra=[/code]   es集群的脑裂问题

    

所谓脑裂问题(类似于精神分裂),就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。


    http://blog.csdn.net/cnweike/article/details/39083089
    

discovery.zen.minimum_master_nodes


    用于控制选举行为发生的最小集群节点数量。推荐设为大于1的数值,因为只有在2个以上节点的集群中,主节点才是有意义的。

  脑裂:(T)如在同一集群上,A节点发现可用的有2个节点,在B上发现有4个可用。可用节点数量不一致。本应所有都是一样的。



————————————————————————————————————————————————————————————————————

1:es优化
1)调大系统的"最大打开文件数",建议32K甚至是64K
ulimit -a (查看)
ulimit -n 32000(设置)
(索引文件越来越多,可能没合并)
2)修改配置文件调整ES的JVM内存大小
1:修改bin/elasticsearch.in.sh中ES_MIN_MEM和ES_MAX_MEM的大小,
建议设置一样大,避免频繁的分配内存,根据服务器内存大小,
一般分配60%左右(默认256M)
2:如果使用searchwrapper插件启动es的话则修改bin/service/elasticsearch.conf(默认1024M)
3)设置mlockall来锁定进程的物理内存地址
避免交换(swapped)来提高性能
修改文件conf/elasticsearch.yml
bootstrap.mlockall: true

4)分片和副本
分片多的话,可以提升建立索引的能力,5-20个比较合适。
如果分片数过少或过多,都会导致检索比较慢。分片数过多会导致检索时打开
比较多的文件,另外也会导致多台服务器之间通讯。而分片数过少会导至
单个分片索引过大,所以检索速度慢。建议单个分片最多存储20G左右的
索引数据,所以,分片数量=数据总量/20G
副本多的话,可以提升搜索的能力,但是如果设置很多副本的话也会对服务器
造成额外的压力,因为需要同步数据。所以建议设置2-3个即可。

5)要定时对索引进行优化,不然segment越多,查询的性能就越差
索引量不是很大的话情况下可以将segment设置为1
curl -XPOST 'http://localhost:9200/crxy/_optimize?max_num_segments=1'
java代码:client.admin().indices().prepareOptimize("crxy").setMaxNumSegments(1).get();

6)删除文档:
在Lucene中删除文档,数据不会马上在硬盘上除去,
而是在lucene索引中产生一个.del的文件,而在检索过程中这部分数据也会
参与检索,lucene在检索过程会判断是否删除了,如果删除了在过滤掉。
这样也会降低检索效率。所以可以执行清除删除文档
curl -XPOST 'http://localhost:9200/crxy/_optimize?only_expunge_deletes=true'
client.admin().indices().prepareOptimize("crxy").setOnlyExpungeDeletes(true).get();
7)如果在项目开始的时候需要批量入库大量数据的话,建议将副本数设置为0
因为es在索引数据的时候,如果有副本存在,数据也会马上同步到副本中,
这样会对es增加压力。待索引完成后将副本按需要改回来。
这样可以提高索引效率

8)去掉mapping中_all域,Index中默认会有_all的域,
(相当于solr配置文件中的拷贝字段text),这个会给查询带来方便,
但是会增加索引时间和索引尺寸
"_all":{"enabled":"false"}

9)log输出的水平默认为trace,即查询超过500ms即为慢查询,就要打印日志,
造成cpu和mem,io负载很高。把log输出水平改为info,可以减轻服务器的压力。
修改ES_HOME/conf/logging.yaml文件
或者修改ES_HOME/conf/elasticsearch.yaml

2:通过反射获取es的客户端
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
public class EsUtil {
// 设置client.transport.sniff为true来使客户端去嗅探整个集群的状态,把集群中其它机器的ip地址加到客户端中,
static Settings settings = ImmutableSettings.settingsBuilder()
.put("cluster.name", "elasticsearch")
.put("client.transport.sniff", true).build();
// 创建私有对象
private static TransportClient client;
static {
try {
Class<?> clazz = Class.forName(TransportClient.class.getName());
Constructor<?> constructor = clazz
.getDeclaredConstructor(Settings.class);
constructor.setAccessible(true);
client = (TransportClient) constructor.newInstance(settings);
client.addTransportAddress(new InetSocketTransportAddress(
"192.168.1.170", 9300));
} catch (Exception e) {
e.printStackTrace();
}
}
public static synchronized TransportClient getTransportClient() {
return client;
}

3:es需要注意的问题
1:使用java代码操作es的时候,尽量保证本地使用es依赖的版本和es集群中es的版本一致
2:es集群中各个节点的es版本和配置要保持一致,并且jdk也保持一致,

4:es中数据的分片规则
分析这个类org.elasticsearch.cluster.routing.operation.plain.PlainOperationRouting中的sharid方法

这个方法返回的就是数据存在的分片ID
分析源码可以发现,如果没有指定routing分片规则,那么会根据数据的id和分片的总数量求模,再求绝对值。
也就是说,如果是5个分片的话,返回的结果一定是0-4

还可以通过指定routing,把相同分类的数据保存到同一个分片中,
这样就可以利用前面讲的使用分片查询方式来查询指定的分片。

例子:
curl -XPOST 'localhost:9200/crxy/emp?routing=test' -d '{"name":"zs","age":20,"flag":"test"}'
java代码的实现,参考ppt或者estest.java

5:es+hbase实例

hbase建表语句
create 'article','info';

1:分析数据
id 存储,建立索引
title 存储,建立索引
author 存储,不建立索引
describe 存储,建立索引
content 不存储,不键索引

2:配置es
因为我们添加的是中文数据,所以需要使用中文分词工具
整合IK
1:先把打包之后的Ik压缩包拷贝到ES_HOME/plugins/analysis-ik目录下
在IK插件源码的这个位置找压缩包\elasticsearch-analysis-ik-master\target\releases
把elasticsearch-analysis-ik-1.2.9.zip 上传到ES_HOME/plugins/analysis-ik

2:在服务器上解压IK插件
cd /usr/local/elasticsearch-1.4.4/plugins/analysis-ik
unzip elasticsearch-analysis-ik-1.2.9.zip
rm -f elasticsearch-analysis-ik-1.2.9.zip

3:把ik源码下面的config目录下的ik目录,上传到服务器上的ES_HOME/config目录下

4:修改配置文件
cd /usr/local/elasticsearch-1.4.4/config
vi elasticsearch.yml
index.analysis.analyzer.default.type: ik

5:重启es
6:验证整合效果
先创建一个索引库
curl -XPUT 'localhost:9200/crxy'
curl 'http://localhost:9200/crxy/_analyze?analyzer=ik&pretty=true' -d '{"text":"超人学院"}'

7:针对我们要加载的数据,设计settings和mappings信息

vi crxy.json

{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
},
"mappings":{
"article":{
"dynamic":"strict",
"_all":{"enabled":"false"},
"properties":{
"id":{"type":"long","store":"yes"},
"title":{"type":"string","store":"yes","indexed":"analyzed","analyzer":"ik"},
"author":{"type":"string","store":"yes","indexed":"no"},
"describe":{"type":"string","store":"yes","indexed":"analyzed","analyzer":"ik"}
}

}
}

curl -XPUT 'localhost:9200/crxy' -d @crxy.json

3:执行es_hbase中的cn.crxy.spider.web.dataimport.DataImportAndIndex

4:启动项目

5:访问:http://localhost:8080/article
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: