本文主要討論es加載速度的優(yōu)化,有些優(yōu)化會導(dǎo)致部分功能及數(shù)據(jù)安全性喪失释簿,需要理性使用庶溶。
網(wǎng)絡(luò)中大部分的性能優(yōu)化方案基本源于官網(wǎng)捌肴,如下位置:
以下優(yōu)化包含但不限于官方文檔:
整體寫入操作影響因子:
1. indice相關(guān)設(shè)置
{
"settings": {
"number_of_shards": n,//分片盡量設(shè)置多一些酿联,能提高加載速度
"number_of_replicas": 0,//副本設(shè)置為0夺巩,喪失數(shù)據(jù)安全性
"refresh_interval": "-1",//刷新時間設(shè)置為-1劲够,喪失數(shù)據(jù)實時性
"merge": {
"scheduler": {
"max_thread_count": "1" //合并時最大線程數(shù)
},
"policy": {
"max_merged_segment": "5gb",//段超過多大就不參與合并
"segments_per_tier": "24"
}
},
"translog.durability": "async",//異步translog,后續(xù)具體分析
"translog.flush_threshold_size": "2gb",//這個參數(shù)表示在當(dāng)未提交的translog日志達(dá)到該閾值的時候進(jìn)行一次刷盤操作蹲姐。
"translog.sync_interval": "100s"
},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "keyword",
"doc_values":false, //不存儲doc,喪失聚合排序等功能
"index":false //不索引柴墩,喪失查詢功能
}
}
}
}
}
2. cluster相關(guān)設(shè)置
indices.memory.index_buffer_size: 30% //加大索引數(shù)據(jù)的緩存
discovery.zen.ping_timeout: 60s //超時時間江咳,默認(rèn)3s
discovery.zen.fd.ping_interval: 30s //節(jié)點多久ping一次master,默認(rèn)1s
discovery.zen.fd.ping_timeout: 60s //等待響應(yīng)時間爹土,默認(rèn)30s
discovery.zen.fd.ping_retries: 6 //失敗或超時后重試的次數(shù)踩身,默認(rèn)3
thread_pool.write.size: cpus+1 //設(shè)置寫線程數(shù)挟阻,默認(rèn)cpus
thread_pool.write.queue_size: 2000 //加大數(shù)據(jù)寫隊列,默認(rèn)200
具體分析以上配置:
3. 關(guān)閉某些存儲結(jié)構(gòu)
不需要聚合:doc_values:false
不需要返回數(shù)據(jù):_source:false
不需要檢索:index:false
不算分:norms:false
能用keyword就不用text
Index_options設(shè)置倒排索引具體內(nèi)容
……
4. bulk合理使用
Resthighclient和Bulkprocess.add()均為線程安全脱拼,可多線程調(diào)用一個實例添加數(shù)據(jù)挪拟。
控制client提交bulk在多節(jié)點間輪訓(xùn)(client.transport.sniff :true/restclient添加多個節(jié)點)
設(shè)置bulk thread_poll線程數(shù)為cpu+1 击你,增大隊列2000(不要太大丁侄,會GC)
setBulkSize(5mb):大小建議是5-15MB朝巫,默認(rèn)不能超過100M
bulkActions(1000):1000-5000個文檔,如果你的文檔很大拙吉,可以適當(dāng)減少隊列
bulk的concurrentRequests:默認(rèn)是1
多線程并發(fā)寫入筷黔,可以減少每次底層磁盤fsync的次數(shù)和開銷仗颈。
一旦發(fā)現(xiàn)es返回了TOO_MANY_REQUESTS的錯誤,JavaClient也就是EsRejectedExecutionException请祖。此時那么就說明es是說已經(jīng)到了一個并發(fā)寫入的最大瓶頸了肆捕。
如果加載過程中檢測到HTTP429返回表示集群壓力過大
5. 增加/禁用refresh間隔
refresh默認(rèn)1s:用index.refresh_interval參數(shù)可以設(shè)置,這樣會其強(qiáng)迫es每秒中都將內(nèi)存中的數(shù)據(jù)寫入磁盤中眼虱,創(chuàng)建一個新的segment file蒙幻。
延長或者禁止refresh
PUT /test/_settings
{ "refresh_interval": "30s" }
PUT /test/_settings
{ "refresh_interval": -1 }
手動刷新數(shù)據(jù)查詢:
POST /_refresh
POST /test/_refresh
6. 關(guān)閉swap 內(nèi)存交換
如果要將es jvm內(nèi)存交換到磁盤,再交換回內(nèi)存胆筒,大量磁盤IO邮破,性能很差。
將/etc/fstab 文件中包含swap的行注釋掉
sed -i '/swap/s/^/#/' /etc/fstab
系統(tǒng)關(guān)閉:
swapoff -a/vm.swappiness = 1
es鎖定內(nèi)存:
2.4以前:
bootstrap.mlockall: true
新版本:
bootstrap.memory_lock:true
鎖定內(nèi)存需要系統(tǒng)配置:
- 修改/etc/security/limits.conf
- ulimit -l unlimited
7. filesystem cache相關(guān)
filesystem cache被用來執(zhí)行更多的IO操作仆救,如果我們能給filesystemcache更多的內(nèi)存資源抒和,那么es的寫入性能會好很多。即保證運行es實例的服務(wù)器有多余閑置內(nèi)存供給(除去配置的堆內(nèi)存)
8. 使用自動生成的id
如果我們要手動給es document設(shè)置一個id彤蔽,那么es需要每次都去確認(rèn)一下那個id是否存在摧莽,這個過程是比較耗費時間的。如果我們使用自動生成的id顿痪,那么es就可以跳過這個步驟镊辕,寫入性能會更好蚁袭。對于你的業(yè)務(wù)中的表id征懈,可以作為es document的一個field。
9. buffer相關(guān)
如果我們要進(jìn)行非常重的高并發(fā)寫入操作揩悄,那么最好將index buffer調(diào)大一些卖哎,indices.memory.index_buffer_size,這個可以調(diào)節(jié)大一些删性,設(shè)置的這個index buffer大小亏娜,是所有的shard公用的,但是如果除以shard數(shù)量以后蹬挺,算出來平均每個shard可以使用的內(nèi)存大小维贺,一般建議,但是對于每個shard來說巴帮,最多給512mb幸缕,因為再大性能就沒什么提升了群发。es會將這個設(shè)置作為每個shard共享的index buffer,那些特別活躍的shard會更多的使用這個buffer发乔。默認(rèn)這個參數(shù)的值是10%熟妓,也就是jvm heap的10%,如果我們給jvmheap分配10gb內(nèi)存栏尚,那么這個index buffer就有1gb起愈,對于兩個shard共享來說,是足夠的了译仗。
索引緩沖區(qū)用于存儲新索引的文檔抬虽。當(dāng)它填滿時,緩沖區(qū)中的文檔將寫入磁盤上的段纵菌。它在節(jié)點上的所有分片之間劃分阐污。
必須在群集中的每個數(shù)據(jù)節(jié)點上進(jìn)行配置:
1. indices.memory.index_buffer_size:30%
設(shè)置百分比 or 字節(jié)大小值。默認(rèn)為10%咱圆,意味著10%分配給節(jié)點的總堆將用作所有分片共享的索引緩沖區(qū)大小笛辟。
2. indices.memory.min_index_buffer_size
如果index_buffer_size設(shè)置為百分比,則可以使用此設(shè)置指定最小值序苏。默認(rèn)為48mb手幢。
3. indices.memory.max_index_buffer_size
如果index_buffer_size設(shè)置為百分比,則可以使用此設(shè)置指定最大值忱详。默認(rèn)為無限制围来。
10. translog相關(guān)
1. index.translog.sync_interval
translog寫入磁盤并提交頻率。默認(rèn)為5s匈睁。小于的值100ms是不允許的监透。
2. index.translog.durability
是否在每個索引,刪除航唆,更新或批量請求之后提交translog胀蛮。此設(shè)置接受以下參數(shù):
request(默認(rèn)):每個請求后提交。如果發(fā)生硬件故障佛点,所有已確認(rèn)的寫入都已提交到磁盤。
Async:每隔sync_interval時間提交黎比。如果發(fā)生故障超营,將丟棄自上次自動提交以來的所有已確認(rèn)寫入。
3. index.translog.flush_threshold_size
一旦事務(wù)日志達(dá)到這個值阅虫,就會發(fā)生一次flush演闭;默認(rèn)值為512mb。調(diào)大就可以減少flush的次數(shù)以及大段的合并次數(shù)颓帝∶着觯可以適當(dāng)調(diào)大窝革,但不能超過indexBufferSize*1.5倍/(可能并發(fā)寫的大索引數(shù)量),否則會觸發(fā)限流吕座,并導(dǎo)致JVM內(nèi)存不釋放虐译。
4. generation_threshold_size
默認(rèn)64M,系統(tǒng)支持吴趴,但官方文檔沒有的參數(shù)漆诽,超過該閾值會產(chǎn)生新的translog文件,要小于index.translog.flush_threshold_size锣枝,否則會影響flush,進(jìn)而觸發(fā)限流機(jī)制厢拭。
示例:
"translog.durability": "async",
"translog.flush_threshold_size": "2gb",
"translog.sync_interval": "100s",
"translog.generation_threshold_size":"64mb"
11. 段合并策略
老版本策略:
PUT /_cluster/settings
{
"persistent" : {
"indices.store.throttle.max_bytes_per_sec" : "100mb"
}
}
設(shè)置限流類型為 none 徹底關(guān)閉合并限流。等你完成了導(dǎo)入撇叁,記得改回 merge 重新打開限流
PUT /_cluster/settings
{
"transient" : {
"indices.store.throttle.type" : "none"
}
}
"merge.policy.max_merged_segment": "1000mb",
當(dāng)前策略:
"merge" : {
"scheduler" : {
"max_thread_count" : "1" //merge時最大的線程數(shù)
},
"policy" : {
"max_merged_segment":"5gb"供鸠,//超過此大小的segment不再參與合并
"floor_segment" : "2g", //默認(rèn) 2MB陨闹,小于這個大小的 segment楞捂,優(yōu)先被歸并
"segments_per_tier" : "24", //每個tier允許的segement 數(shù)正林,越小需要合并的操作越多泡一,要大于at_once
"max_merge_at_once" : "5" //默認(rèn)一次最多歸并 10 個 segment
}
}
merge 策略有三種:
tiered
log_byete_size
log_doc
默認(rèn)情況下:
1. index.merge.polcy.type: tiered
索引創(chuàng)建時合并策略就已確定,不能更改,但是可以動態(tài)更新策略參數(shù),一般情況下,不需要調(diào)整.如果堆棧經(jīng)常有很多 merge, 可以嘗試調(diào)整以下配置:
2. index.merge.policy.floor_segment
該屬性用于阻止segment 的頻繁flush, 小于此值將考慮優(yōu)先合并,默認(rèn)為2M,可考慮適當(dāng)降低此值
3. index.merge.policy.segments_per_tier
該屬性指定了每層分段的數(shù)量,取值約小最終segment 越少,因此需要 merge 的操作更多,可以考慮適當(dāng)增加此值.默認(rèn)為10,他應(yīng)該大于等于 index.merge.policy.max_merge_at_once
4. index.merge.policy.max_merged_segment
指定了單個 segment 的最大容量,默認(rèn)為5GB,可以考慮適當(dāng)降低此值
12. spark的使用
使用spark寫es,利用分布式的資源
13. didi開源的fastindex分析
核心思想:啟動多個java進(jìn)程(可以利用mr/spark)構(gòu)造多個es實例寫數(shù)據(jù)觅廓,然后將多個es實例的data目錄下的索引文件(lucene索引)合并到線上集群的真實索引中(使用lucene自帶的indexWriter.addIndexes(*) api)