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

搜索引擎怎么選?攜程酒店訂單Elasticsearch實(shí)戰(zhàn)

開發(fā) 架構(gòu) 開發(fā)工具
隨著訂單量的日益增長(zhǎng),單個(gè)數(shù)據(jù)庫(kù)的讀寫能力開始捉襟見肘。這種情況下,對(duì)數(shù)據(jù)庫(kù)進(jìn)行分片變得順理成章。

 隨著訂單量的日益增長(zhǎng),單個(gè)數(shù)據(jù)庫(kù)的讀寫能力開始捉襟見肘。這種情況下,對(duì)數(shù)據(jù)庫(kù)進(jìn)行分片變得順理成章。

[[237273]]

分片之后的寫,只要根據(jù)分片的維度進(jìn)行取模即可??墒嵌嗑S度的查詢應(yīng)該如何處理呢?

一片一片的查詢,然后在內(nèi)存里面聚合是一種方式,可是缺點(diǎn)顯而易見。

對(duì)于那些無(wú)數(shù)據(jù)返回分片的查詢,不僅對(duì)應(yīng)用服務(wù)器是一種額外的性能消耗,對(duì)寶貴的數(shù)據(jù)庫(kù)資源也是一種不必要的負(fù)擔(dān)。

至于查詢性能,雖然可以通過(guò)開線程并發(fā)查詢進(jìn)行改善,但是多線程編程以及對(duì)數(shù)據(jù)庫(kù)返回結(jié)果的聚合,增加了編程的復(fù)雜性和易錯(cuò)性。可以試想一下分片后的分頁(yè)查詢?nèi)绾螌?shí)現(xiàn),便可有所體會(huì)。

所以我們選擇對(duì)分片后的數(shù)據(jù)庫(kù)建立實(shí)時(shí)索引,把查詢收口到一個(gè)獨(dú)立的 Web Service,在保證性能的前提下,提升業(yè)務(wù)應(yīng)用查詢時(shí)的便捷性。那問題就來(lái)了,如何建立高效的分片索引呢?

索引技術(shù)的選型

實(shí)時(shí)索引的數(shù)據(jù)會(huì)包含常見查詢中所用到的列,例如用戶 ID,用戶電話,用戶地址等,實(shí)時(shí)復(fù)制分發(fā)一份到一個(gè)獨(dú)立的存儲(chǔ)介質(zhì)上。

查詢時(shí),會(huì)先查索引,如果索引中已經(jīng)包含所需要的列,直接返回?cái)?shù)據(jù)即可。

如果需要額外的數(shù)據(jù),可以根據(jù)分片維度進(jìn)行二次查詢。因?yàn)橐呀?jīng)能確定具體的分片,所以查詢也會(huì)高效。

為什么沒有使用數(shù)據(jù)庫(kù)索引

數(shù)據(jù)庫(kù)索引是一張表的所選列的數(shù)據(jù)備份。

由于得益于包含了低級(jí)別的磁盤塊地址或者直接鏈接到原始數(shù)據(jù)的行,查詢效率非常高效。

優(yōu)點(diǎn)是數(shù)據(jù)庫(kù)自帶的索引機(jī)制是比較穩(wěn)定可靠且高效的;缺陷是隨著查詢場(chǎng)景的增多,索引的量會(huì)隨之上升。

訂單自身的屬性隨著業(yè)務(wù)的發(fā)展已經(jīng)達(dá)到上千,高頻率查詢的維度可多達(dá)幾十種,組合之后的變形形態(tài)可達(dá)上百種。

而索引本身并不是沒有代價(jià)的,每次增刪改都會(huì)有額外的寫操作,同時(shí)占用額外的物理存儲(chǔ)空間。

索引越多,數(shù)據(jù)庫(kù)索引維護(hù)的成本越大。所以還有其他選擇么?

開源搜索引擎的選擇

當(dāng)時(shí)閃現(xiàn)在我們腦中的是開源搜索引擎 Apache Solr 和 Elastic Search。

Solr 是一個(gè)建立在 Java 類庫(kù) Lucene 之上的開源搜索平臺(tái),以一種更友好的方式提供 Lucene 的搜索能力。

它已經(jīng)存在十年之久,是一款非常成熟的產(chǎn)品,提供分布式索引、復(fù)制分發(fā)、負(fù)載均衡查詢,自動(dòng)故障轉(zhuǎn)移和恢復(fù)功能。

Elastic Search 也是一個(gè)建立在 Lucene 之上的分布式 RESTful 搜索引擎。

通過(guò) RESTful 接口和 Schema Fee JSON 文檔,提供分布式全文搜索引擎。每個(gè)索引可以被分成多個(gè)分片,每個(gè)分片可以有多個(gè)備份。

兩者對(duì)比各有優(yōu)劣:

  • 在安裝和配置方面,得益于產(chǎn)品較新,Elastic Search 更輕量級(jí)以及易于安裝使用。
  • 在搜索方面,撇開大家都有的全文搜索功能,Elastic Search 在分析性查詢中有更好的性能。
  • 在分布式方面,Elastic Search 支持在一個(gè)服務(wù)器上存在多個(gè)分片,并且隨著服務(wù)器的增加,自動(dòng)平衡分片到所有的機(jī)器。
  • 社區(qū)與文檔方面,Solr 得益于其資歷,有更多的積累。

根據(jù) Google Trends 的統(tǒng)計(jì),Elastic Search 比 Solr 有更廣泛的關(guān)注度。

最終我們選擇了 Elastic Search,看中的是它的輕量級(jí)、易用和對(duì)分布式更好的支持,整個(gè)安裝包也只有幾十兆。

復(fù)制分發(fā)的實(shí)現(xiàn)

為了避免重復(fù)造輪子,我們嘗試尋找現(xiàn)存組件。由于數(shù)據(jù)庫(kù)是 SQL Server 的,所以沒有找到合適的開源組件。

SQL Server 本身有實(shí)時(shí)監(jiān)控增刪改的功能,把更新后的數(shù)據(jù)寫到單獨(dú)的一張表。

但是它并不能自動(dòng)把數(shù)據(jù)寫到 Elastic Search,也沒有提供相關(guān)的 API 與指定的應(yīng)用進(jìn)行通訊,所以我們開始嘗試從應(yīng)用層面去實(shí)現(xiàn)復(fù)制分發(fā)。

為什么沒有使用數(shù)據(jù)訪問層復(fù)制分發(fā)

首先進(jìn)入我們視線的是數(shù)據(jù)訪問層,它可能是一個(gè)突破口。每當(dāng)應(yīng)用對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改時(shí),實(shí)時(shí)寫一條數(shù)據(jù)到 Elastic Search。

但是考慮到以下情況后,我們決定另辟蹊徑:

有幾十個(gè)應(yīng)用在訪問數(shù)據(jù)庫(kù),有幾十個(gè)開發(fā)都在改動(dòng)數(shù)據(jù)訪問層的代碼。如果要實(shí)現(xiàn)數(shù)據(jù)層的復(fù)制分發(fā),必須對(duì)現(xiàn)有十幾年的代碼進(jìn)行肉眼掃描,然后進(jìn)行修改。開發(fā)的成本和易錯(cuò)性都很高。

每次增刪改時(shí)都寫 Elastic Search,意味著業(yè)務(wù)處理邏輯與復(fù)制分發(fā)強(qiáng)耦合。

Elastic Search 或相關(guān)其他因素的不穩(wěn)定,會(huì)直接導(dǎo)致業(yè)務(wù)處理的不穩(wěn)定。

異步開線程寫 Elastic Search?那如何處理應(yīng)用發(fā)布重啟的場(chǎng)景?加入大量異常處理和重試的邏輯?然后以 JAR 的形式引用到幾十個(gè)應(yīng)用?一個(gè)小  Bug 引起所有相關(guān)應(yīng)用的不穩(wěn)定?

實(shí)時(shí)掃描數(shù)據(jù)庫(kù)

初看這是一種很低效的方案,但是在結(jié)合以下實(shí)際場(chǎng)景后,它卻是一種簡(jiǎn)單、穩(wěn)定、高效的方案:

  • 零耦合。相關(guān)應(yīng)用無(wú)需做任何改動(dòng),不會(huì)影響業(yè)務(wù)處理效率和穩(wěn)定性。
  • 批量寫 Elastic Search。由于掃描出來(lái)的都是成批的數(shù)據(jù),可以批量寫入 Elastic Search,避免 Elastic Search 由于過(guò)多單個(gè)請(qǐng)求,頻繁刷新緩存。
  • 存在大量毫秒級(jí)并發(fā)的寫。掃描數(shù)據(jù)庫(kù)時(shí)無(wú)返回?cái)?shù)據(jù)意味著額外的數(shù)據(jù)庫(kù)性能消耗,我們的場(chǎng)景寫的并發(fā)和量都非常大,所以這種額外消耗可以接受。
  • 不刪除數(shù)據(jù)。掃描數(shù)據(jù)庫(kù)無(wú)法掃描出刪除的記錄,但是訂單相關(guān)的記錄都需要保留,所以不存在刪除數(shù)據(jù)的場(chǎng)景。

提高 Elastic Search 寫的吞吐量

由于是對(duì)數(shù)據(jù)庫(kù)的實(shí)時(shí)復(fù)制分發(fā),效率和并發(fā)量要求都會(huì)較高。以下是我們對(duì) Elastic Search 的寫所采用的一些優(yōu)化方案:

使用 upsert 替代 select + insert/update

類似于 MySQL 的 replace into,避免多次請(qǐng)求,成倍節(jié)省多次請(qǐng)求帶來(lái)的性能消耗。

使用 bulkrequest,把多個(gè)請(qǐng)求合并在一個(gè)請(qǐng)求里面

Elastic Search 的工作機(jī)制對(duì)批量請(qǐng)求有較好的性能,例如 translog 的持久化默認(rèn)是 request 級(jí)別的,這樣寫硬盤的次數(shù)就會(huì)大大降低,提高寫的性能。

至于具體一個(gè)批次多少個(gè)請(qǐng)求,這個(gè)與服務(wù)器配置、索引結(jié)構(gòu)、數(shù)據(jù)量都有關(guān)系??梢允褂脛?dòng)態(tài)配置的方式,在生產(chǎn)上面調(diào)試。

對(duì)于實(shí)時(shí)性要求不高的索引

把 index.refresh_interval 設(shè)置為 30 秒(默認(rèn)是 1 秒),這樣可以讓 Elastic Search 每 30 秒創(chuàng)建一個(gè)新的 segment,減輕后面的 flush 和 merge 壓力。

提前設(shè)置索引的 schema,去除不需要的功能

例如默認(rèn)對(duì) string 類型的映射會(huì)同時(shí)建立 keyword 和 text 索引,前者適合于完全匹配的短信息,例如郵寄地址、服務(wù)器名稱,標(biāo)簽等。

而后者適合于一片文章中的某個(gè)部分的查詢,例如郵件內(nèi)容、產(chǎn)品說(shuō)明等。

根據(jù)具體查詢的場(chǎng)景,選擇其中一個(gè)即可,如下圖:

對(duì)于不關(guān)心查詢結(jié)果評(píng)分的字段,可以設(shè)置為 norms:false。

對(duì)于不會(huì)使用 phrase query 的字段,設(shè)置 index_options:freqs。

對(duì)于能接受數(shù)據(jù)丟失的索引或者有災(zāi)備服務(wù)器的場(chǎng)景

把 index.translog.durability 設(shè)置成 async(默認(rèn)是 request)。把對(duì) lucene 的寫持久化到硬盤是一個(gè)相對(duì)昂貴的操作,所以會(huì)有 translog 先持久化到硬盤,然后批量寫入 lucene。

異步寫 translog 意味著無(wú)需每個(gè)請(qǐng)求都去寫硬盤,能提高寫的性能。在數(shù)據(jù)初始化的時(shí)候效果比較明顯,后期實(shí)時(shí)寫入使用 bulkrequest 能滿足大部分的場(chǎng)景。

提高 Elastic Search 讀的性能

為了提高查詢的性能,我們做了以下優(yōu)化:寫的時(shí)候指定查詢場(chǎng)景***的字段為 _routing 的值。

由于 Elastic Search 的分布式分區(qū)原則默認(rèn)是對(duì)文檔 id 進(jìn)行哈希和取模決定分片,所以如果把查詢場(chǎng)景***的字段設(shè)為 _routing 的值就能保證在對(duì)該字段查詢時(shí),只要查一個(gè)分片即可返回結(jié)果。

寫:

查:

對(duì)于日期類型,在業(yè)務(wù)能夠接受的范圍內(nèi),盡可能降低精確度。能只包含年月日,就不要包含時(shí)分秒。

當(dāng)數(shù)據(jù)量較大時(shí),這個(gè)優(yōu)化的效果會(huì)特別的明顯。因?yàn)榫仍降鸵馕吨彺娴?**率越高,查詢的速度就會(huì)越快。

同時(shí)內(nèi)存的重復(fù)利用也會(huì)提升 Elastic Search 服務(wù)器的性能,降低 CPU 的使用率,減少 GC 的次數(shù)。

系統(tǒng)監(jiān)控的實(shí)現(xiàn)

技術(shù)中心專門為業(yè)務(wù)部門開發(fā)了一套監(jiān)控系統(tǒng)。它會(huì)周期性的調(diào)用所有服務(wù)器的 Elastic Search CAT API,把性能數(shù)據(jù)保存在單獨(dú)的 Elastic Search 服務(wù)器中,同時(shí)提供一個(gè)網(wǎng)頁(yè)給應(yīng)用負(fù)責(zé)人進(jìn)行數(shù)據(jù)的監(jiān)控。

災(zāi)備的實(shí)現(xiàn)

Elastic Search 本身是分布式的。在創(chuàng)建索引時(shí),我們根據(jù)未來(lái)幾年的數(shù)據(jù)總量進(jìn)行了分片,確保單片數(shù)據(jù)總量在一個(gè)健康的范圍內(nèi)。

為了在寫入速度和災(zāi)備之間找到一個(gè)平衡點(diǎn),把備份節(jié)點(diǎn)設(shè)置為 2。

所以數(shù)據(jù)分布在不同的服務(wù)器上,如果集群中的一個(gè)服務(wù)器宕機(jī),另外一個(gè)備份服務(wù)器會(huì)直接進(jìn)行服務(wù)。

同時(shí)為了防止一個(gè)機(jī)房發(fā)生斷網(wǎng)或者斷電等突發(fā)情況,而導(dǎo)致整個(gè)集群不能正常工作,我們專門在不同地區(qū)的另一個(gè)機(jī)房部署了一套完全一樣的 Elastic Search 集群。

日常數(shù)據(jù)在復(fù)制分發(fā)的時(shí)候,會(huì)同時(shí)寫一份到災(zāi)備機(jī)房以防不時(shí)之需。

總結(jié)

整個(gè)項(xiàng)目的開發(fā)是一個(gè)逐步演進(jìn)的過(guò)程,實(shí)現(xiàn)過(guò)程中也遇到了大量問題。

項(xiàng)目上線后,應(yīng)用服務(wù)器的 CPU 與內(nèi)存都有大幅下降,同時(shí)查詢速度與沒有分片之前基本持平。在此分享遇到的問題和解決問題的思路,供大家參考。

參考:

  • Elastic Search官方文檔;
  • https://en.wikipedia.org/wiki/Database_index
  • https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95
  • https://logz.io/blog/solr-vs-elasticsearch/

責(zé)任編輯:武曉燕 來(lái)源: 攜程技術(shù)中心
相關(guān)推薦

2022-04-14 17:53:50

攜程AWS上云

2018-12-28 09:48:11

SolrElasticSear搜索

2021-04-12 10:38:17

ElasticSearSolrJava

2017-08-17 16:42:38

Elastic 全文搜索服務(wù)器

2014-11-25 10:09:59

ElasticSear分布式搜索引擎Lucene

2011-06-20 18:23:06

SEO

2017-01-17 15:18:42

2017-08-07 08:15:31

搜索引擎倒排

2020-03-20 10:14:49

搜索引擎倒排索引

2022-10-08 09:13:18

搜索引擎?站

2012-09-07 13:22:21

搜索搜狗

2009-02-19 09:41:36

搜索引擎搜狐百度

2010-04-20 11:43:46

2009-09-22 16:23:52

搜索引擎

2023-09-27 09:11:13

操作系統(tǒng)HTTP

2024-02-23 12:24:00

引擎數(shù)據(jù)

2020-10-13 09:25:27

ESClickHouse搜索引擎

2009-07-30 10:40:56

搜索引擎優(yōu)化網(wǎng)站

2023-02-08 10:45:23

2010-06-13 16:27:28

搜索引擎
點(diǎn)贊
收藏

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