自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

幾十億數(shù)據(jù)查詢3秒返回,ES性能優(yōu)化實(shí)戰(zhàn)!

大數(shù)據(jù) 數(shù)據(jù)分析
公司的數(shù)據(jù)平臺(tái)已迭代三個(gè)版本,從頭開始遇到很多常見的難題,終于有時(shí)間整理一些完善的文檔,在此分享以供所需的朋友。

公司的數(shù)據(jù)平臺(tái)已迭代三個(gè)版本,從頭開始遇到很多常見的難題,終于有時(shí)間整理一些完善的文檔,在此分享以供所需的朋友。

[[283800]] 

圖片來自 Pexels

在此篇幅中偏重于 ES 的優(yōu)化,關(guān)于 HBase,Hadoop 的設(shè)計(jì)優(yōu)化有很多文章可以參考,不再贅述。

需求說明

項(xiàng)目背景:在一業(yè)務(wù)系統(tǒng)中,部分表每天的數(shù)據(jù)量過億,已按天分表,但業(yè)務(wù)上受限于按天查詢,并且 DB 中只能保留 3 個(gè)月的數(shù)據(jù)(硬件高配),分庫代價(jià)較高。

改進(jìn)版本目標(biāo):

  1. 數(shù)據(jù)能跨月查詢,并且支持 1 年以上的歷史數(shù)據(jù)查詢與導(dǎo)出。
  2. 按條件的數(shù)據(jù)查詢秒級(jí)返回。

Elasticsearch 檢索原理

①關(guān)于 ES 和 Lucene 基礎(chǔ)結(jié)構(gòu)

談到優(yōu)化必須能了解組件的基本原理,才容易找到瓶頸所在,以免走多種彎路。

先從 ES 的基礎(chǔ)結(jié)構(gòu)說起(如下圖):

 

一些基本概念:

  • Cluster 包含多個(gè) Node 的集群。
  • Node 集群服務(wù)單元。
  • Index 一個(gè) ES 索引包含一個(gè)或多個(gè)物理分片,它只是這些分片的邏輯命名空間。
  • Type 一個(gè) index 的不同分類,6.x 后只能配置一個(gè) Type,以后將移除。
  • Document 最基礎(chǔ)的可被索引的數(shù)據(jù)單元,如一個(gè) JSON 串。
  • Shards 一個(gè)分片是一個(gè)底層的工作單元,它僅保存全部數(shù)據(jù)中的一部分,它是一個(gè) Lucence 實(shí)例。

一個(gè) Lucene 索引最大包含 2,147,483,519 (= Integer.MAX_VALUE - 128)個(gè)文檔數(shù)量。

  • Replicas 分片備份,用于保障數(shù)據(jù)安全與分擔(dān)檢索壓力。

ES 依賴一個(gè)重要的組件 Lucene,關(guān)于數(shù)據(jù)結(jié)構(gòu)的優(yōu)化通常來說是對(duì) Lucene 的優(yōu)化,它是集群的一個(gè)存儲(chǔ)與檢索工作單元,結(jié)構(gòu)如下圖: 


在 Lucene 中,分為索引(錄入)與檢索(查詢)兩部分,索引部分包含分詞器、過濾器、字符映射器等,檢索部分包含查詢解析器等。

一個(gè) Lucene 索引包含多個(gè) Segments,一個(gè) Segment 包含多個(gè)文檔,每個(gè)文檔包含多個(gè)字段,每個(gè)字段經(jīng)過分詞后形成一個(gè)或多個(gè) Term。

通過 Luke 工具查看 ES 的 Lucene 文件如下,主要增加了 _id 和 _source 字段:

 

②Lucene 索引實(shí)現(xiàn)

Lucene 索引文件結(jié)構(gòu)主要的分為:詞典、倒排表、正向文件、DocValues 等。

如下圖:

 

整理來源于 Lucene 官方:

  1. http://lucene.apache.org/core/7_2_1/core/org/apache/lucene/codecs/lucene70/package-summary.html#package.description 

Lucene 隨機(jī)三次磁盤讀取比較耗時(shí)。其中 .fdt 文件保存數(shù)據(jù)值損耗空間大,.tim 和 .doc 則需要 SSD 存儲(chǔ)提高隨機(jī)讀寫性能。另外一個(gè)比較消耗性能的是打分流程,不需要?jiǎng)t可屏蔽。

關(guān)于 DocValues:倒排索引解決從詞快速檢索到相應(yīng)文檔 ID, 但如果需要對(duì)結(jié)果進(jìn)行排序、分組、聚合等操作的時(shí)候則需要根據(jù)文檔 ID 快速找到對(duì)應(yīng)的值。

通過倒排索引代價(jià)卻很高:需迭代索引里的每個(gè)詞項(xiàng)并收集文檔的列里面 Token。

這很慢而且難以擴(kuò)展:隨著詞項(xiàng)和文檔的數(shù)量增加,執(zhí)行時(shí)間也會(huì)增加。

Solr docs 對(duì)此的解釋如下:

  • For other features that we now commonly associate with search, such as sorting, faceting, and highlighting, this approach is not very efficient. The faceting engine,
  • for example, must look up each term that appears in each document that will make up the result set and pull the document IDs in order to build the facet list. In Solr, this is maintained in memory, and can be slow to load (depending on the number of documents, terms, etc.)

在 Lucene 4.0 版本前通過 FieldCache,原理是通過按列逆轉(zhuǎn)倒排表將(field value->doc)映射變成(doc->field value)映射,問題為逐步構(gòu)建時(shí)間長并且消耗大量內(nèi)存,容易造成 OOM。

DocValues 是一種列存儲(chǔ)結(jié)構(gòu),能快速通過文檔 ID 找到相關(guān)需要排序的字段。

在 ES 中,默認(rèn)開啟所有(除了標(biāo)記需 analyzed 的字符串字段)字段的 doc values,如果不需要對(duì)此字段做任何排序等工作,則可關(guān)閉以減少資源消耗。

③關(guān)于 ES 索引與檢索分片

ES 中一個(gè)索引由一個(gè)或多個(gè) Lucene 索引構(gòu)成,一個(gè) Lucene 索引由一個(gè)或多個(gè) Segment 構(gòu)成,其中 Segment 是最小的檢索域。

數(shù)據(jù)具體被存儲(chǔ)到哪個(gè)分片上:

  1. shard = hash(routing) % number_of_primary_shards 

默認(rèn)情況下 routing 參數(shù)是文檔 ID (murmurhash3),可通過 URL 中的 _routing 參數(shù)指定數(shù)據(jù)分布在同一個(gè)分片中,index 和 search 的時(shí)候都需要一致才能找到數(shù)據(jù)。

如果能明確根據(jù) _routing 進(jìn)行數(shù)據(jù)分區(qū),則可減少分片的檢索工作,以提高性能。

優(yōu)化案例

在我們的案例中,查詢字段都是固定的,不提供全文檢索功能,這也是幾十億數(shù)據(jù)能秒級(jí)返回的一個(gè)大前提:

  • ES 僅提供字段的檢索,僅存儲(chǔ) HBase 的 Rowkey 不存儲(chǔ)實(shí)際數(shù)據(jù)。
  • 實(shí)際數(shù)據(jù)存儲(chǔ)在 HBase 中,通過 Rowkey 查詢,如下圖。
  • 提高索引與檢索的性能建議,可參考官方文檔:
  1. https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html 

一些細(xì)節(jié)優(yōu)化項(xiàng)官方與其他的一些文章都有描述,在此文章中僅提出一些本案例的重點(diǎn)優(yōu)化項(xiàng)。

 

優(yōu)化索引性能

①批量寫入,看每條數(shù)據(jù)量的大小,一般都是幾百到幾千。

②多線程寫入,寫入線程數(shù)一般和機(jī)器數(shù)相當(dāng),可以配多種情況,在測試環(huán)境通過 Kibana 觀察性能曲線。

③增加 Segments 的刷新時(shí)間,通過上面的原理知道,Segment 作為一個(gè)最小的檢索單元。

比如 Segment 有 50 個(gè),目的需要查 10 條數(shù)據(jù),但需要從 50 個(gè) Segment 分別查詢 10 條,共 500 條記錄,再進(jìn)行排序或者分?jǐn)?shù)比較后,截取最前面的 10 條,丟棄 490 條。

在我們的案例中將此 "refresh_interval": "-1" ,程序批量寫入完成后進(jìn)行手工刷新(調(diào)用相應(yīng)的 API 即可)。

④內(nèi)存分配方面,很多文章已經(jīng)提到,給系統(tǒng) 50% 的內(nèi)存給 Lucene 做文件緩存,它任務(wù)很繁重,所以 ES 節(jié)點(diǎn)的內(nèi)存需要比較多(比如每個(gè)節(jié)點(diǎn)能配置 64G 以上最好)。

⑤磁盤方面配置 SSD,機(jī)械盤做陣列 RAID5 RAID10 雖然看上去很快,但是隨機(jī) IO 還是 SSD 好。

⑥使用自動(dòng)生成的 ID,在我們的案例中使用自定義的 KEY,也就是與 HBase 的 ROW KEY,是為了能根據(jù) Rowkey 刪除和更新數(shù)據(jù),性能下降不是很明顯。

⑦關(guān)于段合并,合并在后臺(tái)定期執(zhí)行,比較大的 Segment 需要很長時(shí)間才能完成。

為了減少對(duì)其他操作的影響(如檢索),Elasticsearch 進(jìn)行閾值限制,默認(rèn)是 20MB/s,可配置的參數(shù)(根據(jù)磁盤性能調(diào)整):

  1. "indices.store.throttle.max_bytes_per_sec" : "200mb" 

合并線程數(shù)默認(rèn)是:

  1. Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)) 

如果是機(jī)械磁盤,可以考慮設(shè)置為 1:

  1. index.merge.scheduler.max_thread_count: 1 

在我們的案例中使用 SSD,配置了 6 個(gè)合并線程。

優(yōu)化檢索性能

①關(guān)閉不需要字段的 doc values。

②盡量使用 keyword 替代一些 long 或者 int 之類,term 查詢總比 range 查詢好 (參考 Lucene 說明 )。

  1. http://lucene.apache.org/core/7_4_0/core/org/apache/lucene/index/PointValues.html 

③關(guān)閉不需要查詢字段的 _source 功能,不將此存儲(chǔ)僅 ES 中,以節(jié)省磁盤空間。

④評(píng)分消耗資源,如果不需要可使用 filter 過濾來達(dá)到關(guān)閉評(píng)分功能,score 則為 0,如果使用 constantScoreQuery 則 score 為 1。

⑤關(guān)于分頁

from+size:每分片檢索結(jié)果數(shù)最大為 from+size,假設(shè) from=20,size=20,則每個(gè)分片需要獲取 20*20=400 條數(shù)據(jù)。

多個(gè)分片的結(jié)果在協(xié)調(diào)節(jié)點(diǎn)合并(假設(shè)請(qǐng)求的分配數(shù)為 5,則結(jié)果數(shù)最大為 400*5=2000 條)再在內(nèi)存中排序后,然后 20 條給用戶。

這種機(jī)制導(dǎo)致越往后分頁獲取的代價(jià)越高,達(dá)到 50000 條將面臨沉重的代價(jià),默認(rèn) from+size 默認(rèn)如下:

  1. index.max_result_window :10000 

search_after:使用前一個(gè)分頁記錄的最后一條來檢索下一個(gè)分頁記錄。

在我們的案例中,首先使用 from+size,檢索出結(jié)果后再使用 search_after,在頁面上我們限制了用戶只能跳 5 頁,不能跳到最后一頁。

scroll:用于大結(jié)果集查詢,缺陷是需要維護(hù) scroll_id。

⑥關(guān)于排序:我們?cè)黾右粋€(gè) long 字段,它用于存儲(chǔ)時(shí)間和 ID 的組合(通過移位即可),正排與倒排性能相差不明顯。

⑦關(guān)于 CPU 消耗,檢索時(shí)如果需要做排序則需要字段對(duì)比,消耗 CPU 比較大,如果有可能盡量分配 16cores 以上的 CPU,具體看業(yè)務(wù)壓力。

⑧關(guān)于合并被標(biāo)記刪除的記錄,我們?cè)O(shè)置為 0 表示在合并的時(shí)候一定刪除被標(biāo)記的記錄,默認(rèn)應(yīng)該是大于 10% 才刪除:

  1. "merge.policy.expunge_deletes_allowed""0" 
  1.     "mappings": { 
  2.         "data": { 
  3.             "dynamic""false"
  4.             "_source": { 
  5.                 "includes": ["XXX"]  -- 僅將查詢結(jié)果所需的數(shù)據(jù)存儲(chǔ)僅_source中 
  6.             }, 
  7.             "properties": { 
  8.                 "state": { 
  9.                     "type""keyword",   -- 雖然state為int值,但如果不需要做范圍查詢,盡量使用keyword,因?yàn)閕nt需要比keyword增加額外的消耗。 
  10.                     "doc_values"false  -- 關(guān)閉不需要字段的doc values功能,僅對(duì)需要排序,匯聚功能的字段開啟。 
  11.                 }, 
  12.                 "b": { 
  13.                     "type""long"    -- 使用了范圍查詢字段,則需要用long或者int之類 (構(gòu)建類似KD-trees結(jié)構(gòu)) 
  14.                 } 
  15.             } 
  16.         } 
  17.     }, 
  18.    "settings": {......} 

性能測試

優(yōu)化效果評(píng)估基于基準(zhǔn)測試,如果沒有基準(zhǔn)測試無法了解是否有性能提升,在這所有的變動(dòng)前做一次測試會(huì)比較好。

在我們的案例中:

  • 單節(jié)點(diǎn) 5000 萬到 1 億的數(shù)據(jù)量測試,檢查單點(diǎn)承受能力。
  • 集群測試 1 億-30 億的數(shù)量,磁盤 IO/內(nèi)存/CPU/網(wǎng)絡(luò) IO 消耗如何。
  • 隨機(jī)不同組合條件的檢索,在各個(gè)數(shù)據(jù)量情況下表現(xiàn)如何。
  • 另外 SSD 與機(jī)械盤在測試中性能差距如何。

性能的測試組合有很多,通常也很花時(shí)間,不過作為評(píng)測標(biāo)準(zhǔn)時(shí)間上的投入有必要,否則生產(chǎn)出現(xiàn)性能問題很難定位或不好改善。

對(duì)于 ES 的性能研究花了不少時(shí)間,最多的關(guān)注點(diǎn)就是 Lucene 的優(yōu)化,能深入了解 Lucene 原理對(duì)優(yōu)化有很大的幫助。

生產(chǎn)效果

目前平臺(tái)穩(wěn)定運(yùn)行,幾十億的數(shù)據(jù)查詢 100 條都在 3 秒內(nèi)返回,前后翻頁很快,如果后續(xù)有性能瓶頸,可通過擴(kuò)展節(jié)點(diǎn)分擔(dān)數(shù)據(jù)壓力。

 

責(zé)任編輯:武曉燕 來源: 博客園
相關(guān)推薦

2020-08-19 12:29:35

留存分析數(shù)據(jù)工具

2020-09-29 09:09:03

數(shù)據(jù)庫程序運(yùn)行

2009-04-20 08:51:50

MySQL查詢優(yōu)化數(shù)據(jù)庫

2017-03-29 14:44:20

網(wǎng)絡(luò)性能優(yōu)化

2022-05-17 09:02:30

前端性能優(yōu)化

2022-09-26 09:41:25

MySQL數(shù)據(jù)庫

2023-11-28 07:48:23

SQL Server數(shù)據(jù)庫

2019-05-22 15:57:11

面試ES性能數(shù)據(jù)

2021-11-24 15:16:02

Quick阿里云操作系統(tǒng)

2023-02-24 16:37:04

MySQL數(shù)據(jù)查詢數(shù)據(jù)庫

2023-07-12 08:55:16

PawSQL數(shù)據(jù)庫

2022-12-28 08:29:12

CKESRediSearch

2011-04-06 14:50:05

SQL查詢效率

2021-01-31 17:50:41

數(shù)據(jù)庫查詢程序員

2023-09-07 07:30:26

Oracle數(shù)據(jù)庫

2015-06-23 10:53:02

TeradataJSON

2019-12-13 10:25:08

Android性能優(yōu)化啟動(dòng)優(yōu)化

2013-09-08 22:40:38

EF Code Fir數(shù)據(jù)查詢架構(gòu)設(shè)計(jì)

2022-09-08 09:35:22

數(shù)據(jù)查詢

2019-05-28 09:31:05

Elasticsear億級(jí)數(shù)據(jù)ES
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)