<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Elasticsearch:從寫入原理談寫入優(yōu)化

          共 6052字,需瀏覽 13分鐘

           ·

          2021-04-06 13:56

          1、線上實(shí)戰(zhàn)問(wèn)題

          問(wèn)題 1:想要請(qǐng)問(wèn)一下,我這邊需求是每分鐘利用 sparksteaming 插入按天的索引150萬(wàn)條數(shù)據(jù)。一般情況下還好,索引7個(gè)分片,1副本,但是偶爾會(huì)出現(xiàn)延遲很高的情況。比如:一般情況下1分鐘插入150萬(wàn)能正常插入,可能突然就出現(xiàn)了需要5分鐘才能插入成功,然后又正常了。很頭疼。

          請(qǐng)問(wèn)這種情況我需要怎么去查看一下是否正常。我已經(jīng)把副本設(shè)置成了0,還把批量插入的參數(shù)從 5000 設(shè)置成 2 萬(wàn)。我節(jié)點(diǎn)是 12 個(gè) 16g 的,但是好像還是沒(méi)有改觀。

          問(wèn)題 2:由于使用了多個(gè)分詞器的原因造成數(shù)據(jù)寫入慢,請(qǐng)問(wèn)有什么優(yōu)化的方法嗎?

          問(wèn)題 3:求問(wèn):現(xiàn)在日志 收集鏈路 kafka-logstash-es,壓力測(cè)試 logstash輸出70M/s,而 Elasticsearch 索引寫入一半不到。這邊的性能損失可能是什么原因呢?需要怎么調(diào)優(yōu)呢?

          類似問(wèn)題還有很多、很多......

          2、問(wèn)題分析

          以上三個(gè)問(wèn)題各有各自特點(diǎn),但基本都是基于不同的數(shù)據(jù)源向 Elasticsearch 寫入過(guò)程中遇到的問(wèn)題。

          可以簡(jiǎn)單歸結(jié)為:Elasticsearch 寫入問(wèn)題或者寫入優(yōu)化問(wèn)題。Elasticsearch 寫入問(wèn)題涉及寫入流程、寫入原理及優(yōu)化策略。

          本文針對(duì)如上幾點(diǎn)展開討論。

          3、基于單文檔/批量文檔寫入流程談寫入優(yōu)化

          單個(gè)文檔寫入對(duì)應(yīng) Index 請(qǐng)求,批量寫入對(duì)應(yīng) Bulk 請(qǐng)求,Index 和 Bulk 是相同的處理邏輯,請(qǐng)求統(tǒng)一封裝到 BulkRequest中。

          流程拆解如下:

          第一:客戶端向 Node 1 發(fā)送寫數(shù)據(jù)請(qǐng)求。

          注意,此時(shí)Node1 便充當(dāng)協(xié)調(diào)節(jié)點(diǎn)(cooridiniate)的角色。

          第二:節(jié)點(diǎn)Node1 使用文檔的 _id 確定文檔屬于分片 0 。請(qǐng)求會(huì)被轉(zhuǎn)發(fā)到 Node 3,因?yàn)榉制?0 的主分片目前被分配在 Node 3 上。

          使用文檔的 _id 確定文檔所屬分片的方法是:路由算法。

          路由算法計(jì)算公式:

          shard = hash(routing) % number_of_primary_shards
          • routing:文檔 _id。
          • number_of_primary_shards: 主分片個(gè)數(shù)。
          • shard: 文檔 _id 所屬分片號(hào)。

          第三:Node 3 在主分片上面執(zhí)行寫入操作。如果寫入成功了,它將請(qǐng)求并行轉(zhuǎn)發(fā)到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都報(bào)告成功, Node 3 將向協(xié)調(diào)節(jié)點(diǎn)報(bào)告寫入成功,協(xié)調(diào)節(jié)點(diǎn)向客戶端報(bào)告寫入成功。

          如上流程拆解后的注意點(diǎn):

          • 寫操作必須在主分片執(zhí)行成功后,才能復(fù)制到相關(guān)的副本分片。
          • 主分片寫入失敗,則整個(gè)請(qǐng)求被認(rèn)為是寫失敗。
          • 如果有部分副本寫失?。ㄇ疤幔褐鞣制瑢懭氤晒Γ瑒t整個(gè)請(qǐng)求被認(rèn)為是寫成功。

          如果設(shè)置了副本,數(shù)據(jù)會(huì)先寫入主分片,主分片再同步到副本分片,同步操作會(huì)加重磁盤 IO,間接影響寫入性能。

          基于以上分析,既然主分片的寫入起到寫入成敗的決定性作用。那么寫入前將:副本分片寫入前置為0,待寫入完成后復(fù)原副本,是不是就能提升寫入性能了呢?

          是的!

          寫入優(yōu)化一:副本分片寫入前置為0,等完成寫入后復(fù)原副本

          PUT test-0001
          {
            "settings": {
              "number_of_replicas": 0
            }
          }

          寫入優(yōu)化二:優(yōu)先使用系統(tǒng)自動(dòng)生成 id

          文檔的_id 的生成有兩種方式,

          • 第一:系統(tǒng)自動(dòng)生成id。

          • 第二:外部控制自增id。

          但,如果使用外部 id,Elasticsearch 會(huì)先嘗試讀取原來(lái)文檔的版本號(hào),以判斷是否需要更新。

          也就是說(shuō),使用外部控制 id 比系統(tǒng)自動(dòng)生成id要多一次讀取磁盤操作。

          所以,非特殊場(chǎng)景推薦使用系統(tǒng)自動(dòng)生成的 id。

          4、基于 Elasticsearch 寫入原理談寫入優(yōu)化

          Elasticsearch 中的 1 個(gè)索引由一個(gè)或多個(gè)分片組成,每個(gè)分片包含多個(gè)segment(段),每一個(gè)段都是一個(gè)倒排索引。如下圖所示:

          在 lucene 中,為了實(shí)現(xiàn)高索引速度,使用了segment 分段架構(gòu)存儲(chǔ)。一批寫入數(shù)據(jù)保存在一個(gè)段中,其中每個(gè)段最終落地為磁盤中的單個(gè)文件。

          將文檔插入 Elasticsearch 時(shí),它們會(huì)被寫入緩沖區(qū)中,然后在刷新時(shí)定期從該緩沖區(qū)刷新到段中。刷新頻率由 refresh_interval 參數(shù)控制,默認(rèn)每1秒刷新一次。

          也就是說(shuō),新插入的文檔在刷新到段(內(nèi)存中)之前,是不能被搜索到的。如下圖所示:

          刷新的本質(zhì)是:寫入數(shù)據(jù)由內(nèi)存 buffer 寫入到內(nèi)存段中,以保證搜索可見。

          來(lái)看個(gè)例子,加深對(duì) refresh_inteval 的理解,注釋部分就是解讀。

          PUT test_0001/_doc/1
          {
            "title":"just testing"
          }

          # 默認(rèn)一秒的刷新頻率,秒級(jí)可見(用戶無(wú)感知)

          GET test_0001/_search

          如下設(shè)置后,寫入后 60s 后才可見。

          DELETE test_0001
          # 設(shè)置了60s的刷新頻率
          PUT test_0001
          {
            "settings": {
              "index":{
                "refresh_interval":"60s"
              }
            }
          }
           
          PUT test_0001/_doc/1
          {
            "title":"just testing"
          }
          # 60s后才可以被搜索到
          GET test_0001/_search

          關(guān)于是否需要實(shí)時(shí)刷新:

          • 如果新插入的數(shù)據(jù)需要近乎實(shí)時(shí)的搜索功能,則需要頻繁刷新。

          • 如果對(duì)最新數(shù)據(jù)的檢索響應(yīng)沒(méi)有實(shí)時(shí)性要求,則應(yīng)增加刷新間隔,以提高數(shù)據(jù)寫入的效率。

          所以,自然我們想到的優(yōu)化是:調(diào)整刷新頻率。

          寫入優(yōu)化三:合理調(diào)整刷新頻率

          調(diào)整方法如下:

          方法1:寫入前刷新頻率設(shè)置為 -1,寫入后設(shè)置為業(yè)務(wù)實(shí)際需要值(比如:30s)。

          PUT test-008
          {
            "settings": {
              "refresh_interval": -1
            }
          }

          方法2:直接設(shè)置為業(yè)務(wù)實(shí)際需要值(比如:30s)

          PUT test-008
          {
            "settings": {
              "refresh_interval": "30s"
            }
          }

          寫入優(yōu)化四:合理調(diào)整堆內(nèi)存中索引緩沖區(qū)(index_buffer)大小

          堆內(nèi)存中 index_buffer 用于存儲(chǔ)新索引的文檔。

          填滿后,緩沖區(qū)中的文檔將最終寫入磁盤上的某個(gè)段。

          index_buffer_size 默認(rèn)值如下所示,為堆內(nèi)存的 10%。

          indices.memory.index_buffer_size: 10%

          例如,如果給 JVM 31GB的內(nèi)存,它將為索引緩沖區(qū)提供 3.1 GB的內(nèi)存,一般情況下足以容納大量數(shù)據(jù)的寫入操作。

          但,如果著實(shí)數(shù)據(jù)量非常大,建議調(diào)大該默認(rèn)值。比如:調(diào)整為堆內(nèi)存的 20%。

          調(diào)整建議:必須在集群中的每個(gè)數(shù)據(jù)節(jié)點(diǎn)上進(jìn)行配置。

          緩存區(qū)越大,意味著能緩存數(shù)據(jù)量越大,相同時(shí)間段內(nèi),寫盤頻次低、磁盤 IO 小,間接提升寫入性能。

          寫入優(yōu)化五:給堆外內(nèi)存也留夠空間(常規(guī)要求)

          這其實(shí)算不上寫入優(yōu)化建議,而是通用集群配置的常規(guī)配置。

          內(nèi)存分配設(shè)置堆內(nèi)存比例官方建議:機(jī)器內(nèi)存大小一半,但不超過(guò) 32 GB。

          一般設(shè)置建議:

          • 如果內(nèi)存大小 >= 64 GB,堆內(nèi)存設(shè)置:31 GB。
          • 如果內(nèi)存大小 < 64 GB,堆內(nèi)存設(shè)置:內(nèi)存大小一半。

          堆內(nèi)存之外的內(nèi)存留給:Lucene 使用。

          推薦閱讀:干貨 | 吃透Elasticsearch 堆內(nèi)存

          寫入優(yōu)化六:bulk 批量寫入而非單個(gè)文檔寫入

          批量寫入自然會(huì)比單個(gè)寫入性能要好(批量寫入意味著相同時(shí)間產(chǎn)生的段會(huì)大,段的總個(gè)數(shù)自然會(huì)少),但批量值的設(shè)置一般需要慎重,不要盲目一下搞的很大。

          一般建議:遞增步長(zhǎng)測(cè)試,直到達(dá)到資源使用上限。

          比如:第一次批量值設(shè)置:100,第二次:200,第三次:400,以此類推......

          批量值 bulk 已經(jīng) ok 了,但集群尚有富余資源,資源利用并沒(méi)有飽和怎么辦?

          上多線程,通過(guò)并發(fā)提升寫入性能。

          寫入優(yōu)化七:多線程并發(fā)寫入

          這點(diǎn),在 logstash 同步數(shù)據(jù)到 Elasticsearch,基于spark、kafka、Flink 批量寫入 Elasticsearch時(shí),經(jīng)常會(huì)出現(xiàn):Bulk Rejections 的報(bào)錯(cuò)。

          當(dāng)批量請(qǐng)求到達(dá)集群中的某個(gè)節(jié)點(diǎn)時(shí),整個(gè)請(qǐng)求將被放入批量隊(duì)列中,并由批量線程池中的線程進(jìn)行處理。批量線程池處理來(lái)自隊(duì)列的請(qǐng)求,并將文檔轉(zhuǎn)發(fā)到副本分片,作為此處理的一部分。子請(qǐng)求完成后,將響應(yīng)發(fā)送到協(xié)調(diào)節(jié)點(diǎn)。

          Elasticsearch 具有有限大小的請(qǐng)求隊(duì)列的原因是:為了防止集群過(guò)載,從而增加了穩(wěn)定性和可靠性。

          如果沒(méi)有任何限制,客戶端可以很容易地通過(guò)惡意攻擊行為將整個(gè)集群搞宕機(jī)。

          這里就引申出下面的優(yōu)化點(diǎn)。

          寫入優(yōu)化八:合理設(shè)置線程池和隊(duì)列大小

          關(guān)于線程池和隊(duì)列,參考:Elasticsearch 線程池和隊(duì)列問(wèn)題,請(qǐng)先看這一篇。

          核心建議就是:結(jié)合 CPU 核數(shù)和 esrally 的測(cè)試結(jié)果謹(jǐn)慎的調(diào)整 write 線程池和隊(duì)列大小。

          為什么要謹(jǐn)慎設(shè)置?

          針對(duì)批量寫入拒絕(reject)的場(chǎng)景,官方建議:

          增加隊(duì)列的大小不太可能改善集群的索引性能或吞吐量。相反,這只會(huì)使集群在內(nèi)存中排隊(duì)更多數(shù)據(jù),這很可能導(dǎo)致批量請(qǐng)求需要更長(zhǎng)的時(shí)間才能完成。

          隊(duì)列中的批量請(qǐng)求越多,將消耗更多的寶貴堆空間。如果堆上的壓力太大,則可能導(dǎo)致許多其他性能問(wèn)題,甚至導(dǎo)致集群不穩(wěn)定。

          推薦閱讀:

          https://www.elastic.co/cn/blog/why-am-i-seeing-bulk-rejections-in-my-elasticsearch-cluster

          5、其他寫入優(yōu)化建議

          寫入優(yōu)化九:設(shè)置合理的Mapping

          實(shí)戰(zhàn)業(yè)務(wù)場(chǎng)景中不推薦使用默認(rèn) dynamic Mapping,一定要手動(dòng)設(shè)置 Mapping。

          • 舉例1:默認(rèn)字符串類型是:text 和 keyword 的組合類型,就不見得適用所有業(yè)務(wù)場(chǎng)景。要結(jié)合自己業(yè)務(wù)場(chǎng)景設(shè)置,正文 cont 文本內(nèi)容一般不需要設(shè)置 keyword 類型(因?yàn)椋翰恍枰判蚝途酆喜僮鳎?/span>

          • 舉例2:互聯(lián)網(wǎng)采集數(shù)據(jù)存儲(chǔ)場(chǎng)景,正文需要全文檢索,但包含 html 樣式的文本一般留給前端展示用,不需要索引。這時(shí)候Mapping 設(shè)置階段要果斷將 index 設(shè)置為 false。

          寫入優(yōu)化十:合理的使用分詞器

          分詞器決定分詞的粒度,常見的中文分詞 IK 可細(xì)分為:

          • 粗粒度分詞:ik_smart。
          • 細(xì)粒度分詞:ik_max_word。

          從存儲(chǔ)角度基于 ik_max_word 分詞的索引會(huì)比基于 ik_smart 分詞的索引占據(jù)空間大。

          而更細(xì)粒度自定義分詞 ngram 會(huì)占用大量資源,并且可能減慢索引速度并顯著增加索引大小。

          所以要結(jié)合檢索指標(biāo)(召回率和精準(zhǔn)率)、結(jié)合寫入場(chǎng)景斟酌選型。

          寫入優(yōu)化十一:必要時(shí),使用 SSD 磁盤

          SSD 很貴,但很香。

          尤其針對(duì)寫入密集型場(chǎng)景,如果其他優(yōu)化點(diǎn)都考慮了,這可能是你最后一根“救命稻草“。

          寫入優(yōu)化十二:合理設(shè)置集群節(jié)點(diǎn)角色

          這也是經(jīng)常被問(wèn)到的問(wèn)題,集群規(guī)模小的時(shí)候,一般節(jié)點(diǎn)會(huì)混合多種角色,如:主節(jié)點(diǎn) + 數(shù)據(jù)節(jié)點(diǎn)、數(shù)據(jù)節(jié)點(diǎn) + 協(xié)調(diào)節(jié)點(diǎn)混合部署。

          但,集群規(guī)模大了之后,硬件資源相對(duì)豐富后,強(qiáng)烈建立:獨(dú)立主節(jié)點(diǎn)、獨(dú)立協(xié)調(diào)節(jié)點(diǎn)。

          讓各個(gè)角色的節(jié)點(diǎn)各盡其責(zé),對(duì)寫入、檢索性能都會(huì)有幫助。

          寫入優(yōu)化十三:推薦使用官方客戶端

          推薦使用官方 Elasticsearch API,因?yàn)楣俜皆谶B接池和保持連接狀態(tài)方面有優(yōu)化。

          高版本 JAVA API 推薦:官方的High-level-Rest API。

          其他寫入優(yōu)化

          待補(bǔ)充......

          6、寫入過(guò)程中做好監(jiān)控

          如下是 kibana 監(jiān)控截圖,其中:index Rate 就是寫入速率。

          • index rate: 每秒寫入的文檔數(shù)。

          • search rate:每秒的查詢次數(shù)(分片級(jí)別,非請(qǐng)求級(jí)別),也就意味著一次查詢請(qǐng)求命中的分片數(shù)越多,值越大。

          7、小結(jié)

          Elasticsearch 寫入優(yōu)化沒(méi)有普適的最優(yōu)優(yōu)化建議,只有適合自己業(yè)務(wù)場(chǎng)景的反復(fù)試驗(yàn)、調(diào)優(yōu),形成屬于自己業(yè)務(wù)場(chǎng)景的最佳實(shí)踐。

          你的業(yè)務(wù)場(chǎng)景做過(guò)哪些寫入優(yōu)化?歡迎留言討論交流。


          參考:

          • https://www.elastic.co/guide/en/elasticsearch/reference/7.2/tune-for-indexing-speed.html
          • 《Elasticsearch源碼解析與優(yōu)化實(shí)戰(zhàn)》
          • https://wx.zsxq.com/dweb2/index/search/%E5%88%86%E7%89%87%E6%95%B0/alltopics
          • https://t.zsxq.com/v7qNNRz
          • https://opster.com/blogs/improve-elasticsearch-indexing-rate/
          • 國(guó)外博客

          推薦:

          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产在线一区二区三区 | 91无码内射 | 欧美五月婷婷 | 男人天堂v在线 | 人人做人人爱青青草视频 |