天天看點

把ElasticSearch當成是NoSQL資料庫

Elasticsearch 可以被當成一個 "NoSQL"-資料庫來使用麼? NoSQL 意味着在不同的環境下存在不同的東西, 而erestingly 它并不是真的跟 SQL 有啥關系. 我們開始隻會覺得 "可能"而已, 是以細細研究了 Elasticsearch 的各種屬性,包括它已經為了成就最具靈活性,可伸縮性和性能優異的分析查詢引擎的那些屬性。

NoSQL 資料庫是什麼?

NoSQL-資料庫 将 NoSQL 定義為“下一代主要解決如下問題的資料庫: 非關系型的,分布式的,開元的并且可以扁平擴充.”. 換言之,它并不是一個精确的定義.

它尤其與SQL無關. 比方說, Hive 查詢語言的靈感顯然來自 SQL.  Esper查詢語言同樣如此, 隻是它操作的是流而不是關系. 還有你知道 PostgreSQL 過去被命名為 “Postgres” 并使用 “Quel” 作為它的查詢語言麼? 而首先作為一個關系型資料庫管理系統( ORDBMS), 它現在同樣有許多的特性使其具備無模式文檔存儲的能力.

它同樣也和ACID-特性無關. Hyperdex 就是一個 NoSQL-資料庫的例子,它的目标就是提供 ACID-事務能力. MySQL, 确實是一個 SQL-資料庫, 曆史上它有一段解釋 ACID 的真正意義的暧昧時期.

關系型的? 雖然大多數的 NoSQL-資料庫并不支援加入傳統關系型資料意義相同的功能,但還是有一些那樣做了,并将其留給使用者當做練習使用. RethinkDB, Hive 還有 Pig, 等等. Neo4j, 面向圖形的資料庫, 确實是處理關系用的 - 它擅于周遊圖中的關系 (比如,圖中的邊) . Elasticsearch 有一個概念叫做加入父子關系的“查詢時間”和加入嵌套類型的“索引時間“.

分布式的? 已經有一些分布式的 SQL-資料庫 了, 并以 一些項目 旨在做一些像一個NoSQLite那樣的事情, 更新一代的資料庫趨向于在某些方式上具備分布式能力.

總而言之, 既沒有道理給 NoSQL 做出精确的定義, 也不能簡單的說 Elasticsearch 是一個“文檔存儲”-類型的NoSQL-資料庫. 在我寫這篇文章的時候, nosql-database.org 列出了超過20 個那樣的東西.

在下一節,我們将關注一些重要的屬性并且看看 Elasticsearch 為什麼要實作或者不去實作它們。

無事務

Lucene, 是 Elasticsearch 的建構的基礎, 它是由一個事務的概念的. 而Elasticsearch在另外的方面, 并沒有典型意義的事務. 對于已經送出的文檔并沒有辦法復原, 而你也不能送出一組文檔并且為它們所有或者其中一些建立索引. 然而它所具備的, 是一個用來確定業務過程持久性而不用做昂貴的Lucene送出的預寫日志. 你也可以指定索引操作的一緻性級别, 以確定在傳回之前有多少副本可以拿來确認操作條件. 預設的是法定人數, 例如 ⌊n2⌋

在逐個切片進行處理的方式中,當一個索引被重新整理時,預設是一秒鐘一次,就需要對變更的可見性進行控制。

通過制定送出文檔的版本,可以進行樂觀并發控制。

Elasticsearch追求的是速度。支援分布式事務是一大塊工作。不支援分布式事務會使得很多事情變得容易起來。隻要我們能接受讀取到的資料 有些陳舊,而且所有人看到的是同一時間點的資料,那麼Elasticsearch就可以利用緩存提供很多服務 - 這對于我們鐘愛的極速性能來說是至關重要的。

模式靈活

Elasticsearch 不要求你先指定模式。扔給它一個 JSON 文檔,它就會進行一些訓練有素的猜測來推斷其類型。對于數值、布爾、時間戳它可以做的很好。對于字元串,它會使用“标準化”的分析,這通常是良好的開始。

它是有商榷的“無模式”,在這個意義上你不必指定一個模式,我們更願意把它認做是“模式靈活”。為了開發大規模的搜尋、分析,你确實需要對模式進行 微調。Elasticsearch 有大量的強大工具可以幫助你,例如動态模闆、多字段對象等。這在我們關于映射的文章裡會談及更多。

關系和限制

Elasticsearch是一種面向文檔的資料庫。你想要對之進行搜尋的整個對象關系圖,都需要進行索引,在對文檔進行索引之前,它們必須先被反規範化。反規範化提升了查詢性能(因為不再需要進行關聯查詢),使用了更多存儲空間(因為資料必須被存儲多次),但是,要保持資料一緻性和實時性則更加困難(因為任何資料改變都必須被寫入到所有執行個體中去)。不過,對于一次寫入頻繁讀取的工作場景,它的表現相當優異。

舉例來說,假設你在資料庫中存儲了客戶、訂單和産品等資料,現在你想要通過産品名字和客戶姓名來查找訂單。可以這樣來解決這個問題:在對訂單進行索引時, 把客戶和産品的所有必要資訊都加進來。這樣的話,查詢就非常簡單,但是當你想要改變某個産品的名字時會出現什麼情況呢? 在進行了良好規範化的關系型模型中,你隻需要修改該産品對應的單條記錄就搞定了。這是關系型資料庫所擅長的。而在反規範化的文檔資料庫中,将不得不更新與 該産品有關的所有訂單。

換句話說,在面向文檔類型的資料庫中,比如Elasticsearch, 我們對文檔進行映射和存儲設計隻是為了優化查詢和資訊擷取的性能。

在介紹中已經提到,Elasticsearch中可以使用父/子-關系進行“查詢時”連結,也可以使用内嵌類型進行“索引時”連結。我們會在以後的文章中對該主題進行深入介紹。我們推薦Martijn van Groningen的一篇文章“Document relations with Elasticsearch”.

大多數關系型資料庫也會允許你指定限制關系,來定義什麼需要保持一緻性,什麼不需要保持一緻性。比如,參照完整性和唯一性都是強制性的。你可以要求賬戶變更金額必須是正數,等等。而面向文檔的資料庫不傾向于這麼做,Elasticsearch就是如此。

魯棒性

一個資料庫應當是魯棒的,尤其是當它是你權威的記錄系統時。理想情況下,一個耗費資源的查詢應當可以被撤銷,你肯定不希望資料庫停止工作,除非你指令它停下來。

不幸的是,Elasticsearch (以及它的元件)目前并沒有很好的處理OutOfMemory錯誤。我們在Elasticsearch in Production, OutOfMemory-Caused Crashes一文中進行了更加深入的讨論。是以,給Elasticsearch配置足夠多的記憶體就顯得非常重要,而且在生産叢集中要謹慎運作那些無法預知将會耗費多少記憶體的查詢。

不過,随着Elasticsearch越來越成熟,這個問題很可能會得到改善,記住Elasticsearch的目标是追求速度,是以它假設記憶體永遠是充足的。

分布式

另請參考: Elasticsearch in Production, Networking.

作為一個分布式的系統,Elasticsearch的上手和使用都令人難以置信的簡單,但是分布式系統本身是很複雜的。關于這一點,我們在Elasticsearch in Production, Networking有更多讨論,是以下面隻是一個簡短的摘要。

分布式系統天生的特性,意味着很多事情都可能會出錯。同樣的,不同的資料庫系統緻力于擁有不同強項: 有些力争強大的安全保證,另外一些則緻力于高可用性,即使某些時候(甚至多數時候)出現錯誤也在所不惜。而且,正如Kyle Kingsbury在他傑出的網絡分區的風險系列文章中所指出的那樣,當問題發生時,實際上資料庫系統并沒有像它們所宣稱的那樣來處理問題。簡言之,他發現當分布式資料庫運作良好晴空萬裡時,絕大部分資料庫在遭受到大量可能的問題時所做的努力,都會以失敗而告終。

在一緻性,可用性,以及分區容錯性方面,Elasticsearch 是一個CP系統,一個相當不靠譜的“一緻性”定義。如果你有一個隻讀的工作負載, Elasticsearch 允許你通過不嚴格的“最小主節點”要求(如不需要quorum)實作AP行為。然而,通常你需要叢集中大量節點是可用的。寫入一個配置錯誤的沒有大量節點 的叢集,像“split brain”叢集,可能引起無法恢複的資料丢失。這不隻是特定于Elasticsearch的。

Elasticsearch 選擇自己的主節點。然而這是一個相當簡單但不是非常可靠的算法,這在現實世界的網絡壓力下可能導緻很多問題。事實上,我們管理成百上千的叢集,經常看到主節點選擇問題,是以我們主動将主節點移入ZooKeeper, 當然我們也有其他目的。

在拓展性方面,索引被分到了一個或多個碎片中。這在索引建立時就指定了并且不能改變。是以,随着預期的增長,一個索引應該被合理的分割。随着越來越 多的節點添加到Elasticsearch叢集中來,它在重新配置設定和移動碎片上表現良好。是以,Elasticsearch很容易拓展。

安全

另請參閱: Elasticsearch in Production, Security.

Elasticsearch沒有提供授權和認證特性。你可以認為,任何人隻要能連接配接到你的Elasticsearch叢集,就擁有了“超級使用者”權限,尤其是當Elasticsearch的強大腳本功能被激活時。

總結

如果本文描述的這些限制都不能阻止你,你當然可以使用Elasticsearch作為主存儲庫。一個不錯的例子是,當你使用Logstash時。Logstash是一個神奇的工具,用來管理日志并把它們導入到Elasticsearch中,你可以隻是對日志進行備份以防萬一。日志都是一次寫入,多次讀取的。不需要更新,不需要事務支援,沒有完整性限制,等等。

那麼像Postgres那樣的系統怎麼樣呢,它有全文檢索和ACID-事務。 (其它例子包括MySQL, MongoDB, Riak等等的全文檢索能力) 你當然可以通過Postgres來實作基本的檢索,但是在性能上和功能上與ElasticSearch都有巨大的差距。正如我們在事務那 一節中所提到的,Elasticsearch會做很多緩存,是以有可能會“欺騙”我們,而且不關心多版本之間的并發控制以及其它複雜的事情。搜尋遠不止在 一段文本中找到一個關鍵字那麼簡單:它是利用領域特定知識來實作良好的相關度模型,由此給出整個結果空間的一個全貌,并且能做拼寫檢查和自動補全之類的工 作。而且所有這些工作都要保證速度。

Elasticsearch通常被用作其它資料庫的補充。那樣的資料庫系統要有強大的資料限制保證、容錯性和魯棒性、高可用性和帶事務支援的資料更 新能力,它維護着核心資料 - 這些資料随後會被異步推送到Elasticsearch中去(也可能是抽取,前提是你使用了Elasticsearch的某一種“rivers”)。 保持資料同步是我們打算将來撰文深入探讨的話題。這裡,在Found網站的文章中,我們使用具有代表性的PostgreSQL和ZooKeeper來提供 源資料,并把這些資料輸入給Elasticsearch來提供強大的搜尋。

像其它所有事情一樣,沒有包治百病的靈丹妙藥,沒有一個資料庫可以做到所有的事情。也許這種情況會永遠持續下去,是以一定要了解你的資料庫的優點和弱點!