ES学习2

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

ES学习2的相关文章

OpenGL ES学习笔记(二)&mdash;&mdash;平滑着色、自适应宽高及三维图像生成

首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <Android学习笔记--OpenGL ES的基本用法.绘制流程与着色器编译>中实现了OpenGL ES的Android版HelloWorld,并且阐明了OpenGL ES的绘制流程,以及编译着色器的流程及注意事项.本文将从现实世界中图形显示的角度,说明OpenGL ES如何使得图像在移动设备上显示的更加真实.首先,物体有各种颜色

OpenGL ES学习资料总结

从今年春节后开始学习OpenGL ES,发现网上资料很有限,而且良莠不齐,所以整理了一下我学习时用到的资料和一些心得. 1. OpenGL ES1.x参考资料 把NEHE的教程移植到了Android上,当然用的是ES1 http://insanitydesign.com/wp/projects/nehe-android-ports/ 2. OpenGL ES2.x参考资料 有很多Android上ES2应用的文章 http://tangzm.com/blog/?p=20 特别好的书,网上有英文版p

Elasticsearch之es学习工作中遇到的坑(陆续更新)

1:es集群脑裂问题(不要用外网ip,节点角色不要混用) 原因1:阿里云服务器,外网有时候不稳定. 解决方案:单独采购服务器,内网安装 原因2:master和node节点没有分开 解决方案: 分角色:master节点(三台),data节点(随着数据增加而增加),client(随着查询压力而增加)节点 Master节点:node.master: true   node.data: false Data节点:node.master: false   node.data: true Client 节点

Es学习第六课, ES基本搜索_search

前面几课ES的基本概念.安装和分词都讲过了,下面我们就来实战一下ES的核心功能-搜索,这节课我们主要讲的是基本搜索 _search(注意:ES的关键字都要加前缀_,所以我们在定义索引.类型名称时不要带_). 我们先通过kibana插入几条三个文档 PUT /customer/doc/1?pretty { "name": "John Doe" } POST /customer/doc/ { "title": "My second blog

Es学习第七课, term、terms、match等基本查询语法

term.terms查询 term query会去倒排索引中寻找确切的term,它并不知道分词器的存在,这种查询适合keyword.numeric.date等明确值的 term:查询某个字段里含有某个关键词的文档 GET /customer/doc/_search/ { "query": { "term": { "title": "blog" } } } terms:查询某个字段里含有多个关键词的文档 GET /custome

ES学习之分片路由

本文主要内容: 1.路由一个文档到一个分片 2.新建.索引和删除请求 3.取回单个文档 4.局部单个文档 5.多文档模式 6.理解一下ES深度分页(from-size)的劣势 路由一个文档到一个分片 当索引一个文档的时候,文档会被存储到一个主分片中. Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢? 首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了.实际上,这个过程是根据下面

es学习(三):分词器介绍以及中文分词器ik的安装与使用

什么是分词 把文本转换为一个个的单词,分词称之为analysis.es默认只对英文语句做分词,中文不支持,每个中文字都会被拆分为独立的个体. 示例 POST http://192.168.247.8:9200/_analyze { "analyzer":"standard", "text":"good good study" } # 返回 { "tokens": [ { "token":

ES学习笔记

变量的解构赋值 1.圆括号使用 var [(a)] = [1]; //报错,变量声明语句中,不能带有圆括号.[(a)] = [1]; //正确,模式是取数组的第一个成员,跟圆括号无关. 2.遍历Map结构 任何部署了Iterator接口的对象,都可以用for...of循环遍历.Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便. var map = new Map(); map.set('first', 'hello'); map.set('second', '

OpenGL ES 学习教程(十三) Stencil_TEST(模板缓冲测试)

模板缓冲测试,是指 将模版缓冲区中的值 与 一个参考值 进行比较,根据比较的结果,来对缓冲区中的值进行修改.进而决定该片段是否有效. 在应用中的体现就比如:Unity中的Mask . 大致的工作流程: 1.第一次Draw的时候,将所有的片段都设置为不通过模版测试.然后修改模版缓冲区的值,比如+1. 2.第二次Draw的时候,给定一个值 与 模版缓冲区中的值进行比较,比如用 1 与模版缓冲区中的值进行比较 . 因为第一步中,已经+1,所以模版缓冲区中值已经是1,然后用相等 作为条件判定 模版测试通