使用Elasticsearch作為主資料儲存
荷蘭和比利時最大的電子商務公司 bol.com開始了為期4年的重新思考和重建其整個ETL(提取,轉換,載入) 管道的過程,該管道一直在陰暗的甲骨文 Oracle PL / SQL黑客的地牢中呼吸,處於腐爛狀態,導致生產上的不斷增加的短暫停頓。
重寫是不可避免的。在起草了許多藍圖後,我們選擇了Elasticsearch支援的Java服務作為主儲存!
這個想法給即使是最資深的Elasticsearch聘請的顧問帶來了挫折,所以為了讓你放心,我會告訴你為什麼我們採取如此激進的方法以及我們如何設法逃脫我們的舊系統遺產。
在深入瞭解詳情之前,讓我分享一下2,000英尺的電子商務搜尋設定概述,這將有助於您更好地瞭解前面討論的主題。請注意,這種簡化完全省略了合併快取層的星雲,編排多個搜尋叢集的系統,具有自定義重新整理和重放功能的佇列,就地彈性機制,維護不推薦使用的搜尋實體的服務,以避免因404引起的機器人排名,斷路器,節流器,負載平衡器等。但它仍然足夠準確,可傳達一般的想法。
搜尋
[在進一步討論之前,我想借此機會通過搜尋來確定我的意思。我希望這可以幫助您更好地圍繞ETL的最終消費者。話雖如此,請隨意跳過本節,直接跳到下一節的ETL深入部分。]
許多人傾向於犯錯誤,即在電子商務中對搜尋進行狹隘的觀察,並將其用例僅限於在一堆產品屬性中進行索引。我試圖提供一般性的,但遠非完整的概述,它可以實現:
- 在數百種產品屬性中搜索一個術語,其中匹配 和排名由直接或間接使用者決定的(您是PS4所有者搜尋最新的“使命召喚”的嗎?)和相關性(您可能通過鍵入”與“門和窗戶”有關的“門“,但是與部門無關),
- 瀏覽(基本上是沒有術語的搜尋)在數千個類別中使用上述搜尋中使用的類似排名機制,
- 如果輸入與某些模式(EAN,ISBN,ISSN等)或商品推銷規則相匹配。
- 隱含地觸發多項搜尋(例如縮小到較低的類別或擴大到更高的類別等)以增強結果,
- 裝飾每個列表(您可能希望在“Harddisks”支援中搜索/瀏覽時看到“容量”方面而不是“鞋尺寸”的細節)。
誰/什麼使用搜索?
一些使用者:
- 客戶:搜尋和購買商品的人。它們看起來是無害的,直到在ping%29" rel="nofollow,noindex" target="_blank">黑色星期五 使用,類似DDoS 攻擊。
-
機器人:他們定期(截至本文撰寫之日,每天最多幾次)嘗試將整個目錄消化到他們的系統中,主要用於兩個目的:
- 將目錄整合到他們自己的搜尋引擎(即Google)中,
- 調整他們的定價策略(即競爭對手)
處理機器人流量最糟糕的部分是你不能總是限制它們(例如,谷歌考慮到排名的網站延遲),你需要確保它們不會損害客戶流量。深思熟慮:想象一下,你的顧客在聖誕節前夕在你的商店裡蜂擁而至,谷歌決定用每秒數千個請求來捕捉整個目錄。
- 合作伙伴:您的業務合作伙伴還可以定期掃描您的目錄以整合到他們自己的系統中 (有趣的事實:有些甚至需要每日Excel匯出。)可以將它們歸類為僅對資料子集感興趣的機器人。
- 內部服務:上次我統計,除了上面列出的使用者之外,還有20多個內部服務使用搜索來增強他們的結果。它們的使用量最多可佔流量的50%。
在合作伙伴和內部服務的情況下,人們可能會爭論為什麼他們需要搜尋資料而不是直接訪問原始產品屬性和優惠。答案很簡單:它們還使用ETL管道中包含的其他屬性(例如,構成,類別)。因此,不是將內部ETL系統暴露給它們,而是在搜尋閘道器上管理它們更方便,已知搜尋閘道器具有經過實戰考驗的可擴充套件性和彈性測量。
效能怎麼樣?
在這個領域長達數十年的經驗,使搜尋速度提高10ms可以產生數百萬歐元的額外收入,具體取決於您的業務規模。不幸的是,這個等式也是相反的。因此,您總是希望在一定的延遲和高於某個吞吐量閾值的情況下執行。
內容有多不穩定?
非常非常非常不穩定!
- 產品可能有多個優惠(bol.com優惠,合作伙伴優惠等),具有不同的屬性(定價,可傳遞性,折扣等),其中兩個優惠和/或其屬性都是高度不穩定的。優惠可能缺貨,價格可能會發生變化等。雖然面向客戶的網頁在執行時使用最新資料進行了增強,但搜尋索引可能會落後並提供最終一致的檢視。這種情況下的波動可能從幾秒到幾個月不等。在黃金時間,例如在情人節那天,您不希望您的搜尋引擎返回幾秒鐘前缺貨的禮品列表。
- 您的手冊(由店鋪專家觸發)和自動(人工智慧,機器學習驅動)流程可以改變類別樹,新增新方面,調整現有方面的曝光,修改搜尋行為(例如,由商品推銷規則觸發的流量),新增上下文敏感(例如,依賴於類別)同義詞條目,同義詞,引入新的排名等。這些更改可能需要追溯更新數百萬個文件。
ETL
在電子商務搜尋領域,ETL 表示輸入是大量資訊源(產品屬性,報價,折扣,排名,構面,同義詞,同義詞條目等)的輸出,輸出是非 Denormalization" rel="nofollow,noindex" target="_blank">規範化 輸入構成針對搜尋查詢效能優化的搜尋就緒文件。等一等?如果一個ETL管道只是提供了一些優化目的,這聽起來不像沒有它可以進行搜尋嗎?排序......這在某種程度上確實是可能的。如果我們暫時擱置細節,我們可以大致比較兩種方法如下:
沒有ETL:
優點:輸入源中的每個更改都會立即生效。(因此,索引時間成本幾乎為零。)
缺點:由於在查詢時需要對輸入源進行連線和豐富操作,因此延遲和吞吐量會受到嚴重影響。
有ETL:
由於滿足搜尋請求的所有潛在資料已經被索引到索引中,因此搜尋需要最少的努力來在查詢時滿足請求。
輸入源的每次變化都需要預處理,影響從數百到數百萬的眾多產品。
換句話說,ETL完全是關於索引與查詢時間效能之間的權衡:
- 我們現有的ETL功能足夠全面,
- Elasticsearch的查詢時間效能已經因為分面faceting,內部觸發的查詢等而受到影響,在某種程度上外部快取成為必需,
- 搜尋延遲對收入有很大影響,
我們採用了厚厚的ETL管道路徑。
實時內容流
在這裡,ETL管道從十幾個佇列中偵聽從產品屬性到報價,特定報價折扣到排名等更新,所有這些都是用JSON 格式化的。幸運的是,每個實時內容流訊息都會觸發單個產品更新。讓我用一個案例來舉例說明:當disk_capacity_bytes產品的屬性發生變化時,我們
- 首先從儲存中獲取相關文件,
- 更新其disk_capacity_bytes屬性,
- 應用與更新文件的最後狀態匹配的配置,
- 並持久取得的結果。
這裡有一些問題需要解決:兩個關鍵問題:
- 您如何表示配置謂詞,以便您可以將它們與內容進行匹配?
- 您如何表示配置變異,以便您可以針對內容執行它們?
配置流
配置是通過業務友好的螢幕定義的規則。每個已釋出的配置最終都有三個用途:
- 搜尋閘道器使用它來確定如何查詢搜尋索引,
- ETL管道使用它來處理實時內容流,
- 和ETL管道追溯更新可能受影響的文件。
雖然前兩個是相對便宜的操作,但最後一個是房間裡的大象!這是我們迄今為止描述的美麗故事中第一次我們需要將更改傳播到數百萬個文件。(banq注:這好像是EventSourcing,事件溯源追溯)
這裡省略原文各個資料庫用來實現ES的比較,其實肯定都不行。原文作者可能沒有意識到事件這個概念,執著於操作變更的複雜跟蹤。
舊ETL
舊的ETL是一個Oracle資料庫,其中的配置是在PL / SQL中建模的。由於配置抽象語言是資料庫使用的完全相同的語言,因此執行突變和謂詞是毫不費力的。HailSQL注入 功能!雖然這帶來了一些顯著的成本:
- 在抽象模型中使用PL / SQL建立了功能和財務供應商鎖定。功能缺陷(表達能力不足,PL / SQL洩漏到不相關的元件)多年來阻礙了許多創新,隨著時間的推移,它變得越來越困難。此外,它構成了將服務遷移到雲的重大障礙。它的財務方面在bol.com 的規模上可以忽略不計。
- 回滾更新配置變異的變化是PL / SQL工程在實踐中努力實現的。這種困難,加上日誌,測試,除錯,分析等實用程式的不足,使程式設計師不再採取這種方式。因此,每晚有超過12個小時的完整ETL執行配置快照增量。由經驗豐富的工程師馴服的這種野獸有著頻繁暫停的影響,並且使得bug很難除錯,查詢和重現,更不用說修復了!
在其先前的版本中,內容屬性以<id, content_id, key, value>標準化形式儲存。這種方法開始受到鉸鏈中效率疼痛的影響,將ETL資料拉到搜尋索引。當時僱傭的Oracle顧問檢查了這些用法,並建議使用非規範化結構,其中每個屬性都儲存為一列。除了臨時包紮相關的傷口之外,這還允許DBA讓他們的想象力變得狂野,將屬性對映到列。問題:
- PL / SQL中的任務並行化非常困難。我們嘗試通過內部Oracle AQ修補此漏洞,但我不確定它是否改善或惡化了狀態。
- 在預計執行12個小時以上的資料庫程式中,出現墨菲定律,我們明智地(!)設計了系統,以便在某些檢查點保持其狀態,這些檢查點構成可重複的處理,這樣在早上來時可看到ETL崩潰。
- 移動元件的數量需要使用支援Oracle的專有排程工具 。該計劃與bash/" rel="nofollow,noindex" target="_blank">bash 指令碼粘合在一起,設計在僅適用於Windows的專有開發環境中,並在執行GNU / Linux的Oracle機器上推出。GNU / Linux和使用開發人員的Windows都不喜歡這種情況。
- 由於ETL出現故障的成本很高,企業也無法輕易改變和/或進行業務優化。這是一個非常令人失望的問題,對技術和商業有影響的人士卻需要使用它。
儲存引擎之戰
鑑於我們的功能要求,我們評估了幾個不同的ETL管道儲存解決方案:PostgreSQL、MongoDB、Elasticsearch。
ostgreSQL結果被省略的原因是無論我們丟擲什麼樣的優化,基準測試總是花費超過2小時,無論分割槽如何,而MongoDB和Elasticsearch花了幾分鐘。
讓我分享一些結果的意見:
- 增加併發性可提高Elasticsearch效能(最多32個併發批處理),但對MongoDB沒有太大影響。
- Elasticsearch在效能方面受到了衝擊,儘管它受到整個文件更新的影響,而MongoDB只是嘗試更新單個屬性。使用32個併發批次,Elasticsearch和MongoDB分別花費了175s和518s來完成基準測試。
- 與MongoDB相比,Elasticsearch產生了更可預測的效能資料。請注意75和99百分位數之間的差異。
- Elasticsearch段合併在執行期間出乎意料地非常穩定,而我們預計它會因高更新率而成為瓶頸。但是,在_version欄位上播放的比較和交換迴圈允許必要的資料完整性而不會出汗。
在測試時,由於我們的操作障礙,我們最初無法在MongoDB中啟用分片。儘管Elasticsearch的結果非常有希望,但即使是受僱的Elasticsearch顧問也感到震驚,我們決定採用它,我們擁有多年的生產經驗。如果我們將白名單配置謂詞欄位問題的必要性放在一邊 - 也就是說,可以查詢的內容需要明確的索引 - MongoDB也很可能是一個可行的選擇。
為什麼Elasticsearch有一個不被推薦為主要資料儲存的聲譽?我認為這一切都始於幾年前官方專案網站包含一個明確的宣告,承認Elasticsearch並不打算用作主資料儲存。
下面是它的一些特點:
- 安全性:Elasticsearch不提供開箱即用的任何安全措施(加密等)。我們不使用Elasticsearch來儲存任何型別的PII 。
- 事務:Elasticsearch沒有事務支援。雖然我們通過在_version 欄位上執行比較和交換迴圈來解決它。
- 工具:Elasticsearch工具......只是一塊垃圾。它沒有適當的開發環境 - 你只能執行一個完全成熟的Kibana才能使用它的 控制檯 。它的Java客戶端以Elasticsearch整個像銀河系一樣多的元件為依賴,這是一個等待爆炸的JAR地獄 定時炸彈。此外,最近推出的高階REST客戶端 洩漏了Apache HTTP Client API模型等。對於洩露的模型和傳遞依賴性,您無能為力 - 您只需學會與它們共存。對於IDE,您只需使用您喜歡的HTTP客戶端保留一大堆 HTTP請求配方,例如 curl.haxx.se/2" rel="nofollow,noindex" target="_blank">cURL ,Postman , httpie 等
- 文件:Elasticsearch沒有文件; PostgreSQL有文件 ,MongoDB有文件 。Elasticsearch所擁有的是一堆表面 令人搔癢的部落格文章,以類似文件的網站形式提供 。Elasticsearch還有Stack Overflow 和論壇 帖子的海洋,您可以在方便的時候游泳。話雖這麼說,人們需要承認,隨著時間的推移情況正在改善。(是的,情況更糟!)
- 彈性:是的,Elasticsearch可能會崩潰,就像另一個軟體一樣。為了應對這些緊急情況,除了熱備用叢集之外,我們還會定期拍攝快照 並將ETL管道處理的訊息儲存到單獨的儲存中,從而提供高效的寫入和批量讀取操作,例如PostgreSQL,Google BigQuery等。在需要的情況下,我們只需從快照恢復並重放必要的訊息集以恢復丟失的狀態。
更多詳細資料可點選標題檢視原文,個人認為作者沒有采取業界通用的模式,就是在主資料庫與ETL之間採用Apache Kafka,將Elasticsearch成為Kafka的一個數據源,對於特定的使用者比如外部客戶,機器人或內部客戶採取不同的資料來源,針對客戶設計不同的資料結構,通過Kafka匯出轉換。