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步的源码编译和打包过程, 把打好的包上传到服务器上面启动即可。 具体思路,可以参照:http://www.cnblogs.com/cxzdy/p/5128778.html 8:es集群的脑裂问题 所谓脑裂问题(类似于精神分裂),就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。 http://bbs.superwu.cn/forum.php?mod=viewthread&tid=1161&extra=
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实例 参考<es+hbase项目步骤.txt>
时间: 2024-10-14 13:01:40