(轉)ElasticSearch學習


ElasticSearch是一個基於Lucene構建的開源,分布式,RESTful搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。支持通過HTTP使用JSON進行數據索引。 
 
官方站點:http://www.elasticsearch.com/ 
中文站點:http://es-cn.medcl.net/  
 
 1.安裝 
 
必須先安裝Java環境,並設置 JAVA_HOME => C:\Program Files\Java\jdk1.6.0_18 
 
elasticsearch-rtf 中文入門集成包 https://github.com/medcl/elasticsearch-rtf 
使用git簽出,下載到本地。windows下,執行bin下面的elasticsearch.bat。linux下,執行bin下面或者service下面elasticsearch。  
 
 
 2.角色關系對照 
 
elasticsearch 跟 MySQL 中定義資料格式的角色關系對照表如下 
 
MySQL             elasticsearch 
database                 index 
table                         type 
 
table schema mapping 
row                          document 
field                         field  
 
 
 
 選用原因 
 
    主要原因有:實時性能優越;安裝配置簡單;RESTful API 和 JSON 格式的文檔型數據,降低開發調試的難度。 另外,Tire 這個 Gem 可以簡單方便的與 ActiveRecord 整合。 測試中發現:ES 自帶了中文分詞,支持中文搜索,但是,可以換用更高效精確的分詞插件。
    業界資訊:GitHub searches 20TB of data using Elasticsearch, including 1.3 billion files and 130 billion lines of code. 
 
簡單介紹 
 
    ElasticSearch 是開源搜索平台領域的一個新成員。 ElasticSearch(簡稱 ES) 是一個基於 Lucene 構建的開源,分布式,RESTful 搜索引擎。 設計用於雲計算中,能夠達到搜索實時、穩定、可靠和快速,並且安裝使用方便。 支持通過 HTTP 請求,使用 JSON 進行數據索引。 
 
 
 
 特點優勢 
 
    (1)Open Source(開源) 
    (2)Apache Lucene(基於 Lucene) 
    (3)Schema Free(模式自由) 
    (4)Document Oriented(面向文檔型的設計) 
    (5)Real Time Data & Analytics(實時索引數據) 
    (6)Distributed(分布式) 
    (7)High Availability(高可靠性) 
    (8)其他特性:RESTful API;JSON format;multi-tenancy;full text search;conflict management;per-operation persistence 
 
 
================================================ 
分布式搜索elasticsearch 中文分詞集成 
 
對於索引可能最關系的就是分詞了 一般對於es 來說默認的smartcn  但效果不是很好  
 
一個是ik的,一個是mmseg的,下面分別介紹下兩者的用法,其實都差不多的,先安裝插件,命令行: 
 
下載ik相關配置詞典文件到config目錄: 
    cd config 
 
    wget http://github.com/downloads/medcl/elasticsearch-analysis-ik/ik.zip --no-check-certificate 
 
    unzip ik.zip 
 
    rm ik.zip 
 
分詞配置 
ik分詞配置,在elasticsearch.yml文件中加上 
    index: 
      analysis:                    
        analyzer:       
          ik: 
          alias: [ik_analyzer] 
          type: org.elasticsearch.index.analysis.IkAnalyzerProvider 
或 
    index.analysis.analyzer.ik.type : “ik” 
 
安裝mmseg插件: 
    bin/plugin -install medcl/elasticsearch-analysis-mmseg/1.1.0 
下載相關配置詞典文件到config目錄 
    cd config 
 
    wget http://github.com/downloads/medcl/elasticsearch-analysis-mmseg/mmseg.zip --no-check-certificate 
 
    unzip mmseg.zip 
 
    rm mmseg.zip 
mmseg分詞配置,也是在在elasticsearch.yml文件中 
    index: 
      analysis: 
        analyzer: 
          mmseg: 
          alias: [news_analyzer, mmseg_analyzer] 
          type: org.elasticsearch.index.analysis.MMsegAnalyzerProvider 
          
 
mmseg分詞還有些更加個性化的參數設置如下 
    index: 
      analysis: 
        tokenizer: 
          mmseg_maxword: 
          type: mmseg 
          seg_type: "max_word" 
          mmseg_complex: 
          type: mmseg 
          seg_type: "complex" 
          mmseg_simple: 
          type: mmseg 
          seg_type: "simple" 
 
這樣配置完后插件安裝完成,啟動es就會加載插件。 
 
定義mapping 
 
在添加索引的mapping時就可以這樣定義分詞器 
 

   "page":{ 
      "properties":{ 
         "title":{ 
            "type":"string", 
            "indexAnalyzer":"ik", 
            "searchAnalyzer":"ik" 
         }, 
         "content":{ 
            "type":"string", 
            "indexAnalyzer":"ik", 
            "searchAnalyzer":"ik" 
         } 
      } 
   } 

 
 
indexAnalyzer為索引時使用的分詞器,searchAnalyzer為搜索時使用的分詞器。 
 
java mapping代碼如下: 
 
XContentBuilder content = XContentFactory.jsonBuilder().startObject() 
        .startObject("page") 
          .startObject("properties")        
            .startObject("title") 
              .field("type", "string")            
              .field("indexAnalyzer", "ik") 
              .field("searchAnalyzer", "ik") 
            .endObject()  
            .startObject("code") 
              .field("type", "string")          
              .field("indexAnalyzer", "ik") 
              .field("searchAnalyzer", "ik") 
            .endObject()      
          .endObject() 
         .endObject() 
       .endObject() 
 
 
測試分詞可用調用下面api,注意indexname為索引名,隨便指定一個索引就行了 
 
http://localhost:9200/indexname/_analyze?analyzer=ik&text=測試elasticsearch分詞器 
 
附: 
 
ik分詞插件項目地址:https://github.com/medcl/elasticsearch-analysis-ik 
 
mmseg分詞插件項目地址:https://github.com/medcl/elasticsearch-analysis-mmseg 
 
配置好的es版本,地址如下:https://github.com/medcl/elasticsearch-rtf 
 
================================================ 
 
cluster 
 
  代表一個集群,集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對於集群內部來說的。es的一個概念就是去中心化,字面上理解就是無中心節點,這是對於集群外部來說的,因為從外部來看es集群,在邏輯上是個整體,你與任何一個節點的通信和與整個es集群通信是等價的。 
 
 
shards 
 
  代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。構成分布式搜索。分片的數量只能在索引創建前指定,並且索引創建后不能更改。 
 
 
replicas 
 
  代表索引副本,es可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當個某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高es的查詢效率,es會自動對搜索請求進行負載均衡。 
 
 
recovery 
 
  代表數據恢復或叫數據重新分布,es在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行數據恢復。 
 
 
river 
 
  代表es的一個數據源,也是其它存儲方式(如:數據庫)同步數據到es的一個方法。它是以插件方式存在的一個es服務,通過讀取river中的數據並把它索引到es中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia的。 
 
 
gateway 
 
  代表es索引快照的存儲方式,es默認是先把索引存放到內存中,當內存滿了時再持久化到本地硬盤。gateway對索引快照進行存儲,當這個es集群關閉再重新啟動時就會從gateway中讀取索引備份數據。es支持多種類型的gateway,有本地文件系統(默認),分布式文件系統,Hadoop的HDFS和amazon的s3雲存儲服務。 
 
 
discovery.zen 
 
  代表es的自動發現節點機制,es是一個基於p2p的系統,它先通過廣播尋找存在的節點,再通過多播協議來進行節點之間的通信,同時也支持點對點的交互。 
 
 
Transport 
 
  代表es內部節點或集群與客戶端的交互方式,默認內部是使用tcp協議進行交互,同時它支持http協議(json格式)、thrift、servlet、memcached、zeroMQ等的傳輸協議(通過插件方式集成)。 
 
------------------------------------------------ 
 
雲計算平台(檢索篇)-Elasticsearch-配置篇 
 
ElasticSearch安裝好后我們需要對ElasticSearch的Config進行一系列配置,具體如下: 
 
  
 
cluster.name: rmscloud 
 
集群名稱 
 
  
 
node.name: "rcnode21" 
 
節點名稱 
 
  
 
node.tag: "tag21" 
 
節點標簽 
 
  
 
node.data: true 
 
節點是否存儲數據 
 
  
 
index.number_of_shards: 5 
 
索引分片數 
 
  
 
index.number_of_replicas: 1 
 
索引副本數 
 
  
 
path.data: /data/elasticsearch/data 
 
數據目錄存放位置 
 
  
 
path.logs: /data/elasticsearch/log 
 
日志數據存放位置 
 
bootstrap.mlockall: true 
 
內存 
 
  
 
index.cache.field.max_size: 500000 
 
索引緩存 
 
  
 
index.cache.field.expire: 5m 
 
索引緩引過期時間 
 
  
 
其它配置基本上不用調,具體可參考附錄。另外需要的調配置是分詞具體例子如下: 
 
index: 
 
  analysis: 
 
    tokenizer: 
 
      my_pinyin: 
 
          type: pinyin 
 
          first_letter: "prefix" 
 
          padding_char: "" 
 
      pinyin_first_letter: 
 
          type: pinyin 
 
          first_letter: "only" 
 
      mmseg_maxword: 
 
          type: mmseg 
 
          seg_type: "max_word" 
 
      mmseg_complex: 
 
          type: mmseg 
 
          seg_type: "complex" 
 
      mmseg_simple: 
 
          type: mmseg 
 
          seg_type: "simple" 
 
      semicolon_spliter: 
 
          type: pattern 
 
          pattern: ";" 
 
      pct_spliter: 
 
          type: "pattern" 
 
          pattern: "[%]+" 
 
  
 
    filter: 
 
      ngram_min_2: 
 
          max_gram: 10 
 
          min_gram: 2 
 
          type: nGram 
 
      ngram_min_1: 
 
          max_gram: 10 
 
          min_gram: 1 
 
          type: nGram 
 
      min2_length: 
 
          min:  2 
 
          max:  4 
 
          type: length 
 
  
 
    analyzer: 
 
      lowercase_keyword: 
 
          type: custom 
 
          filter: [standard,lowercase] 
 
          tokenizer: standard 
 
      lowercase_keyword_ngram_min_size1: 
 
          type: custom 
 
          filter: [ngram_min_1,standard,lowercase] 
 
          tokenizer: nGram 
 
      lowercase_keyword_ngram_min_size2: 
 
          type: custom 
 
          filter: [ngram_min_2,standard,lowercase,min2_length,stop] 
 
          tokenizer: nGram 
 
      lowercase_keyword_ngram: 
 
          type: custom 
 
          filter: [ngram_min_1,standard,lowercase] 
 
          tokenizer: nGram 
 
      lowercase_keyword_without_standard: 
 
          type: custom 
 
          filter: [lowercase] 
 
          tokenizer: keyword 
 
      lowercase_whitespace: 
 
          type: custom 
 
          filter: [lowercase] 
 
          tokenizer: whitespace 
 
      ik: 
 
          alias: [ik_analyzer] 
 
          type: org.elasticsearch.index.analysis.IkAnalyzerProvider 
 
      ike: 
 
          alias: [ike_analyzer] 
 
          type: org.elastichsearch.ik.index.IkAnalyzerProvider 
 
          usermode: true 
 
      mmseg: 
 
          alias: [mmseg_analyzer] 
 
          type: org.elasticsearch.index.analysis.MMsegAnalyzerProvider 
 
      comma_spliter: 
 
          type: "pattern" 
 
          pattern: "[,|\\s]+" 
 
      pct_spliter: 
 
          type: "pattern" 
 
          pattern: "[%]+" 
 
      custom_snowball_analyzer: 
 
          type: "snowball" 
 
          language: "English" 
 
      simple_english_analyzer: 
 
          type: "custome" 
 
          tokenizer: whitespace 
 
          filter: [standard,lowercase,snowball] 
 
      edge_ngram: 
 
          type: custom 
 
          tokenizer: edgeNGram 
 
          filter: [lowercase] 
 
      pinyin_ngram_analyzer: 
 
          type: custom 
 
          tokenizer: my_pinyin 
 
          filter: [standard,lowercase,nGram] 
 
      pinyin_first_letter_analyzer: 
 
          type: custom 
 
          tokenizer: pinyin_first_letter 
 
          filter: [standard,lowercase] 
 
      custom_auth_en_analyzer: 
 
          type: custom 
 
          tokenizer: semicolon_spliter 
 
          filter: [standard,snowball,lowercase,trim] 
 
  
 
index.analysis.analyzer.default.type : "keyword" 
 
  
 
  
 
進行完Config的配置后還需要對bin目錄下面的elastichsearch進行配置,此處主要是控制JVM的一些參數 
 
ES_MIN_MEM=27G 
 
ES_MAX_MEM=27G 
 
調整JVM的最大內存和最小內存就可以了,其它JVM參數見附錄。 
 
 
------------------------------------------------ 
 
雲計算平台(檢索篇)-Elasticsearch-Linux優化篇 
 
 Elasticsearch在Linux系統環境中運行,需要對Linux系統進行一系列調優,這樣可以提高ElasticSearch的檢索效率。主要的需要調優的參數如下: 
 
  
 
    1.       Linux調整文件數 
 
/etc/security/limits.conf 
 
在文件中增加 
 
* soft nofile 8192 
 
* hard nofile 20480 
 
* - memlock unlimited 
 
  
 
在登陸中添加下面命令行 
 
/etc/pam.d/login 
 
session  required  /lib64/security/pam_limits.so(在不同系統中文件位置不同) 
 
  
 
    2.       關閉文件的更新時間 
 
/etc/fstab 
 
在文件中添加一行 
 
/dev/sda7               /data/elasticsearch     ext4    noatime,nodiratime 0 0 
 
(此處的/dev/sda7 可以通過df –h查看目錄所在分區) 
 
    3.       修改防火牆設置 
 
為方便調適暫時關閉 
 
/etc/init.d/iptables stop 
 
 
 
------------------------------------------------ 
雲計算平台(檢索篇)-Elasticsearch-索引篇 
 
Es索引的我們可以理解為數據入庫的一個過程。我們知道Es是基於Lucene框架的一個分布式檢索平台。索引的同樣也是基於Lucene創建的,只不過在其上層做了一些封閉。 
 
         Es的索引過程比較通用的大體上有兩種方式,其一是得用自身Rvier從數據庫中拉數據,當然現在已經有了很多相關插件,Mysql、MDB等數據庫。這種方式可以做到近時實索引,因為River是定時從數據庫拉數據與索引數據進行比對。這種方式經較適合數據有周期的更新。 
 
         下面以Mysql-River  plugins為例: 
 
1、    安裝Mysql-River 插件 
 
bin/plugin -install /path/to/plugin/river-mysql.zip 
 
2、    當安裝好Mysql-River plugin 后,一般可以馬上使用,但建立重新加載Es集群。查看log中是否正確的加載了Mysql-River Plugin(在后面我們講到如何開發相關Plugin)。 
 
3、    配置Es索引與Mysql 數據之間的對應關系。 
 
建立索引(相關Mapping 信息如下:) 
 
curl -XPUT 127.0.0.1:9200/elasticsearchindexname/elasticsearchtypename/_mapping -d 
 
"elasticsearchtypename" : { 
 
                   "_timestamp":{ 
 
                            "enabled":true 
 
                   } 
 

 
                   將River索引的配置也提交到Es集群中: 
 
                   curl -XPUT 127.0.0.1:9200/_river/river-mysql/_meta –d 
 
                   { 
 
             "type":"mysql", 
 
                "mysql":{ 
 
        "index":"elasticsearchindexname",(索引名稱) 
 
        "type":"elasticsearchtypename",(類型) 
 
        "hostname":"127.0.0.1:3306",(服務器) 
 
        "database":"ESDATA",(數據庫名稱) 
 
        "username":"root",(用戶名) 
 
        "password":"",(密碼) 
 
        "uniqueIdField":"_ID",(標識) 
 
        "query":"select RID,PNAME FROM wf_mds_chn_biaozhun",(SQL語句) 
 
        "deleteOldEntries":"false", 
 
        "interval":"60000"(更新周期) 
 
    } 
 

 
同時你會在Es看到你的索引中開始導數據了,當然些時也會出現一個對應的保存配置的索引,現在很多River都只能索引字段與數據庫的字段一一對應。如果需要個性化定制,可以到Github上下載相關代碼進行修改。我們可以看到只要繼續River(接口)和AbstractRiverComponent(類)便可以進行相關開發了。 
 
public class MysqlRiver extends AbstractRiverComponent implements River 
 
  
 
         另外一種索引方式當然就是我們把數據Put到Es中去了,最簡單的我們可以用下面命令就完成: 
 
$ curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{ 
 
    "user" : "kimchy", 
 
    "post_date" : "2009-11-15T14:12:12", 
 
    "message" : "trying out Elastic Search" 
 
}' 
 
對上面的命令解釋一下: 
 
Twitter:索引名稱 
 
Tweet:類型名稱 
 
1:ID值 
 
具體我會在下篇中講解索引名稱和類型的關系,當然-d 后面的就是值了。這是單條Put數據的方式雖然簡單,但是如果說數據量很大的情況下還是不建議用這種方式,可以改用批量導入的方式也就是傳說中的Bluk了,Bluk原量很簡單,我們把數據放到緩存中,一次Put多條數據到Es集群中去,Bluk當然要用代碼實現了,給出一個例子如下: 
 
public static void Index() throws ElasticSearchException, IOException, NumberFormatException, SQLException { 
 
                   // TODO Auto-generated method stub 
 
                   // Node node = nodeBuilder().client(true).node(); 
 
                   Settings settings = ImmutableSettings.settingsBuilder() 
 
                                     .put("cluster.name", "elasticsearch_wf").build(); 
 
                   Client client = new TransportClient(settings) 
 
                                     .addTransportAddress(new InetSocketTransportAddress( 
 
                                                        "168.160.200.250", 9300)); 
 
                   
 
                   ////������е��ܼ�¼��ֳ�5000��һ�����ѯ 
 
                   int countRe=100000000; //MySqlClass.getCount("select count(*) from test"); 
 
                   if(countRe>0) 
 
                   { 
 
                            int readercount=1; 
 
                            if(countRe>5000) 
 
                            { 
 
                                     readercount=countRe%5000==0?countRe/5000:countRe/5000+1; 
 
                            } 
 
                            
 
                            ////ÿ�ζ�ȡ5000���¼ 
 
                            for(int j=0;j<readercount;j++) 
 
                            { 
 
                                     ResultSet rs = MySqlClass.executeQuery("select * from test"); 
 
                                     BulkRequestBuilder bulkRequest = client.prepareBulk(); 
 
                                     try { 
 
  
 
                                               if (rs != null) { 
 
                                                        int i = 1; 
 
                                                        while (rs.next()) { 
 
                                                                 bulkRequest.add(client.prepareIndex("qtest", String.valueOf(i++)).setSource( 
 
                                                                                    jsonBuilder().startObject() 
 
                                                                                                       .field("id", rs.getInt("id")) 
 
                                                                                                       .field("�й�", rs.getString("title")) 
 
                                                                                                       .field("AB_EN", rs.getString("descript")) 
 
                                                                                                       .field("AF_CN",rs.getString("text")) 
 
                                                                                                       .endObject())); 
 
                                                        } 
 
                                                        BulkResponse bulkResponse = bulkRequest.execute().actionGet(); 
 
                                                        if (bulkResponse.hasFailures()) { 
 
                                                                 /* has Failures handler Error */ 
 
                                                        } 
 
                                               } 
 
                                     } catch (Exception e) { 
 
                                               e.printStackTrace(); 
 
                                     } 
 
                            } 
 
                   } 
 
                   client.close(); 
 
         } 
 
上面只是一個簡單的例子,大量可以考慮用從線程方式,另外Client鏈接數其實還是比較占資源的,大家可以考慮將出封閉到一個鏈接池中,提供效率。 
 
         整個建索引的過程Es在Lucene的基礎上還是做了很多的優化,但主體上我們對應到Lucene里面基實就是如下代碼: 
 
         public class Index { 
 
         private IndexWriter writer = null; 
 
         private static Analyzer ANALYZER = new IKAnalyzer(); 
 
         private String FilePath = null; 
 
  
 
         public Index(String FilePath, String IndexPath) { 
 
                   try { 
 
                            IndexWriterConfig writerConfig = new IndexWriterConfig( 
 
                                               Version.LUCENE_36, ANALYZER); 
 
                            this.writer = new IndexWriter( 
 
                                               FSDirectory.open(new File(IndexPath)), writerConfig); 
 
                            this.FilePath = FilePath; 
 
                   } catch (Exception e) { 
 
                            e.printStackTrace(); 
 
                   } 
 
         } 
 
  
 
         /* 
 
          * Init Create Index 
 
          */ 
 
         public void Init() { 
 
                   try { 
 
                            if (FilePath.length() > 0) { 
 
                                     // 讀目錄中txt文件 
 
                                     File file = new File(FilePath); 
 
                                     List<File> files = new ArrayList<File>(); 
 
                                     this.ListAllFile(file, files); 
 
  
 
                                     // //將File轉換為 Document對象 
 
                                     for (File sfs : files) { 
 
                                               this.writer.addDocument(this.getDocument(sfs)); 
 
                                     } 
 
                            } 
 
                   } catch (Exception e) { 
 
                            e.printStackTrace(); 
 
                   } 
 
         } 
 
  
 
         /* 
 
          * Close Index 
 
          */ 
 
         public void Close() { 
 
                   try { 
 
                            this.writer.commit(); 
 
                            this.writer.close(); 
 
                   } catch (Exception e) { 
 
                            e.printStackTrace(); 
 
                   } 
 
         } 
 
  
 
         /* 
 
          * 獲取所有txt文件 
 
          */ 
 
         private List<File> ListAllFile(File fileOrDir, List<File> files) 
 
                            throws Exception { 
 
                   if (fileOrDir != null && files != null) { 
 
                            if (fileOrDir.isDirectory()) { 
 
                                     File[] fs = fileOrDir.listFiles(); 
 
                                     for (File sfs : fs) { 
 
                                               if (sfs.isDirectory()) 
 
                                                        this.ListAllFile(sfs, files); 
 
                                               else files.add(sfs); 
 
                                     } 
 
                            } else { 
 
                                     files.add(fileOrDir); 
 
                            } 
 
                   } 
 
                   return null; 
 
         } 
 
  
 
         /* 
 
          * Get Document 
 
          */ 
 
         private Document getDocument(File f) throws Exception { 
 
                   Document doc = new Document(); 
 
                   FileInputStream  is = new FileInputStream(f); 
 
                   byte[] buf = new byte[is.available()]; 
 
                   is.read(buf); 
 
                   String contentStr = new String(buf,"GBK"); 
 
                   Field content = new Field("content", contentStr, Field.Store.YES, 
 
                                     Field.Index.ANALYZED); 
 
                   doc.add(content); 
 
                   Field path = new Field("path", f.getAbsolutePath(), Field.Store.YES, 
 
                                     Field.Index.ANALYZED); 
 
                   Field size=new Field("size",String.valueOf(f.getTotalSpace()),Field.Store.YES,Field.Index.NOT_ANALYZED); 
 
                   doc.add(size); 
 
                   Random rm=new Random(); 
 
                   int year=rm.nextInt(20); 
 
                   Field time=new Field("time",String.valueOf(1990+year),Field.Store.YES,Field.Index.NOT_ANALYZED); 
 
                  doc.add(time); 
 
                   doc.add(path); 
 
                   is.close(); 
 
                   return doc; 
 
         } 
 

 
------------------------------------------------ 
雲計算平台(檢索篇)-Elasticsearch-Mapping篇 
 
         Es Mapping篇主要是講解Mapping的一些相關配置與需要注意的地方,說到Mapping大家可能覺得有些不解,其實我大體上可以將Es 理解為一個數據管理平台,那么index 當然就是庫了,type可以理解為表,mapping可以理解為表的結構和相關設置的信息(當然mapping有更大范圍的意思)。Mapping的作用域也是從cluster、node、index、type。 
 
curl -XPOST localhost:9200/wf_mds_org(索引名稱) -d '{ 
 
    "settings": { 
 
        "number_of_shards": 1, 
 
        "number_of_replicas": 0, 
 
        "index.refresh_interval": "-1", 
 
        "index.translog.flush_threshold_ops": "100000" 
 
    }, 
 
    "mappings": { 
 
        "org": {   //(類型) 
 
            "_all": { 
 
                "analyzer": "ike" 
 
            }, 
 
            "_source": { 
 
                "compress": true 
 
            }, 
 
            "properties": { 
 
                "_ID": { 
 
                    "type": "string", 
 
                    "include_in_all": true, 
 
                    "analyzer": "keyword" 
 
                }, 
 
                                     "NAME": { 
 
                    "type": "multi_field", 
 
                    "fields": { 
 
                        "NAME": { 
 
                            "type": "string", 
 
                            "analyzer": "keyword" 
 
                        }, 
 
                        "IKO": { 
 
                            "type": "string", 
 
                            "analyzer": "ike" 
 
                        } 
 
                    } 
 
                }, 
 
                                     "SHORTNAME": { 
 
                    "type": "string", 
 
                    "index_analyzer": "pct_spliter", 
 
                    "search_analyzer": "keyword", 
 
                    "store": "no" 
 
                }, 
 
                                     "OLDNAME": { 
 
                    "type": "multi_field", 
 
                    "fields": { 
 
                        "OLDNAME": { 
 
                            "type": "string", 
 
                            "analyzer": "keyword" 
 
                        }, 
 
                        "IKO": { 
 
                            "type": "string", 
 
                            "analyzer": "ike" 
 
                        } 
 
                    } 
 
                }, 
 
                                     "TNAME": { 
 
                    "type": "string", 
 
                    "analyzer":"custom_snowball_analyzer", 
 
                    "store": "no" 
 
                }, 
 
                                     "TSNAME": { 
 
                    "type": "string", 
 
                    "index": "no", 
 
                    "store": "no" 
 
                }, 
 
                                     "TONAME": { 
 
                    "type": "string", 
 
                    "index": "no", 
 
                    "store": "no" 
 
                } 
 
            } 
 
        } 
 
    } 
 
}' 
 
上面給出了一個完整Mapping,我們可將Mapping信息大致分成settings和mappings兩個部分,settings主要是作用於index的一些相關配置信息,如分片數、副本數等(分片和副本在es簡介中講過,更加詳細的東西會在索引優化篇中講)、tranlog同步條件、refresh條條等。Mappings部分主是要結果構的一些說明,mappings 我們可以看到主體上大致又分成_all、_source、properites這三個部分。 
 
1、_all:主要指的是All Field字段,我們可以將一個或都多個包含進不,在進行檢索時無需指定字段的情況下檢索多個字段。前提是你得開啟All Field字段 
 
"_all" : {"enabled" : true} 
 
2、_source:主要指的是Source Field字段Source可以理解為Es除了將數據保存在索引文件中,另外還有一分源數據。_source字段我在們進行檢索時相當重要,如果在{"enabled" : false}情況下默認檢索只會返回ID,你需通過Fields字段去倒索索引中去取數據,當然效率不是很高。如果覺得enabale:true時,索引的膨漲率比較大的情況下可以通過下面一些輔助設置進行優化: 
 
Compress:是否進行壓縮,建議一般情況下將其設為true 
 
"includes" : ["author", "name"], 
 
"excludes" : ["sex"] 
 
上面的includes和 excludes主要是針對默認情況下面_source一般是保存全部Bulk過去的數據,我們可以通過include,excludes在字段級別上做出一些限索。 
 
3、properites部分是最重要的部分主要是針對索引結構和字段級別上面的一些設置 
 
"NAME": { //字段項名稱對應lucene里面FiledName 
 
        "type": "string",//type為字段項類型 
 
        "analyzer": "keyword"//字段項分詞的設置對應Lucene里面的Analyzer 
 
        }, 
 
在Es中字段項的 type是一個很重要的概念,在Es中在Lucene的基礎上提供了比較多的類型,而這些類型對應這一些相關的檢索特性如 Date型 我可以使用 [2001 TO 2012]的方式進行范圍檢索等,Es 的類型有如下一些: 
 
簡單類型: 
 
String:字符型最常用的 
 
Integer:整型 
 
Long:長整型 
 
Float:浮點型 
 
Double:雙字節型 
 
Boolean:布爾型 
 
復雜類型: 
 
Array:數組型 
 
“lists”:{{“name”:”…”},{“name”:”…”}} 
 
Object:對象類型 
 
“author”:{“type”:”object”,”perperites”:{“name”:{“type”:”string”}}} 
 
說到Array和Object有一個性能上的問題,Es中提供了Facet檢索,據Es的作者提供的消息,在做Facet時object類型相比與array的內存要占用的少,但我本人經過測試效果不是很明顯有興趣的可以測試一下。 
 
Multi_field:多分詞字段,針對一個字段提供多種分詞方式 
 
Nested: 嵌入類型用的還是比較多的 
 
         類型常用的也就這些了,還有一些類型大家可以參考官網,另外一個比較重的方面的就是分詞了(analyzer),不管在目前任何檢索系統是分詞決定這檢索的查全與查准及索引的膨漲率等。在Es中analyzer的作用域也是從cluster、index、filed這三個作用域。Cluster的配置在配置中講過,下面以Field為主(另外具體的分詞一些相關東西會在分詞篇中講) 
 
Analyzer,在Lucene中是一個分詞器的概念,我們知道Es是建立在Lucene之上的,所以這里的Analzyer同樣的也適用,Mapping 中的Analyzer主在是指定字段采用什么分詞器,具體的程序和配置分詞在插件和配置都有過一些說明。 
 
Analyzer在Es中分為index_analyzer和search_analyzer 
 
Index_analzyer:指的是索引過程中采用的分詞器 
 
Search_analyzer:指的是檢索過程中采用的分詞器 
 
我們知道index和search是兩個過程,但是盡量保證這兩個過程和分詞方式一致這樣可以保證查全和查准,否則再牛B的分詞,index和search采用的不相同也是無用功。 
 
         與analyzer與之相關的就是別外一項index項 
 
"HC":{ "type":"string", "index":"no", "store":"no"} 
 
         Index表示該字段是否索引,如果index為no那個analyzer設為啥也沒用。 
 
最后是”store”項了store項表示該項是否存儲到倒索索引中去,並不是_source,當項mapping中還有很多可以設置和優化的地方,會面在慢慢討論。在mapping中index和store如果大家有時候覺得有點和source搞不清楚,大家可以參考lucene中的Field.Store.YES,Field.Index.NOT_ANALYZED,Field.Index等相關設置就比較明白了。 
 
----------------------------------------------- 
雲計算平台(檢索篇)-Elasticsearch-索引優化篇 
 
         ES索引優化篇主要從兩個方面解決問題,一是索引數據過程;二是檢索過程。 
 
索引數據過程我在上面幾篇文章中有提到怎么創建索引和導入數據,但是大家可能會遇到索引數據比較慢的過程。其實明白索引的原理就可以有針對性的進行優化。ES索引的過程到相對Lucene的索引過程多了分布式數據的擴展,而這ES主要是用tranlog進行各節點之間的數據平衡。所以從上我可以通過索引的settings進行第一優化: 
 
         "index.translog.flush_threshold_ops": "100000" 
 
         "index.refresh_interval": "-1", 
 
         這兩個參數第一是到tranlog數據達到多少條進行平衡,默認為5000,而這個過程相對而言是比較浪費時間和資源的。所以我們可以將這個值調大一些還是設為-1關閉,進而手動進行tranlog平衡。第二參數是刷新頻率,默認為120s是指索引在生命周期內定時刷新,一但有數據進來能refresh像lucene里面commit,我們知道當數據addDoucment會,還不能檢索到要commit之后才能行數據的檢索所以可以將其關閉,在最初索引完后手動refresh一之,然后將索引setting里面的index.refresh_interval參數按需求進行修改,從而可以提高索引過程效率。 
 
         另外的知道ES索引過程中如果有副本存在,數據也會馬上同步到副本中去。我個人建議在索引過程中將副本數設為0,待索引完成后將副本數按需量改回來,這樣也可以提高索引效率。 
 
         "number_of_replicas": 0 
 
         上面聊了一次索引過程的優化之后,我們再來聊一下檢索速度比較慢的問題,其實檢索速度快度與索引質量有很大的關系。而索引質量的好壞與很多因素有關。 
 
一、分片數 
 
分片數,與檢索速度非常相關的的指標,如果分片數過少或過多都會導致檢索比較慢。分片數過多會導致檢索時打開比較多的文件別外也會導致多台服務器之間通訊。而分片數過少為導至單個分片索引過大,所以檢索速度慢。 
 
在確定分片數之前需要進行單服務單索引單分片的測試。比如我之前在IBM-3650的機器上,創建一個索引,該索引只有一個分片,分別在不同數據量的情況下進行檢索速度測試。最后測出單個分片的內容為20G。 
 
所以索引分片數=數據總量/單分片數 
 
目前,我們數據量為4億多條,索引大小為近1.5T左右。因為是文檔數據所以單數據都中8K以前。現在檢索速度保證在100ms 以下。特別情況在500ms以下,做200,400,800,1000,1000+用戶長時間並發測試時最壞在750ms以下. 
 
二、副本數 
 
副本數與索引的穩定性有比較大的關系,怎么說,如果ES在非正常掛了,經常會導致分片丟失,為了保證這些數據的完整性,可以通過副本來解決這個問題。建議在建完索引后在執行Optimize后,馬上將副本數調整過來。 
 
大家經常有一個誤去副本越多,檢索越快,這是不對的,副本對於檢索速度其它是減無增的我曾做過實現,隨副本數的增加檢索速度會有微量的下降,所以大家在設置副本數時,需要找一個平衡值。另外設置副本后,大家有可能會出現兩次相同檢索,出現出現不同值的情況,這里可能是由於tranlog沒有平衡、或是分片路由的問題,可以通過?preference=_primary 讓檢索在主片分上進行。 
 
三、分詞 
 
其實分詞對於索引的影響可大可小,看自己把握。大家越許認為詞庫的越多,分詞效果越好,索引質量越好,其實不然。分詞有很多算法,大部分基於詞表進行分詞。也就是說詞表的大小決定索引大小。所以分詞與索引膨漲率有直接鏈接。詞表不應很多,而對文檔相關特征性較強的即可。比如論文的數據進行建索引,分詞的詞表與論文的特征越相似,詞表數量越小,在保證查全查准的情況下,索引的大小可以減少很多。索引大小減少了,那么檢索速度也就提高了。 
 
四、索引段 
 
索引段即lucene中的segments概念,我們知道ES索引過程中會refresh和tranlog也就是說我們在索引過程中segments number不至一個。而segments number與檢索是有直接聯系的,segments number越多檢索越慢,而將segments numbers 有可能的情況下保證為1這將可以提到將近一半的檢索速度。 
 
$ curl -XPOST 'http://localhost:9200/twitter/_optimize? max_num_segments =1' 
 
五、刪除文檔 
 
刪除文檔在Lucene中刪除文檔,數據不會馬上進行硬盤上除去,而進在lucene索引中產生一個.del的文件,而在檢索過程中這部分數據也會參與檢索,lucene在檢索過程會判斷是否刪除了,如果刪除了在過濾掉。這樣也會降低檢索效率。所以可以執行清除刪除文檔。 
 
$ curl -XPOST 'http://localhost:9200/twitter/_optimize? only_expunge_deletes =true' 
 
----------------------------------------------- 
ES JVM 設置 
 
JVM參數 
     
 
ES默認值 
     
 
環境變量名 
 
-Xms 
     
 
256m 
     
 
  
 
-Xmx 
     
 
1g 
     
 
  
 
-Xms   and –Xmx 
     
 
  
     
 
  
 
-Xmn 
     
 
  
     
 
  
 
-XX:MaxDirectMemorySize 
     
 
  
     
 
  
 
-Xss 
     
 
256k 
     
 
  
 
-XX:UseParNewGC 
     
 

     
 
  
 
-XX:UseConcMarkSweepGC 
     
 

     
 
  
              
    
 
-XX:CMSInitiatingOccupancyFraction 
           
 
75 
    
 
  
     
 
75 
     
 
  
 
-XX:UseCMSInitiatingOccupancyOnly 
     
 
  
     
 
  
 
-XX:UseCondCardMark 
     
 
  
     
 
  我們可以注意到ES JVM Heap內存設置為在256M在1GB之間. 
 
         這個設置是為在開發和示范環境中使用的,開發人員可以通過簡單地安裝ES就可以使用了,但是這樣的內存設置在很多情況下都是不夠用的,我在需要設置更大的值。 
 
 
 
ES_MIN_MEM/ES_MAX_MEM 用於控制jvm的堆內存,另外還有ES_HEAP_SEIZ,這樣我可以設置更多的堆內存用於ES,另外建議不在啟動內存堆平衡,因為這樣會浪費很大的性能。 
 
 ES_HEAP_NEWSIZE這個參數用於控制堆內存的子集,即新生代堆控制 
 
 ES_DIRECT_SIZE,我們可以對應到Direct Memory Size這個參數,在JVM管理數據中使用的是NIO,本機內存可以映射到虛擬地址空間,在X64的架構上更有效,在ES中沒有選擇進行設置,但是有一個問題,本機直接內存的分配不會受到Java堆大小的限制,但是即然是內存那肯定還是要受到本機物理內存(包括SWAP區或者Windows虛擬內存)的限制的,一般服務器管理員配置JVM參數時,會根據實際內存設置-Xmx等參數信息,但經常忽略掉直接內存,使得各個內存區域總和大於物理內存限制(包括物理的和操作系統級的限制),而導致動態擴展時出現OutOfMemoryError異常。 
 
 
 下面例出一些JVM參數設置 
 
JVM parameter    Garbage collector 
 
-XX:+UseSerialGC    serial collector 
 
-XX:+UseParallelGC    parallel collector 
 
-XX:+UseParallelOldGC    Parallel compacting collector 
 
-XX:+UseConcMarkSweepGC    Concurrent-Mark-Sweep ( CMS ) collector 
 
-XX:+UseG1GC         Garbage-First    collector (G1) 
 
 
UseParNewGC和UseConcMarkSweepGC是結並並行和行發性的垃圾回收機制,在JAVA6中將默認為UserParNewGC和UseGoncMarkSweepGC並禁用串行收集器. 
 
UseCondCardMark  將在在高度並發的情況下,將些值注釋掉 
 
總結: 
 
       1、修改MAX 和MIN Heap大小設置。 
 
         2、設置垃圾回收百分比 
 
         3、如果在JAVA7中禁用默認的G1垃圾回收機制。 
 
 
JVM內存分為如下幾段: 
 
         JVM CODE用於內部代碼存放 
 
         Noe-heap memory用於加載類 
 
         Stack memory 用於存放本地變量和線程操作數 
 
         Heap memory 存放引用類型對象 
 
         Direct Buffer,緩沖輸入,輸出數據    
 
         Heap memory大小設置是非常重要的,因為java的運行取決於一個合理的heap的大小,如果設置太小,在許多垃圾回收或是高性能的情況下就會出現OutOfMemory異常。如果堆太大,垃圾回收將需要更大的數據,該算法將要面對更高數量的存活堆,這樣操作系統也會面對較大的壓力。 
 
         Non-heap內存分配是由java應用程序自動設置的,沒有辦法控制這個參數,因為它是由JAVA應用程序代碼決定的。 
 
 
垃圾回收與Lucene段 
 
        在ES中的垃圾回收器是集用的CMS垃圾回收,這種回收器不是提高敢回收的效率可是降低了回收的次數,但是面對比較大的數據集合時,這種回收可能需要的時間更長。 
 
         而這種大的數據集合主要是在Lucene的索引中,因些可以將索引的段進行一行調優工作,提高GC的效率。 
 
index.merge.policy.segments_per_tier 
 
 
減少分頁 
 
         在大堆內存的情況下,如果內存不足時會與操作系統的SWAP空間進行分頁數據的交換,但是這種交換是非常慢的,這種會降低整體性能。 
 
垃圾回收器的選擇 
 
JAVA 7中的默認是G1垃圾回收器,這種回收器和CMS回收相對,他在於處理吞吐量,但是如果在大堆的情況下CMS回收器在性能上將超過G1. 
 
性能調優策略 
 
1、  收集日志 
 
2、  對日志進行分析 
 
3、  選擇你要優化的目標 
 
4、  計划優化 
 
5、  應用新有設置 
 
6、  監控程序在新設置后的運行情況 
 
7、  反復試嘗 
 
ES 垃圾回收日志格式 
 
將日志等級調用警告在垃圾回收時你能看到如下信息: 
 
 
LogFile 
     
 
說明 
 
Gc 
     
 
垃圾回收運行 
 
ParNew 
     
 
新生代垃圾回收器 
 
duration 2.6m 
     
 
垃圾回收花費時間 
 
collections [1]/[2.7m] 
     
 
一個收集器運行花費2.7M 
 
memory [2.4gb] 
     
 
預設2.4GB 
 
[2.3gb]/[3.8gb] 
     
 
現在使用2.3GB/總共3.8GB 
 
Code Cache [13.7mb]->[13.7mb]/[48mb] 
     
 
代碼緩存 
 
Par Eden Space [109.6mb]->[15.4mb]/[1gb] 
     
 
Par   Eden Space使用空間 
 
Par Survivor Space[136.5mb]->[0b]/[136.5mb] 
     
 
Par   Survivor Space 
 
CMS Old Gen [2.1gb]->[2.3gb]/[2.6gb] 
     
 
CMS Old Gen 
 
CMS Perm Gen [35.1mb]->[34.9mb]/[82mb] 
     
 
CMS Perm Gen 
 
  
 
建議: 
 
1、ES不要運行在6U22之前因之多版本的JDK存在許多的bug,盡量使用Sun/Oracle比較最出的JDK6-7因為里面修復很多bug. 
 
         如果在JAVA7正式發布的情況下最好使用JDK7(不過要到2013了) 
 
2、考慮到ES是一個比較新的軟件,利用最先的技術來獲取性能,盡量從JVM中來擠壓性能,另外檢索您的操作系統是否是最新版的,盡量使用最新版的操作系統。 
 
3、做好隨時更新JAVA版本和ES的版本的情況,因為每季度或是每年都會有新的版本出來。所以在做好版本更新的准備 
 
4、測試從小到大,因為ES的強在多個節點的部署,一個節點是不足以測試出其性能,一個生產系統至少在三個節點以上。 
 
5、測試JVM 
 
6、如果索引有更新請記住對索引段的操作(index.merge.policy.segments_per_tier) 
 
7、在性能調優之前,請先確定系統的最大性能和最大吞吐量 
 
8、啟用日志記錄對JAVA垃圾回怍機制,有助於更好的診斷,以至於來調整你的系統 
 
9、提高CMS垃圾收集器,您可以添加一個合理的- xx:CMSWaitDuration參數 
 
10、如果堆大小趣過6-8GB,請選擇使用CMS 
 
 
 
 
 
----------------------------------------------- 
ElasticSearch教程(3)——ElasticSearch的插件 
更多 0 
插件 ElasticSearch 教程 
 
插件作為一種普遍使用的,用來增強原系統核心功能的機制,得到了廣泛的使用,elasticsearch也不例外。 
1. 安裝elasticsearch插件 
 
從0.90.2安裝其實很簡單,有三種方式, 
 
1.1 在確保你網絡順暢的情況下,執行如下格式的命令即可: 
 
plugin --install <org>/<user/component>/<version> 
 
 具體的<org>/<user/component>/<version>可參加各插件的使用說明。 
 
1.2  如果網絡不太順暢,可以下載好插件的壓縮包后以如下方式安裝: 
 
bin/plugin --url file://path/to/plugin --install plugin-name 
 
1.3 你也可以直接將插件的相關文件拷貝到plugins目錄下面,需要注意的是,這種方式需要特別留意插件的種類。 
2. 如何查看當前已經加載的插件 
 
curl -XGET 'http://localhost:9200/_nodes/plugin' 
 
 或者可以指定某個實例 
 
curl -XGET 'http://localhost:9200/_nodes/10.0.0.1/plugin' 
 
3. 個人強力推薦的插件 
 
要想知道整個插件的列表,請訪問http://www.elasticsearch.org/guide/reference/modules/plugins/ 插件還是很多的,個人認為比較值得關注的有以下幾個,其他的看你需求,比如你要導入數據當然就得關注river了。 
 
3.1 BigDesk 
 
該插件可以查看集群的jvm信息,磁盤IO,索引創建刪除信息等,適合查找系統瓶頸,監控集群狀態等,可以執行如下命令進行安裝,或者訪問項目地址:https://github.com/lukas-vlcek/bigdesk 
 
bin/plugin -install lukas-vlcek/bigdesk 
 
 說明:ElasticSearch HQ功能跟這個插件也很強大。 
 
3.2 Head 
 
可以查看索引情況,搜索索引,查看集群狀態和分片分布等,可以執行如下命令進行安裝,或者訪問項目地址:https://github.com/mobz/elasticsearch-head 
 
bin/plugin -install mobz/elasticsearch-head 
 
 3.3 elasticsearch中文分詞插件 
 
官方的中文分詞插件:Smart Chinese Analysis Plugin 
 
Medcl開發的中午分詞插件: IK Analysis Plugin  以及 Pinyin Analysis Plugin 
 
3.4 ZooKeeper Discovery Plugin 
 
elasticsearch 默認是使用Zen作為集群發現和存活管理的,ZooKeeper作為一個分布式高可用性的協調性系統,在這方面有着天然的優勢,如果你比較信任zookeeper,那么你可以使用這個插件來替代Zen。 
 
總結:本文主要介紹了elasticsearch的插件安裝方法,如何查看當前加載的插件的方法,以及個人認為比較值得關注的一些插件。

 

REFERENCE FROM : http://www.cnblogs.com/Jrain/p/3595390.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM