概覽一下大數(shù)據(jù)項(xiàng)目中可以使用的數(shù)據(jù)存儲(chǔ)技術(shù),聚焦于Couchbase 和 ElasticSearch,展示如何使用以及它們的區(qū)別,先理解一下NoSQL領(lǐng)域中各種不同的技術(shù)。
NoSQL
關(guān)系型數(shù)據(jù)庫是過去的選擇,幾乎是許多開發(fā)者和DBA對(duì)于傳統(tǒng)三層架構(gòu)應(yīng)用的唯一選擇。使用這一場景有很多原因,數(shù)據(jù)建模方法,查詢語言與數(shù)據(jù)交互,保證數(shù)據(jù)的一致性部署,并能夠?yàn)閺?fù)雜的應(yīng)用服務(wù)。
然而,這不是解決所有數(shù)據(jù)存儲(chǔ)問題的唯一方案,也是NoSQL 產(chǎn)生的原因。NoSQL 提供了新的方法而不是采用面向標(biāo)準(zhǔn)SQL的范式。
NoSQL 技術(shù)與高伸縮性無縫融合,很多技術(shù)同時(shí)具備了高分布性和高性能。大多數(shù)時(shí)間里,它們使 現(xiàn)有RDBMS 技術(shù)所實(shí)現(xiàn)的架構(gòu)更加完整,例如 作為緩存服務(wù)器,搜索引擎,非結(jié)構(gòu)化存儲(chǔ),易變信息存儲(chǔ)等。主要分為4類:
Key/value
列存儲(chǔ)
面向文檔的存儲(chǔ)
圖存儲(chǔ)
現(xiàn)在深入到各種技術(shù),選擇最適用我們場景的技術(shù)。
Key/Value
第一個(gè)也是最早的 NoSQL 數(shù)據(jù)存儲(chǔ)就是key/value. 這些數(shù)據(jù)就像字典一樣根據(jù)key來匹配value,通常使用在需要高性能的基本信息存儲(chǔ),例如需要快速讀寫的session信息,這些存儲(chǔ)在這樣的情景非常高效,也通常具有高伸縮性。
Key/value也經(jīng)常被用于上下文的隊(duì)列化來保證數(shù)據(jù)不丟失,例如日志架構(gòu)或搜索引擎的索引架構(gòu)。Redis 和Riak KV 是非常有名的key/value數(shù)據(jù)存儲(chǔ); Redis 使用的更加廣泛,因?yàn)樗兄粋€(gè)內(nèi)存型 K/V 存儲(chǔ),并且持久化是可選的。Redis 經(jīng)常用于web應(yīng)用中來存儲(chǔ)session相關(guān)的數(shù)據(jù),例如node或者-
PHP的 web應(yīng)用 ; 每秒鐘可以提取成千上萬的session信息而沒有性能損失。另一個(gè)典型場景是后面要講到的序列化:Redis位于 Logstash 和 ElasticSearch 之間來存儲(chǔ)t ElasticSearch 查詢中的索引。
Column
由于要存儲(chǔ)超大量的記錄信息 到達(dá)了key/value存儲(chǔ)限制的時(shí)候就需要用到列存儲(chǔ)。列存儲(chǔ)技術(shù)對(duì)于RDBMS世界的工程師可能不太容易理解,但事實(shí)上非常簡單。RDBMS 中數(shù)據(jù)是按行存儲(chǔ)的,而列存儲(chǔ)中是按列的。使用列數(shù)據(jù)庫的主要好處是能高速訪問海量數(shù)據(jù)。 RDBMS的一行在硬盤上是一個(gè)連續(xù)的存儲(chǔ),多行可能存儲(chǔ)在硬盤不同的位置,使訪問稍顯復(fù)雜,在列數(shù)據(jù)庫中的一列數(shù)據(jù)是連續(xù)存儲(chǔ)的。
舉個(gè)例子,考慮在RDBMS中查詢索引博客的標(biāo)題,尤其是有數(shù)百萬數(shù)據(jù)的時(shí)候,需要大量的IO操作,而在列數(shù)據(jù)庫中,這樣的查詢只是一次訪問。這樣的數(shù)據(jù)庫在從特定簇提取海量數(shù)據(jù)中非常順手,但此消彼長的是缺乏靈活性。使用最多的列存儲(chǔ)數(shù)據(jù)庫是
Google Cloud Bigtable, 但開源的列存儲(chǔ)數(shù)據(jù)庫是Apache HBase 和Cassandra.
列存儲(chǔ)數(shù)據(jù)庫的另一個(gè)好處是容易伸縮,這些列在海量存儲(chǔ)時(shí)具有高伸縮性。這就是為什么它們主要用于保存非易變且長久保留信息的原因。
Document
列存儲(chǔ)數(shù)據(jù)庫對(duì)于含有比較深嵌套結(jié)構(gòu)的結(jié)構(gòu)化數(shù)據(jù)的存儲(chǔ)不是最好的,這種場景需要使用面向文檔的數(shù)據(jù)存儲(chǔ)。數(shù)據(jù)實(shí)際上以key/value 存儲(chǔ),但是所有壓縮的數(shù)據(jù)叫做文檔。 文檔依賴于一個(gè)結(jié)構(gòu)或者編碼例如XML, 但更多時(shí)候是 JSON (JavaScript Object Notation).
盡管文檔型數(shù)據(jù)庫對(duì)于數(shù)據(jù)的結(jié)構(gòu)化存儲(chǔ)和表達(dá)都非常有用,但也有其脆弱的一面,特別是與數(shù)據(jù)的交互性操作。它們基本上要遍歷整個(gè)文檔,例如當(dāng)讀取某個(gè)特定字段的時(shí)候,遍歷可能會(huì)影響性能。
當(dāng)需要存儲(chǔ)嵌套信息的時(shí)候,可以采用文檔型數(shù)據(jù)庫。例如,考慮怎樣表達(dá)應(yīng)用中的一個(gè)賬戶,大概有以下信息:
基礎(chǔ)信息:姓名,生日,照片 ,URL, 創(chuàng)建日期等等
復(fù)雜信息: 地址,認(rèn)證方法(password, Facebook, 等第三方認(rèn)證),興趣等等。
這也是NoSQL 文檔型數(shù)據(jù)庫經(jīng)常用到web應(yīng)用的原因: 表達(dá)嵌套對(duì)象非常容易,由于都使用JSON,還可以與前端的JavaScript技術(shù)無縫集成。
使用最多的文檔型數(shù)據(jù)庫是MongoDB, Couchbase, 和 Apache CouchDB,都非常容易安裝和啟動(dòng),有很好的文檔說明,而且都是可伸縮的,除此之外,它們也是開放現(xiàn)代web應(yīng)用的明確選擇。
Couchbase 是我們架構(gòu)中選擇的技術(shù),使用它來存儲(chǔ),查詢和組織數(shù)據(jù)。原因是基于它的性能基準(zhǔn)測試,它的高吞吐量操作時(shí)延低于MongoDB.
還有一個(gè)值得關(guān)注的是,Couchbase 今天是 CouchDB 和Memcached的結(jié)合體。從支持的角度上看,使用CouchBase更顯得有意義。
Graph
Graph 數(shù)據(jù)庫與其它數(shù)據(jù)庫有著本質(zhì)的區(qū)別。它使用了不同的范式來表達(dá)數(shù)據(jù)——樹結(jié)構(gòu),節(jié)點(diǎn)和邊連接起來叫做關(guān)系。這些數(shù)據(jù)庫是隨著社交網(wǎng)絡(luò)而誕生的,例如表達(dá)用戶的好友網(wǎng)絡(luò),他們的好友關(guān)系等等。對(duì)于其它類型的數(shù)據(jù)存儲(chǔ),可能把一個(gè)用戶的好友關(guān)系存儲(chǔ)在一個(gè)文檔中,但是,存儲(chǔ)好友關(guān)系還依然非常復(fù)雜;使用圖數(shù)據(jù)庫就非常簡單,為每個(gè)好友創(chuàng)建節(jié)點(diǎn),通過關(guān)系連接他們,依賴查詢的需要和范圍瀏覽圖。
最著名的圖數(shù)據(jù)庫是Neo4j, 象前面所說的,主要使用場景是處理復(fù)雜的關(guān)系信息,例如實(shí)體間的連接,也可以用于分類的場景。
Figure 2-1 展示了在圖數(shù)據(jù)庫中3個(gè)實(shí)體是如何連接的。
Figure 2-1. Graph database example
圖中的兩天賬戶節(jié)點(diǎn)Jane 和 John, 它們之間的每一條邊定義了他們的關(guān)系,在某天相互認(rèn)識(shí),另一組節(jié)點(diǎn)連接的兩個(gè)賬戶展示了Jane 和 Joh在某天后都成為了足球組的成員。
我們使用場景中的NoSQL
根據(jù)我們的使用場景,首先需要一個(gè)文檔型的 NoSQL數(shù)據(jù)庫,將存儲(chǔ)在關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)結(jié)構(gòu)化的一個(gè) JSON 文檔. 如前所述,傳統(tǒng)的RDBMSs 將數(shù)據(jù)存儲(chǔ)到多個(gè)有關(guān)系的表,當(dāng)?shù)玫揭粋€(gè)完整對(duì)象時(shí)變得比較復(fù)雜和低效。讓我們?cè)贔igure 2-2. 中看一個(gè)賬戶被分割成多個(gè)表的例子。
Figure 2-2. Account tables
如果要獲得所有的賬戶信息,基本上需要join兩到三個(gè)表?,F(xiàn)在考慮這樣的情形: 需要處理所有用戶在應(yīng)用中的每一次連接,這些連接有著不同的商業(yè)邏輯。 最后,想要賬戶自身的視圖。通過傳遞一個(gè)賬戶標(biāo)識(shí)通過API從全部用戶視圖中得到一個(gè)怎樣的文檔呢?
{
"id": "account_identifier",
"email": "account@email.com",
"firstname": "account_firstname",
"lastname": "account_lastname",
"birthdate": "account_birthdate",
"authentication": [{
"token": "authentication_token_1",
"source": "authenticaton_source_1",
"created": "12-12-12"
}, {
"token": "authentication_token_2",
"source": "authenticaton_source_2",
"created": "12-12-12"
}],
"address": [{
"street": "address_street_1",
"city": "address_city_1"
"zip": "address_zip_1"
"country": "address_country_1"
"created": "12-12-12"
}]
}
好處顯而易見: 通過保持一個(gè)實(shí)體的 JSON 表達(dá),可以更快更好的訪問數(shù)據(jù)。進(jìn)一步,將這一方法通用化,從NoSQL數(shù)據(jù)庫讀取所有的讀操作,而讓所有的寫操作 (create, update,delete) 還在RDBMS上 .但我們必須實(shí)現(xiàn)一個(gè)邏輯來維持 RDBMS到NoSQL 的數(shù)據(jù)同步,如果沒在緩存中的話還要?jiǎng)?chuàng)建一個(gè)關(guān)系型數(shù)據(jù)庫的對(duì)象。
當(dāng)我們?cè)贜oSQL高效可伸縮地創(chuàng)建文檔時(shí)問什么還要保持 RDBMS呢?因?yàn)檫@不是我們應(yīng)用的真正目的。我門不想產(chǎn)生一個(gè)Big Bang 的影響. 假設(shè)RDBMS已經(jīng)準(zhǔn)備好了,但因?yàn)镽DBMS缺乏靈活性而集成了一個(gè)NoSQL存儲(chǔ)。希望充分利用兩個(gè)最好的技術(shù) —特別是RDBMS的數(shù)據(jù)一致性和NoSQL的伸縮性 。
除此之外,這是一個(gè)簡單查詢的例子,但是希望更進(jìn)一步,例如文檔中任意字段的全文檢索。那么,在關(guān)系型數(shù)據(jù)庫中如何做的呢?是索引,但是要索引表中所有的列么?實(shí)際上,這是不可能的,但可以輕松地使用NoSQL技術(shù)做這件事,例如ElasticSearch. 在我們深入一個(gè)NoSQL 緩存系統(tǒng)之前,先看一下如何使用 Couchbase 這一文檔型數(shù)據(jù)庫,然后回顧它的局限再切換到ElasticSearch。
先看一下Couchbase這一可伸縮架構(gòu), 但因?yàn)镃ouchbase 的一些嚴(yán)重局限, 還是在遷移前看一下?lián)碛蠩lasticSearch的完整架構(gòu)。
Couchbase 介紹
Couchbase是一個(gè)開源的文檔型數(shù)據(jù)庫,有著靈活的數(shù)據(jù)模型,性能和伸縮性都適合我們的使用場景,將關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)存儲(chǔ)到一個(gè)結(jié)構(gòu)化的 JSON 文檔.大多數(shù)NoSQL技術(shù)有著類似的架構(gòu)—首先看 Couchbase 架構(gòu)師如何組織的,然后介紹 Couchbase中命名約定, 再深入到存儲(chǔ)數(shù)據(jù)是如何查詢的,最后討論跨數(shù)據(jù)中心的復(fù)制。
架構(gòu)
Couchbase是一個(gè)真正的無共享架構(gòu),這意味著沒有單點(diǎn)故障,因?yàn)榧褐械拿總€(gè)節(jié)點(diǎn)都是自給自足而且獨(dú)立的。分布式技術(shù)工作的方式如何?——各節(jié)點(diǎn)不共享任何內(nèi)存或硬盤存儲(chǔ)。文檔以JSON或者二進(jìn)制形式存儲(chǔ)在Couchbase中,在集群間復(fù)制,所組織的單元叫buckets. 一個(gè)bucket 通過設(shè)置RAM緩存來根據(jù)存儲(chǔ)和訪問需求完成伸縮,還可以設(shè)置彈性副本的數(shù)量。 從底層看, bucket 被分割成叫做vBuckets 的小單元,實(shí)際上是數(shù)據(jù)分區(qū)。 Couchbase 使用一個(gè)集群映射將分區(qū)和服務(wù)器關(guān)聯(lián)起來。一個(gè)Couchbase服務(wù)器在一個(gè)集群內(nèi)對(duì)一個(gè)bucket有3個(gè)副本,每個(gè) Couchbase 管理vbucket 激活或副本的子集。 這就是Couchbase的彈性原理; 每個(gè)文檔的每次索引,都有副本,如果集群中的一個(gè)節(jié)點(diǎn)掛了,集群將激活副本分區(qū)來保證連續(xù)的服務(wù)。
Figure 2-3 解釋了集群中只有一個(gè)激活的數(shù)據(jù)拷貝同時(shí)有一個(gè)或多個(gè)副本。
Figure 2-3. Couchbase active document and replicas
從客戶端視角看,如果使用智能客戶端(Java, C, C++,Ruby等.), 然后這些客戶端連接集群映射; 客戶端從應(yīng)用發(fā)送請(qǐng)求到合適的服務(wù)器. 就交互而言,有非常重要的一點(diǎn): 文檔操作默認(rèn)是異步的。這意味著當(dāng)你更新文檔的時(shí)候,Couchbase 不能在硬盤上立即更新數(shù)據(jù)。Figure 2-4. 呈現(xiàn)了真實(shí)的處理過程。
Figure 2-4. Couchbase data flow
如 Figure2-4 所示, 智能客戶端連接到一個(gè) Couchbase 實(shí)例,首先異步將文檔寫到緩存中,客戶端立即得到響應(yīng)而不是阻塞到數(shù)據(jù)流處理完,當(dāng)寫操作完成時(shí)由客戶端改變行為狀態(tài)。然后,文檔被放入集群那邊的寫隊(duì)列,所以在集群間復(fù)制; 此后, 文檔被放入硬盤存儲(chǔ)的寫隊(duì)列來持久化到相關(guān)節(jié)點(diǎn)。如果部署了多集群,Cross Data Center Replication (XDCR) 特性可以在不同集群間傳播這種數(shù)據(jù)改變,集群可以位于不同的數(shù)據(jù)中心。
Couch base有自己的數(shù)據(jù)查詢方法; 實(shí)際上, 簡單地使用文檔ID就可以查詢文檔,Couchbase的強(qiáng)大在視圖特性的內(nèi)部. Couchbase 中, 有一個(gè)二級(jí)索引叫做設(shè)計(jì)文檔,是在bucket內(nèi)部創(chuàng)建的. bucket可以包含文檔的多個(gè)類型,例如一個(gè)簡單的電子商務(wù)應(yīng)用的bucket 包含如下內(nèi)容:
- Account
- Product
- Cart
- Orders
- Bills
Couchbase 使用設(shè)計(jì)文檔來完成它們的邏輯分割. 一個(gè)bucket 可以包含多設(shè)計(jì)文檔 , 也包含了多視圖. 一個(gè)視圖是由用戶定義bucket內(nèi)的索引文檔的函數(shù)。該函數(shù)是用戶定義的map/reduce 函數(shù)將文檔映射到集群中,輸出 key/value 對(duì), 存儲(chǔ)在索引中用于將來的信息提取?;仡欕娚叹W(wǎng)站的例子,嘗試從帳戶標(biāo)識(shí)的所有訂單中建立索引. map/reduce 函數(shù)如下所示:
function(doc, meta) {
if (doc.order_account_id)
emit(doc.order_account_id, null);
}
if 判斷語句允許函數(shù)聚焦在一個(gè)文檔,它包含了order_account_id 字段然后索引這一標(biāo)識(shí)。因此,任何客戶端都可以根據(jù)這一標(biāo)識(shí)從Couchbase中查詢數(shù)據(jù)。
Cluster Manager 和管理控制臺(tái)
Cluster manager 是集群中一個(gè)特殊的節(jié)點(diǎn)。在任何時(shí)候,如果集群內(nèi)的一個(gè)節(jié)點(diǎn)掛了, orchestrator 通過通知集群內(nèi)所有其它節(jié)點(diǎn)來處理故障切換, 定位故障節(jié)點(diǎn)的副本分區(qū)來使之處于激活狀態(tài). Figure 2-5 描述了故障切換處理。
Figure 2-5. Couchbase failover
如果 orchestrator 節(jié)點(diǎn)掛了,所有節(jié)點(diǎn)都可以通過心跳監(jiān)控檢測到,這個(gè) watchdog 運(yùn)行在集群中的所有節(jié)點(diǎn)上。所有集群相關(guān)的特性都可以通過API形式來管理Couchbase, 但是有現(xiàn)成的管理控制臺(tái)。Couchbase 有一個(gè)安全控制臺(tái)來管理和監(jiān)控集群; 可以選擇可用的操作包括服務(wù)器搭建,創(chuàng)建buckets, 瀏覽和更新文檔, 實(shí)現(xiàn)新的視圖,以及監(jiān)控 vBucket 和硬盤寫隊(duì)列.
Figure 2-6 展示了Couchbase 控制臺(tái)主頁,有現(xiàn)存buckets所使用的內(nèi)存, 數(shù)據(jù)使用的硬盤, 以及buckets的活動(dòng).
Figure 2-6. Couchbase console home
在 Server Nodes 中執(zhí)行集群管理,讓用戶配置故障切換和復(fù)制以防止數(shù)據(jù)丟失。 Figure 2-7 展示了單節(jié)點(diǎn)安裝故障切換的不安全型。
Figure 2-7. Couchbase server nodes
任何時(shí)候,都可以通過點(diǎn)擊Add Server 按鈕來增加一個(gè)新的Couchbase 服務(wù)器,這一操作的時(shí)候,數(shù)據(jù)就開始在節(jié)點(diǎn)間復(fù)制來保證故障切換。通過點(diǎn)擊
服務(wù)器IP, 可用訪問一個(gè)bucket的監(jiān)控?cái)?shù)據(jù), 如 Figure 2-8.
Figure 2-8. Couchbase bucket monitoring
該圖展示了一個(gè)叫做DevUser的數(shù)據(jù) bucket,包含了用戶相關(guān)的JSON文檔.如前所述 ,新文檔索引的處理是復(fù)雜的底層處理的一部分。當(dāng)處理高索引吞吐量的海量數(shù)據(jù)時(shí),可用從監(jiān)控控制臺(tái)看到基本的測量信息。例如,當(dāng)寫操作時(shí)統(tǒng)計(jì)磁盤寫隊(duì)列的瓶頸。
Figure 2-9 中, 可用看的drain rate—從磁盤寫隊(duì)列中寫入磁盤的數(shù)據(jù)數(shù)量——在寫入副本時(shí)活躍節(jié)點(diǎn)時(shí)平滑的,而且在平滑區(qū)間內(nèi)增長相對(duì)平均。一個(gè)改變的行為將是看到活動(dòng)項(xiàng)目的平均年齡保持增長,這意味著,寫操作是與數(shù)據(jù)推入寫磁盤隊(duì)列的數(shù)量相比太慢了。
Figure 2-9. Couchbase bucket disk queue
管理文檔
通過bucket視圖,可以從管理控制臺(tái)管理所有的文檔. 這一視圖允許用戶瀏覽buckets, 設(shè)計(jì)文檔以及視圖.文檔存儲(chǔ)在Couchbase的一個(gè)bucket中,可以通過管理控制臺(tái)的 Data Bucket 欄目訪問,如Figure 2-10 所示.
Figure 2-10. Couchbase console bucket view
從服務(wù)器來看 , 控制臺(tái)給出了bucket的統(tǒng)計(jì)數(shù)據(jù)如 RAM 和存儲(chǔ)大小以及每秒操作的數(shù)量。但真正的好處是這個(gè)視圖可以瀏覽文檔并通過ID來提取它們,如 Figure 2-11 所示.
Figure 2-11. Couchbase document by ID
同時(shí),可以通過這一視圖創(chuàng)建設(shè)計(jì)文檔和索引文檔的視圖如Figure 2-12 所示.
Figure 2-12. Couchbase console view implementation
在Figure 2-12 中, 實(shí)現(xiàn)了一個(gè)視圖,它基于公司名稱提取文檔。管理控制臺(tái)可用非常方便的管理文檔,但在真實(shí)世界中,需要在管理控制臺(tái)開始實(shí)現(xiàn)一個(gè)設(shè)計(jì)文檔,并且創(chuàng)建一個(gè)工業(yè)化部署的備份。所有的設(shè)計(jì)文檔都存儲(chǔ)在一個(gè)JSON 文件中,有著一個(gè)簡單的結(jié)構(gòu)來描繪上所有的視圖,如表 2-1 所示.
Listing 2-1. Designing a Document JSON Example
[{
...
"doc": {
"json": {
"views": {
"by_Id": {"map": "function (doc, meta)
{\n emit(doc.id, doc);\n}"},
"by_email": {"map": "function (doc, meta)
{\n emit(doc.email, doc);\n}"},
"by_name": {"map": "function (doc, meta)
{\n emit(doc.firstname, null);\n}"},
"by_company": {"map": "function (doc, meta)
{\n emit(doc.company, null);\n}"},
"by_form": {"map": "function (doc, meta)
{\n emit(meta.id, null);\n}"}
}
}
...
}
}]
已經(jīng)看到,可以通過管理控制臺(tái)執(zhí)行文檔的管理,但是在商用架構(gòu)中,大量這樣的操作是通過使用Couchbase API 的腳本完成的。
介紹ElasticSearch
已經(jīng)了解了Couchbase這樣的一個(gè)NoSQL; ElasticSearch 也是一個(gè)NoSQL技術(shù),但與 Couchbase完全不同. 這是由Elastic公司命名的分布式數(shù)據(jù)庫。
架構(gòu)
它是一個(gè)建立于Apache Lucene(一個(gè)Java寫的全文搜素引擎)之上的索引/搜索引擎。從一開始, ElasticSearch 就是分布式可伸縮的,可以通過增加節(jié)點(diǎn)資源來垂直擴(kuò)展,也可以通過增加節(jié)點(diǎn)來水平擴(kuò)展增加高可用性同時(shí)保持彈性。如果一個(gè)節(jié)點(diǎn)掛了,由于在集群間的復(fù)制,由其它節(jié)點(diǎn)提供服務(wù)。
ElasticSearch 是一個(gè)無縫引擎;數(shù)據(jù)以JSON存儲(chǔ),分區(qū)叫做shards. 一個(gè) shard 實(shí)際上是一個(gè)Lucene的索引,是 ElasticSearch中最小的可擴(kuò)展單元. Shards 組織成ElasticSearch中的索引,使應(yīng)用完成讀寫交互。最后, 索引是一個(gè)ElasticSearch中邏輯上的命名空間,是shards 集合的一個(gè)重新分組,當(dāng)請(qǐng)求到達(dá)時(shí), ElasticSearch 將它路由到合適的shard上,如 Figure 2-13 所示.
Figure 2-13. Elasticsearch index and shards
ElasticSearch中有兩種shard類型:基本 shards 和復(fù)制shards. 當(dāng)啟動(dòng)一ElasticSearch 節(jié)點(diǎn), 開始只增加一個(gè)基本shard, 這就足夠了,當(dāng)時(shí)當(dāng)讀/檢索請(qǐng)求的吞吐量迅猛增加的時(shí)候會(huì)怎樣呢?這種情況下, 一個(gè)基本 shard 可能不夠用了,就需要另一個(gè)shard. 不能實(shí)時(shí)增加shard來期望ElasticSearch 來擴(kuò)展; 這將在兩個(gè)新的基本shard中重新索引所有的數(shù)據(jù)。所以,在啟動(dòng)一個(gè) ElasticSearch項(xiàng)目的開始, 適當(dāng)評(píng)估集群中有多少個(gè)基本shard 非常重要。在一個(gè)節(jié)點(diǎn)增加多個(gè) shards 不能增加集群的容量,因?yàn)橛兄布默F(xiàn)在。為了增加集群容量,也需要增加更多的節(jié)點(diǎn)來承載基本 shards,見Figure 2-14.
Figure 2-14. ElasticSearch primary shard allocation
一個(gè)好事情時(shí)ElasticSearch在新節(jié)點(diǎn)上可以通過網(wǎng)絡(luò)自動(dòng)拷貝shard,如 Figure 2-14.但是如何確保數(shù)據(jù)不丟失呢?這就是replica shards的角色。
Replica shards 開始源于故障切換;當(dāng)primary shard 掛了, 一個(gè)副本被提升為primary來保證集群的連續(xù)性。Replica shards 在primary shards 做索引的時(shí)候擁有同樣的負(fù)載; 一旦一個(gè)文檔在 primary shard中建立了索引, 同樣也在replica shards中做了索引. 這就是為什么在集群中增加副本卻不會(huì)增加索引的性能,但是如果增加了額外的硬件,就會(huì)提升搜索的性能。在一個(gè)三節(jié)點(diǎn)集群中,有一個(gè)primary shards 和兩個(gè)副本 Figure 2-15 展示了如何重新分區(qū).
Figure 2-15. ElasticSearch primary and replica shards
另外, 通過在集群中幫助請(qǐng)求的負(fù)載均衡,從而得到更好的性能。最后要討論的是純 ElasticSearch 架構(gòu)的indices以及多節(jié)點(diǎn). Indices 被重新分組到 ElasticSearch 的節(jié)點(diǎn),Figure 2-16 展示了3種類型的節(jié)點(diǎn)。
Figure 2-16. ElasticSearch cluster topology
這是三種節(jié)點(diǎn)的描述:
Master nodes: 這些節(jié)點(diǎn)是輕量級(jí)的,負(fù)責(zé)集群管理。它們不承載任何數(shù)據(jù), server indices,或搜素請(qǐng)求. 它們專門來保證集群的穩(wěn)定性,負(fù)載較低。推薦使用三個(gè)master nodes通過冗余保證故障切換。
Data nodes: 這些節(jié)點(diǎn)持有數(shù)據(jù),索引和搜索請(qǐng)求。
Client nodes: 這保證部分處理步驟的負(fù)載均衡,且部分工作負(fù)載在數(shù)據(jù)節(jié)點(diǎn)執(zhí)行,例如搜索請(qǐng)求發(fā)散在不同節(jié)點(diǎn)上。
理解了ElasticSearch架構(gòu), 就可以使用API運(yùn)行一些查詢了。
ElasticSearch 監(jiān)控
Elastic 提供了一個(gè)叫 Marvel 的插件,目標(biāo)是監(jiān)控 ElasticSearch 集群. 這個(gè)插件是個(gè)商用產(chǎn)品,但你可以在開發(fā)模式免費(fèi)使用它。
下載和安裝都非常簡單:https://www.elastic.co/downloads/marvel
Marvel 是依賴 Kibana的, Elastic的可視化控制臺(tái),帶來大量的可視化技術(shù),使操作者準(zhǔn)確地知道在集群上發(fā)生了什么。 Figure 2-17展示了 Marvel的控制面板.
Figure 2-17. ElasticSearch Marvel console
Marvel 提供了節(jié)點(diǎn)indices和shards的信息; CPU 利用率;JVM所使用的內(nèi)存;索引的速度,以及搜索的速度. Marvel 甚至可以進(jìn)入到 Lucene的底層查看
flushes 和 merges的信息.例如集群中shard的分布列表 見 Figure 2-18.
Figure 2-18. Marvel’s shard allocation view
Marvel 可以提供大量有關(guān)集群的信息。Figure 2-19展示了節(jié)點(diǎn)統(tǒng)計(jì)的子集.
Figure 2-19. Marvel Node Statistics dashboard
dashboard 被組織成幾行; 實(shí)際上,在截屏中是看不到多于20行的內(nèi)容的.每行包含一個(gè)或行標(biāo)題的可視化。 在 Figure 2-19中,沒看到發(fā)送到
indices的GET 請(qǐng)求; 這就是為什么線圖是平的. 在開發(fā)模式中,這些統(tǒng)計(jì)可以幫助判定服務(wù)器是否伸縮,例如,啟動(dòng)一個(gè)單節(jié)點(diǎn)集群,查看特殊需求的行為。在生產(chǎn)環(huán)境,能夠真實(shí)地看到集群的信息,而不損失什么。
通過 ElasticSearch搜索
Marvel又一個(gè)叫 Sense的特性,是ElasticSearch的一個(gè)查詢編輯器. Sense 的強(qiáng)大是又一個(gè)自動(dòng)補(bǔ)全查詢的能力,當(dāng)不熟悉
ElasticSearch API時(shí)非常有用, 見Figure 2-20.
Figure 2-20. Marvel Sense completion feature
也可以將查詢導(dǎo)出到cURLs, 例如, 使用的腳本參見Figure 2-21.
Figure 2-21. Marvel Sense copy as cURL feature
在這種情況下,查詢被視為cURL 命令,見 Listing 2-3.
Listing 2-3. Example of cURL Command Generated by Sense
curl -XGET "http://192.168.59.103:9200/yahoo/_search" -d'
{
"query": {
"match_all": {}
}
}'
這一查詢基本上搜索了Yahoo索引下的全部文檔. 未來展示 search API的優(yōu)勢, 使用來自 Yahoo的數(shù)據(jù)集,它包含了若干年Yahoo股票的信息。一個(gè) ElasticSearch’s search API中關(guān)鍵的特性是,這是一個(gè)聚合框架??梢杂貌煌姆椒ň酆蠑?shù)據(jù); 更通用的方式是事業(yè)日期直方圖,相當(dāng)于時(shí)間線。Figure 2-22 解釋了一個(gè)查詢的例子; 通過日期聚合股票數(shù)據(jù),間隔可以是月,也可以計(jì)算給定月份的股價(jià)最大值。
Figure 2-22. Marvel Sense Aggregation example
作為結(jié)果, 我們得到一個(gè)文檔的數(shù)組,每個(gè)條目包含了日期,每月的文檔數(shù)量,最高值,見Listing 2-4.
Listing 2-4. Aggregation Bucket
{
"key_as_string": "2015-01-01T00:00:00.000Z",
"key": 1420070400000,
"doc_count": 20,
"by_high_value": {
"value": 120
}
}
可以看到如 Figure 2-22的查詢, 有兩個(gè)層次的聚合: 一個(gè)是日期直方圖,第二個(gè)是最大值。實(shí)際上 , ElasticSearch 支持多層次聚合。
搜素API 非常豐富,不可能逐個(gè)瀏覽,詳情參見:
https://www.elastic.co/guide/en/elasticsearch/reference/1.4/search-search.html
現(xiàn)在熟悉了兩種 NoSQL技術(shù) , 看一下把它們集成到一個(gè)電子商務(wù)應(yīng)用的不同方法。
在基于SQL的架構(gòu)中 使用 NoSQL 緩存
盡管理解了NoSQL技術(shù)相對(duì)于 SQL 數(shù)據(jù)庫的優(yōu)勢,但不想打破依賴于SQL數(shù)據(jù)庫的現(xiàn)有架構(gòu)。下面的方法可以完善我們的架構(gòu),基于NoSQL技術(shù)增加訪問數(shù)據(jù)的靈活性。
文檔緩存
第一個(gè)要討論的是如何復(fù)制數(shù)據(jù)到我們NoSQL的后端。希望每次數(shù)據(jù)寫到SQL數(shù)據(jù)庫中的時(shí)候,一個(gè)文檔同時(shí)在我們的NoSQL創(chuàng)建或更新。文檔的創(chuàng)建、更新字段,或者豐富子文檔對(duì)應(yīng)于 RDBMS的表關(guān)系. 在訪問文檔的時(shí)候,只要API的GET 請(qǐng)求產(chǎn)生了,都先看NoSQL后端,如果有則返回此文檔。
如果文檔沒找到怎么辦?緩存沒有命中的事件將被觸發(fā),NoSQL manager 從 RDBMS中重建此文檔. 那在SQL層插入的transaction失敗了怎么辦? 框架應(yīng)該是交易型的,只有當(dāng)SQL 的交易完成時(shí)才觸發(fā)文檔的重建。Figure 2-23 總結(jié)了這一機(jī)制.
Figure 2-23. Caching a document in NoSQL
Figure 2-23 描述的內(nèi)容:
第一框圖展示了一個(gè)賬戶如何在 RDBMS 中創(chuàng)建的,以及如何在NoSQL中創(chuàng)建一個(gè)完整賬戶的文檔表達(dá)
第二框圖展示了API如何從NoSQL存儲(chǔ)中獲得一個(gè)賬戶信息.
第三個(gè)框圖展示了一個(gè)緩存丟失的例子,當(dāng)文檔不在NoSQL中的時(shí)候必須從RDBMS中重建
實(shí)際上,基于NoSQL為web應(yīng)用建立了一個(gè)緩存。這種方法依賴于NoSQL訪問整個(gè)文檔的靈活性而不增加SQL數(shù)據(jù)庫的負(fù)擔(dān),也充分利用了NoSQL的分布式靈活性。 通過這種方法,隨著請(qǐng)求速度的大量增長可以擴(kuò)展集群,減少SQL數(shù)據(jù)庫的壓力。
ElasticSearch的 Couchbase 插件
為了獲得這樣一個(gè)緩存機(jī)制,需要選擇NoSQL技術(shù)。第一個(gè)方法獨(dú)立使用
Couchbase, 但是 Couchbase的搜索特性不太好使。用map/reduce 函數(shù)索引數(shù)據(jù)較煩瑣,尤其是只做簡單聚合的時(shí)候。 Couch base 是個(gè)很棒的 NoSQL 數(shù)據(jù)庫, 但實(shí)現(xiàn)搜索確實(shí)痛苦。作為替代方法,可以使用Couchbase/ElasticSearch 集成插件, 基本上使用Cross Data Center Replication (XDCR) 傳輸所有數(shù)據(jù)到 ElasticSearch 集群(www.couchbase.com/jp/couchbase-server/connectors/elasticsearch).
就操作任務(wù)而言,要維護(hù)三種不同的技術(shù):RDBMS, Couchbase, 和 ElasticSearch.
最有效的ElasticSearch
保持使用 Couchbase 原因:
索引全部對(duì)象的能力, 例如將SQL中的賬戶信息簽到NoSQL
通過靈活的搜索API適應(yīng)從簡單到復(fù)雜聚合查詢的能力
從選擇 Couchbase 開始,作為最佳實(shí)踐,文檔存儲(chǔ)在數(shù)據(jù)庫中。當(dāng)體驗(yàn)架構(gòu)的時(shí)候,要知道什么是訪問和請(qǐng)求數(shù)據(jù)的最有效方法。在我們使用場景中, ElasticSearch 就是最有效的方法。