如何讓NoSQL記憶體資料庫適合企業級應用

chszs發表於2013-10-04

如何讓NoSQL記憶體資料庫適合企業級應用

作者:chszs,轉載需註明。部落格主頁:http://blog.csdn.net/chszs

英文原文:How to Make Your In-memory NoSQL Datastores Enterprise-Ready

對於每一個關注使用者體驗的Web應用或移動應用而言,NoSQL記憶體資料庫(例如開源的 Redis和Memcached)正逐步成為事實上的標準。但是,近幾年來,大型企業在採用這些資料庫方面還面臨著諸多挑戰,主要是由於效能、可擴充套件性和可用性方面的問題。

非常幸運的是,現代程式語言(例如Ruby、Node.js、Python等)和開發平臺(例如Rails、Sinatra、Django等)已經內建了很多工具和開發庫。這些工具和開發庫能夠有效利用記憶體資料庫的高效能和各種操作命令,能夠實現當前流行的多種應用專案。

這些開源專案的案例包括作業管理、論壇、實時分析、Twitter克隆、地理位置搜尋以及高階快取等等。

但是,對於這些專案成功至關重要的是資料庫系統的可用性(Availability)、可擴充套件性(Scalability)和效能(Performance)。

本文粗略的介紹如何利用記憶體資料庫構建企業級應用,包括一些技巧和建議;這些技巧和建議能夠解決雲端NoSQL資料庫管理面臨的七大挑戰。

一、可用性(Availability)

無論你在做什麼,對於你的應用來說資料必須是時刻可用的。這對於記憶體資料庫來說尤為重要;因為,如果沒有適當的措施,當下面的情形發生時你的資料將會部分或全部丟失:
1) 節點失效(在雲中經常發生)
2) 程式重啟(你可能需要不時的進行重啟)
3) 按需要擴充套件(我們假設你可能需要這個)

對於情形1和情形2有兩種方式來解決;情形3將在稍後討論。

1、複製:你要確保將你的資料集儲存一份到叢集的另一節點,如果是另一資料中心則更為可靠,以便應付資料中心發生故障(亞馬遜AWS在2012年至少發生了4次故障)。不幸的是事情並非如此簡單。隨便就能舉一個複製非常困難的例子:

一旦程式的寫頻率增加,你會發現應用伺服器寫入速度遠大於複製的速度,尤其是在主節點和複製節點存在網路擁堵的情形下。一旦發生這種情況,如果資料集非常大,節點的複製同步很有可能永遠也完不成。

2、自動切換:為什麼需要這個?記憶體資料庫每秒處理的請求比一般資料庫通常多100倍,這就意味著每增加一秒當機時間就會延遲更多的請求處理並給使用者帶來不好的使用者體驗。在實現自動切換時一定要遵循下面的原則:

(1) 確保主儲存節點一旦失效就立刻切換到備用複製節點。這一般基於成熟健壯的看門狗技術 (Watch Dog),看門狗持續的監控節點,一旦發現失效就切換到健康的複製節點。
(2) 對於你的應用程式而言切換過程應儘可能透明;最理想的情況是無需更改任何配置。更高階的解決方案是僅僅修改DNS中儲存節點的IP地址,確保修復過程在幾秒鐘之內完成。
(3) 自動切換應當基於Quorum並且是完全一致(Fully Consistent)或最終一致(Eventually Consistent)的。討論下面繼續:

二、網路分割過程中和完成後的一致性

網路分割(Network Split)在雲中頻繁發生,對地球上的分散式儲存系統而言也是最複雜的問題。一旦發生分割,應用程式可能只會找到記憶體資料庫的部分節點;同時,每個NoSQL記憶體資料庫節點也可能只能找到其他部分NoSQL資料庫節點。

為什麼說這是一個非常嚴重的問題呢?如果你的資料庫包含一些隱蔽的設計缺陷,當網路分割發生時,應用程式很可能會把資料寫入錯誤的節點。這意味著,當網路分割的情況恢復時,應用程式之前的寫請求操作的資料就會丟失。這對NoSQL記憶體資料庫來說這是一個非常重要的話題,因為NoSQL記憶體資料庫每秒的寫運算元量遠大於其他NoSQL資料庫系統。 

一個設計得當的NoSQL記憶體資料庫是什麼樣子的呢?很不幸,你只能從下面兩個非常糟糕的候選中進行選擇:
(1) 如果NoSQL記憶體資料庫是完全一致的,在某些情況下你是不允許寫入任何內容的,除非網路分割恢復。
(2) 如果NoSQL記憶體資料庫是最終一致的,應用程式可以對“讀”請求採用quorum方法——返回一個值或者阻塞。 

注意:到目前為止,業界並不存在最終一致的NoSQL記憶體資料庫產品,所以只有選項1是可以實際應用的方案。

三、資料的耐久性(Durability)

儘管NoSQL記憶體資料庫解決方案提供了多種複製選擇,你還是需要著重考慮資料的持久化和備份,原因如下:

(1) 或許你不想為記憶體複製支付額外的費用,但是仍希望將資料集儲存在某個地方,以便在遇到節點故障時能夠將資料恢復(即使恢復速度很慢)。
(2) 你肯定希望在遇到任何故障時(比如節點故障、多節點故障、資料中心故障等)都能將資料恢復並且希望保留另外一個選擇——將資料儲存在另外一個安全的地方,即使資料不能與最新的修改同步。
(3) 還有其他一些採用資料持久化的理由,比如匯入產品資料集到階段環境,以便於測試。

現在你已經確信資料持久化是必要的,在大多數雲環境中你應當使用附屬在雲主機上的儲存裝置(像AWS的EBS、Azure的Cloud Derive等)。如果你將資料儲存在本地硬碟,當遇到節點故障時你就會丟失資料。

一旦資料得到持久化儲存,你最大的挑戰將變成:在更新資料持久化儲存的同時保證NoSQL記憶體資料庫的速度。 

四、穩定的效能

NoSQL記憶體資料庫(例如Redis或Memcached)的設計目標是:在毫秒延遲內,每秒鐘能夠處理超過10萬個請求。但是,這個數字在雲環境下是很難達到的,除非你遵循以下原則:

1、確保你的解決方案使用的是功能強大的雲主機(Cloud Instance),比如AWS的 m2.2xlarge/m2.4xlarge雲主機或者是Azure的A6/A7雲主機,而且還有一個專用環境。

另外,可以實現一種預防跨不同雲賬戶的“吵鬧的鄰居”現象的機制。此機制應該能監控你的資料集的效能,可實時監控、按命令監控、基於一定的規則去監控、或根據一套機制去監控,比如當發現延遲超過閾值就自動遷移資料集到另一個節點。

2、避免儲存的I/O瓶頸,確保解決方案使用了功能強大的儲存裝置,最好是配置了RAID。其次,要確保在“請求數突然暴增”的情況下也不會阻塞你的應用。例如,使用開源Redis方案,你可以配置slave節點執行持久化儲存操作;master節點專注於處理使用者請求,在“請求數突然暴增”的情況下避免超時現象。

3、測試雲廠商提供的各種關於儲存I/O優化的建議,例如AWS的PIOPS。大多數情況下,這些建議對隨機訪問(讀或寫)來說很有用;但是,對於NoSQL記憶體資料庫經常採用的像順序寫之類的情況來說就沒什麼優化價值。
AWS的PIOPS

4、 如果記憶體資料庫基於單執行緒架構(例如Redis),要確保不要在同一個執行緒中執行多個資料庫。不然,某個資料庫在執行命令的過程中很有可能會阻塞另外一個資料庫。 
 

五、網速

大多數雲主機都配置了一塊千兆(1Gbps)網路卡。在NoSQL記憶體資料庫上下文中,此千兆網路卡需要處理:

1、應用程式的請求
2、叢集內部的通訊
3、複製
4、儲存訪問

這很容易造成執行瓶頸。因此,下面提供一些建議可解決此問題:

(1) 為每一臺雲主機配置萬兆網路卡(10Gbps,但是要有心理準備,它非常昂貴)
(2) 選擇能夠為一些特殊應用在VPC內部配置多塊千兆網路卡的雲服務商,例如AWS
(3) 採用能夠在NoSQL記憶體資料庫節點之間高效分配資源的解決方案以便讓網路阻塞最小 

六、可擴充套件性(Scalability)

對於簡單的鍵值(Key / Value)快取解決方案(例如Memcached或者Redis的簡單應用),其擴充套件不會被認為是嚴重問題;因為在大多數情況下,它只需在伺服器列表中增加或刪除節點並修改雜湊函式。但是,對於實際遭遇過此問題的人就會意識到它仍然是一個令人痛苦的問題。

對於此問題我們有一些建議:

1、採用一致性雜湊(Hashing)。
用簡單的雜湊函式(例如求模)做擴充套件時,意味著遇到擴充套件事件會丟失所有的鍵資料。另一方面,很多人不知道的是:即使採用一致性雜湊函式,在擴充套件的時候你仍然會丟失部分資料。例如,在擴充套件的時候你會丟失1/N的鍵資料,N是你擴充套件後的節點數目。所以,如果N比較小,它就是一個很痛苦的過程(比如對2個節點的叢集採用一致性雜湊函式進行擴充套件,就意味著會丟失1/3的資料)。

2、建立一種機制,用擴充套件事件同步所有的NoSQL記憶體資料庫的客戶端,以預防這樣的事件發生——在擴充套件過程中不同的應用伺服器寫入到不同的節點。
當進行某些複雜操作時,例如Redis的UNION和INTERSECT操作,擴充套件就會成為非常實際的問題。這些命令等同於SQL中的JOIN命令,在多執行緒架構下,如果不增加一定的延遲和複雜性,這些操作就不能實現。應用程式級的分片(Sharding)能夠解決一定的問題,因為它允許在分片級執行一些複雜命令。但是,這需要很複雜的設計,並且與NoSQL記憶體資料庫的配置有一定的關聯。比如,分片的應用必須注意節點上儲存的每一個主鍵;擴充套件事件(如重分片)需要修改大量程式碼和額外的執行開銷。

另外,一些人聲稱,新一代的超高速RAM,比如亞馬遜AWS的HIgh Memory Cluster Eight Extra Large 244GB記憶體(cr1.8xlarge),能夠解決節點擴充套件中遇到的大多數問題。
但現實是有所不同的,對於25GB-30GB資料集規模,對於像Redis之類的記憶體資料庫,還有一些其他的操作問題會阻止擴充套件的執行。這些問題與本文前面提到的挑戰密切相關,像複製、儲存I/O、單核的單執行緒架構限制、網路頻寬開銷等。

七、巨大的運維開銷

NoSQL記憶體資料庫在處理所有的操作方面會產生巨大的額外開銷。你需要對這些技術進行深入瞭解,以便在緊要關頭能做出正確的決策。同時,因為這些技術更新頻率很快(可能是非常快),你還要時刻關注這些系統的趨勢和最新變化。

八、結論

正如我們上面所說的一樣,為了更好的利用Redis、Memcached等開源技術帶給我們的優勢,我們需要對這些技術進行深入瞭解和掌握。對於企業IT團隊來說,為了能夠在企業環境中使用NoSQL記憶體資料庫,瞭解如何更好的應對這些挑戰就顯得尤為重要。不是我持有偏見,我強烈建議尋找一些能夠攻克可擴充套件性和高可用性限制而不損害功能和效能的商業解決方案;因為執行這些內部操作需要該領域的高階專家,而這是非常稀少的。

在市場上有一些關於Redis和Memcached的NoSQL服務(NoSQL-as-a-service);我建議你對每一個可用的服務進行深入的比對(就像DIY),以便挑選一個最佳的解決方案。能夠實際體驗一下這些服務就更好了,很多服務商為這個目的都提供了免費體驗。 


相關文章