「Cassandra實戰」Cassandra及其數據模型

<code>Cassandra是一個分佈式、高可擴展的數據庫,用戶可以創建線上應用程序,實時處理大量數據。

  Apache Spark是應用於Hadoop集群的處理引擎,在內存條件下可以為Hadoop加速100倍,在磁盤上運行時也能實現十倍的加速。Spark還提供SQL、流數據處理、機器學習和圖型計算等功能。
  Cassandra與Spark的結合,讓端到端的分析工作流的實現更為容易。另外,交易型數據庫的分析性能也能得到很大的提升,企業可以更快地響應客戶需求。
  對於需要向客戶提供實時推薦和個性化的在線體驗的公司,Cassandra與Spark的結合堪稱福音。/<code> 
<code>Hadoop擴展性有餘,實時性不足。Storm這樣的實時流處理框架,但它只有處理固定的流程時才具有優勢,彈性查詢能力欠佳。
 現在Ooyala正在運行的就是Spark/Cassandra架構/<code>


「Cassandra實戰」Cassandra及其數據模型




1. Cassandra

NoSQL數據庫的選擇之痛,目前市面上有近150多種NoSQL數據庫,如何在這麼龐雜的隊伍中選中適合業務場景的佼佼者,實非易事。

好的是經過大量的篩選,大家比較肯定的幾款NoSQL數據庫分別是HBase、MongoDB和Cassandra。

Cassandra在哪些方面吸引住了大量的開發人員呢?下面僅做一個粗略的分析。

1.1 高可靠性

Cassandra採用gossip作為集群中結點的通信協議,該協議整個集群中的節點都處於同等地位,沒有主從之分,這就使得任一節點的退出都不會導致整個集群失效。

Cassandra和HBase都是借鑑了Google BigTable的思想來構建自己的系統,但Cassandra另一重要的創新就是將原本存在於文件共享架構的p2p(peer to peer)引入了NoSQL。

P2P的一大特點就是去中心化,集群中的所有節點享有同等地位,這極大避免了單個節點退出而使整個集群不能工作的可能。

與之形成對比的是HBase採用了Master/Slave的方式,這就存在單點失效的可能。

1.2 高可擴性

隨著時間的推移,集群中原有的規模不足以存儲新增加的數據,此時進行系統擴容。Cassandra級聯可擴,非常容易實現添加新的節點到已有集群,操作簡單。

1.3 最終一致性

分佈式存儲系統都要面臨CAP定律問題,任何一個分佈式存儲系統不可能同時滿足一致性(consistency),可用性(availability)和分區容錯性(partition tolerance)。

Cassandra是優先保證AP,即可用性和分區容錯性。

Cassandra為寫操作和讀操作提供了不同級別的一致性選擇,用戶可以根據具體的應用場景來選擇不同的一致性級別。

1.4 高效寫操作

寫入操作非常高效,這對於實時數據非常大的應用場景,Cassandra的這一特性無疑極具優勢。

數據讀取方面則要視情況而定:


  • 如果是單個讀取即指定了鍵值,會很快的返回查詢結果。
  • 如果是範圍查詢,由於查詢的目標可能存儲在多個節點上,這就需要對多個節點進行查詢,所以返回速度會很慢
  • 讀取全表數據,非常低效。


1.5 結構化存儲

Cassandra是一個面向列的數據庫,對那些從RDBMS方面轉過來的開發人員來說,其學習曲線相對平緩。

Cassandra同時提供了較為友好CQL語言,與SQL語句相似度很高。

1.6 維護簡單

從系統維護的角度來說,由於Cassandra的對等系統架構,使其維護操作簡單易行。如添加節點,刪除節點,甚至於添加新的數據中心,操作步驟都非常的簡單明瞭。

參考資料


  • 1.http://cassandra.apache.org
  • 2.http://www.datastax.com/doc
  • 3.http://planetcassandra.org/documentation/


2. Cassandra數據模型

2.1 單表查詢

2.1.1 單表主鍵查詢

在建立個人信息數據庫的時候,以個人身份證id為主鍵,查詢的時候也只以身份證為關鍵字進行查詢,則表可以設計成為:


<code>create table person (
	userid text primary key,
	fname text,
	lname text,
	age	int,
	gender int);/<code>

Primary key中的第一個列名是作為Partition key。也就是說根據針對partition key的hash結果決定將記錄存儲在哪一個partition中,如果不湊巧的情況下單一主鍵導致所有的hash結果全部落在同一分區,則會導致該分區數據被撐滿。

解決這一問題的辦法是通過組合分區鍵(compsoite key)來使得數據儘可能的均勻分佈到各個節點上。

舉例來說,可能將(userid,fname)設置為複合主鍵。那麼相應的表創建語句可以寫成


<code>create table person (
userid text,
fname text,
lname text,
gender int,
age int,
primary key((userid,fname),lname);
) with clustering order by (lname desc);/<code>


稍微解釋一下primary key((userid, fname),lname)的含義:


  • 其中(userid,fname)稱為組合分區鍵(composite partition key)
  • lname是聚集列(clustering column)
  • ((userid,fname),lname)一起稱為複合主鍵(composite primary key)


2.1.2 單表非主鍵查詢

如果要查詢表person中具有相同的first name的人員,那麼就必須針對fname創建相應的索引,否則查詢速度會非常緩慢。

Create index on person(fname);

Cassandra目前只能對錶中的某一列建立索引,不允許對多列建立聯合索引。

2.2 多表關聯查詢

Cassandra並不支持關聯查詢,也不支持分組和聚合操作。

那是不是就說明Cassandra只是看上去很美其實根本無法解決實際問題呢?答案顯然是No,只要你不堅持用RDBMS的思路來解決問題就是了。

比如我們有兩張表,一張表(Departmentt)記錄了公司部門信息,另一張表(employee)記錄了公司員工信息。顯然每一個員工必定有歸屬的部門,如果想知道每一個部門擁有的所有員工。如果是用RDBMS的話,SQL語句可以寫成:


<code>select * from employee e , department d where e.depId = d.depId;/<code>

要用Cassandra來達到同樣的效果,就必須在employee表和department表之外,再創建一張額外的表(dept_empl)來記錄每一個部門擁有的員工信息。


<code>Create table dept_empl (
deptId text,/<code>

看到這裡想必你已經明白了,在Cassandra中通過數據冗餘來實現高效的查詢效果。將關聯查詢轉換為單一的表操作。

2.3 分組和聚合

在RDBMS中常見的group by和max、min在Cassandra中是不存在的。

如果想將所有人員信息按照姓進行分組操作的話,那該如何創建數據模型呢?


<code>Create table fname_person (
fname text,
userId text,
primary key(fname)
);/<code>

2.4 子查詢


Cassandra不支持子查詢,下圖展示了一個在MySQL中的子查詢例子:

要用Cassandra來實現,必須通過添加額外的表來存儲冗餘信息。


<code>Create table office_empl (
officeCode text,
country text,
lastname text,
firstname,
primary key(officeCode,country));
create index on office_empl(country);/<code>


2.5 小結

總的來說,在建立Cassandra數據模型的時候,要求對數據的讀取需求進可能的清晰,然後利用反範式的設計方式來實現快速的讀取,原則就是以空間來換取時間。


分享到:


相關文章: