码迷,mamicode.com
首页 > 其他好文 > 详细

ES学习2

时间:2016-01-13 23:43:31      阅读:502      评论:0      收藏:0      [点我收藏+]

标签:

 

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>
    
    
    

 

ES学习2

标签:

原文地址:http://www.cnblogs.com/cxzdy/p/5128801.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!