小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Cassandra數(shù)據(jù)模型設(shè)計(jì)最佳實(shí)踐(下部)

 文檔集成 2016-01-27

通過(guò)column name存儲(chǔ)數(shù)據(jù)是一項(xiàng)常用的實(shí)踐,同樣如果沒(méi)有必要保存column value,你也可以讓它為空。這樣做的動(dòng)機(jī)是column name是物理有序存儲(chǔ)的的,而column value不是。(譯者注:比如某個(gè)column name為字符串類(lèi)型,那么插入005、001、003、007最終的存儲(chǔ)順序?qū)⑹?01、003、005、007,這將意味著可以根據(jù)column name順序讀取數(shù)據(jù))。

注意:

column name(以及row key)最大為64KB,所以請(qǐng)不要存儲(chǔ)如“物品描述”之類(lèi)的信息。

不要單獨(dú)使用timestamp作為column name,那樣會(huì)導(dǎo)致2個(gè)或者多個(gè)應(yīng)用服務(wù)器同時(shí)寫(xiě)入Cassandra時(shí)造成數(shù)據(jù)覆蓋(譯者注:相同row key,相同column name會(huì)覆蓋column value),推薦使用uuid(type-1 uuid)代替(譯者注:time-based UUID主要由cassandra客戶端時(shí)間戳、序列號(hào)、MAC地址組成,這樣的組合可以大大降低數(shù)據(jù)沖突)。

column value最大為2GB,它的采用非流式數(shù)據(jù)讀取,cassandra會(huì)將整個(gè)value加載到heap內(nèi)存中,這是很危險(xiǎn)的,所以請(qǐng)確保column value只存儲(chǔ)不超過(guò)幾MB的數(shù)據(jù)。(使用column value進(jìn)行大數(shù)據(jù)存儲(chǔ)一段時(shí)間內(nèi)都不會(huì)被支持,參見(jiàn) Cassandra-265,但是通過(guò)Cassandra java 客戶端——Astyanax,可以通過(guò)分塊的方式解決這個(gè)問(wèn)題)。

使用寬行(wide row)進(jìn)行排序、分組和過(guò)濾

但不要搞的太長(zhǎng)

這個(gè)實(shí)踐與上面的內(nèi)容相關(guān),當(dāng)實(shí)際數(shù)據(jù)通過(guò)column name存儲(chǔ),我們會(huì)考慮使用寬行。

寬行的好處:

  • 因?yàn)閏olumn name是物理有序存儲(chǔ)的,所以寬行對(duì)于排序和高效過(guò)濾(范圍查找)有優(yōu)勢(shì),而且如果需要,你仍然可以高效查找寬行中單獨(dú)的column。
  • 如果一次要查詢多個(gè)數(shù)據(jù),你可以將數(shù)據(jù)分組然后保存到一個(gè)寬行中,如此可以快速讀取數(shù)據(jù)。舉個(gè)例子,跟蹤和監(jiān)控一些時(shí)間序列數(shù)據(jù),我們可以通過(guò)“小時(shí)/日期/機(jī)器/事件”將數(shù)據(jù)分組到一個(gè)wide row,每個(gè)column包含刻度數(shù)據(jù)或者累加數(shù)據(jù)。我們也可以使用Super Column或者Composite Column進(jìn)一步分組數(shù)據(jù)到一個(gè)row中,這個(gè)我們后面會(huì)討論。
  • 在Cassandra中,寬行column family常常與composite column一起配合用于構(gòu)建自定義索引。
  • 這里還有個(gè)額外的好處,如果你希望數(shù)據(jù)被一同查出或者優(yōu)化讀性能,你可以通過(guò)反范式化(de-normalize)one-to-many關(guān)系模型來(lái)實(shí)現(xiàn)這個(gè)功能。(譯者注:還記得第一篇文章中的示例嗎?一個(gè)User喜愛(ài)多個(gè)Item,一個(gè)User就是一個(gè)row key,column為多個(gè)Item)

示例:

假設(shè)我們系統(tǒng)存儲(chǔ)一些事件日志數(shù)據(jù),然后按照小時(shí)獲取它們。請(qǐng)看下面的模型,row key是日期和小時(shí),column name存儲(chǔ)事件發(fā)生的時(shí)間,column value保存負(fù)荷值(payload)。請(qǐng)注意,這是一個(gè)寬行,事件通過(guò)時(shí)間順序進(jìn)行存儲(chǔ)。寬行的間隔刻度(當(dāng)前示例中,小時(shí)刻度比分鐘更適合)由實(shí)際用例、流量和數(shù)據(jù)大小決定,我們馬上會(huì)討論到它們。

即使是寬行也不要太寬,因?yàn)橐粋€(gè)row的數(shù)據(jù)不會(huì)跨節(jié)點(diǎn)保存

很難準(zhǔn)確的說(shuō)一個(gè)寬行多少個(gè)column才合適,這依賴于你的用例,下面是一些建議:

流量:所有流量相關(guān)數(shù)據(jù)保存到一個(gè)row中將導(dǎo)致只有一個(gè)節(jié)點(diǎn)能夠提供服務(wù)(假設(shè)只有一個(gè)數(shù)據(jù)副本)。那樣的row太龐大,當(dāng)row的數(shù)量小于集群節(jié)點(diǎn)數(shù)(希望這不會(huì)發(fā)生),或者寬行與窄行(skinny row)混合使用,再或者一些行訪問(wèn)更頻繁,都可能出現(xiàn)集群熱點(diǎn)問(wèn)題。但是,集群負(fù)載均衡最終依靠rowkey選擇;相反地,rowkey也決定row的長(zhǎng)度。所以在設(shè)計(jì)模型的時(shí)候要謹(jǐn)記負(fù)載均衡。

大?。?/b>因?yàn)閞ow不會(huì)跨節(jié)點(diǎn)分割,所以單個(gè)row必須適應(yīng)節(jié)點(diǎn)磁盤(pán)大小。但是,row可以擁有大量column,因?yàn)樗粫?huì)加載到內(nèi)存。Cassandra允許每個(gè)row包含20億個(gè)column。在ebay,我們沒(méi)有做任何寬行測(cè)試,我們從不保存超過(guò)百萬(wàn)column或者M(jìn)B大小數(shù)據(jù)到單個(gè)row(我們改變r(jià)owkey刻度或者分割為多個(gè)row)。如果你有興趣,可以看看Aaron Morton關(guān)于寬行性能的文章—— 《Cassandra Query Plans》(譯者注:原文鏈接404)。

但是,這些建議不意味你不應(yīng)該使用寬行,只是不要搞的太長(zhǎng)就好。

譯者注:原文Cassandra-4176Cassandra-3929,這兩個(gè)bug的狀態(tài)為永不修復(fù),這里就不翻譯了。

選擇合適的rowkey

否則,你將死于熱點(diǎn),即使你使用 RandomPartitioner

讓我們?cè)俅慰紤]上面的示例,存儲(chǔ)時(shí)間序列日志,同時(shí)按小時(shí)獲取它們。我們使用日期小時(shí)作為rowkey以保證一小時(shí)數(shù)據(jù)在一個(gè)row里。但是,這里有個(gè)問(wèn)題,當(dāng)前時(shí)間的所有寫(xiě)入都集中到一個(gè)節(jié)點(diǎn)將導(dǎo)致熱點(diǎn)問(wèn)題。減少rowkey刻度從小時(shí)到分鐘并不能真正解決問(wèn)題,因?yàn)?分鐘內(nèi)的數(shù)據(jù)仍然只會(huì)寫(xiě)入一個(gè)節(jié)點(diǎn)。隨著時(shí)間推移,熱點(diǎn)會(huì)移到其他節(jié)點(diǎn)但不會(huì)消失!

糟糕的 row key: “ddmmyyhh”

一種減輕問(wèn)題的方式是添加一些信息到rowkey——事件類(lèi)型、機(jī)器ID,或者適應(yīng)你用例的類(lèi)似值。

不錯(cuò)的 row key: “ddmmyyhh|eventtype”

注意,在這個(gè)column family中,我們現(xiàn)在沒(méi)有對(duì)所有事件按全局時(shí)間進(jìn)行排序,如果我們是通過(guò)事件類(lèi)型來(lái)查詢數(shù)據(jù)的話,這將不是問(wèn)題,如果用例要求按照時(shí)間順序獲取所有事件,我們就需要使用multi-get方法一次查詢多個(gè)event rowkey,然后將數(shù)據(jù)在Cassandra客戶端程序中將數(shù)據(jù)按照時(shí)間順序合并即可。

如果你不能添加任何信息到rowkey或者的確需要時(shí)間周期作為rowkey,另一個(gè)選擇是將你的row key手工分割為:“ddmmyyhh | 1″, “ddmmyyhh | 2″,… “ddmmyyhh | n”, N值為集群的節(jié)點(diǎn)數(shù)。一小時(shí)內(nèi),可以用輪詢的方式寫(xiě)入各個(gè)節(jié)點(diǎn)。當(dāng)讀取數(shù)據(jù)的時(shí)候,你需要使用multi-gets方法獲取所有節(jié)點(diǎn)的數(shù)據(jù)并做合并。(假設(shè)這里使用RandomPartitioner,因此無(wú)法使用rowkey范圍查詢)

讓讀多數(shù)據(jù)與寫(xiě)多數(shù)據(jù)分離

這么做,你能夠充分利用Cassandra的off-heap行緩存特性。(譯者注:off--heap是一種脫離java gc的用法,通過(guò)api可以直接分配、釋放內(nèi)存)

無(wú)論NOSQL與否,保持讀寫(xiě)數(shù)據(jù)分離都是一個(gè)不錯(cuò)的實(shí)踐。

注意:行緩存對(duì)于窄行來(lái)說(shuō)很有用,但對(duì)寬行卻無(wú)益,因?yàn)樗鼤?huì)將整個(gè)行數(shù)據(jù)放到內(nèi)存中。通過(guò)Cassandra-1956 和 Cassandra-2864 未來(lái)可能改變這一現(xiàn)象,但是保持讀寫(xiě)分離這項(xiàng)實(shí)踐將仍然適用。

假如你的column family有大量數(shù)據(jù)(超過(guò)可用內(nèi)存),同時(shí)有熱行,開(kāi)啟行緩存可能對(duì)你有用。

確保column key和row key是唯一的

否則,數(shù)據(jù)可能被覆蓋

在Cassandra(一個(gè)分布式數(shù)據(jù)庫(kù))中,row key和 column key是沒(méi)有強(qiáng)制唯一性約束的。

同樣地,cassandra也沒(méi)有update操作。cassandra所有操作都是upsert(不存在插入,存在則更新)操作。如果你插入的數(shù)據(jù)之前已經(jīng)存在相同row key和column key,那么之前的column value將會(huì)被悄無(wú)聲息地覆蓋(cassandra column value是沒(méi)有版本的,之前的數(shù)據(jù)將無(wú)法找回)。

使用合適的 comparator 和validator

除非你真的需要,否則不要使用默認(rèn)的BytesType comparator 和 validator

在Cassandra中,column value(或者row key)的數(shù)據(jù)類(lèi)型稱為“Validator”。一個(gè)column name的數(shù)據(jù)類(lèi)型稱為“Comparator”。雖然Cassandra不要求你全部定義它們,但你必須至少指定comparator,除非你的column family是靜態(tài)的(就是說(shuō),你不會(huì)存儲(chǔ)實(shí)際的數(shù)據(jù)作為column name的一部分),或者你真的不關(guān)心column排序。

一個(gè)不合適的comparator 將不能按照你預(yù)期所想的順序?qū)olumn name排序并存放到磁盤(pán)上。它將很難(或者不能)根據(jù)column name進(jìn)行范圍查詢。

一旦完成定義,你將不能修改comparator,除非重寫(xiě)所有數(shù)據(jù)。但是validator 是可以事后變更的。

通過(guò)Cassandra文檔看看comparators 和 validators 支持的數(shù)據(jù)類(lèi)型。

保持column name簡(jiǎn)短

因?yàn)樗鼘?huì)在被重復(fù)存儲(chǔ)

如果你使用column name存儲(chǔ)數(shù)據(jù),那這個(gè)實(shí)踐是不適用的。除此之外,保持column name簡(jiǎn)短,因?yàn)樗鼘⒑兔總€(gè)column value一起被重復(fù)存儲(chǔ)(根據(jù)數(shù)據(jù)副本數(shù))。當(dāng)column value的大小比column name小很多時(shí),內(nèi)存和存儲(chǔ)的開(kāi)銷(xiāo)可能會(huì)是個(gè)問(wèn)題。

比如,‘fname’ 優(yōu)于 ‘firstname’,‘lname’ 優(yōu)于 ‘lastname’。

注意:Cassandra-4175可能會(huì)導(dǎo)致本實(shí)踐在未來(lái)失效。

將數(shù)據(jù)模型設(shè)計(jì)為支持冪等操作

或者確保你能夠接受用例數(shù)據(jù)不準(zhǔn)確或者最終準(zhǔn)確的情況

像Cassandra這樣具有最終一致性以及完全分布式的系統(tǒng),冪等操作非常有用。冪等操作允許系統(tǒng)因出現(xiàn)錯(cuò)誤而導(dǎo)致的重試是安全的,它不會(huì)影響數(shù)據(jù)的最終結(jié)果。此外,冪等有時(shí)可以降低對(duì)強(qiáng)一致性的需求,因?yàn)樗试S在不產(chǎn)生數(shù)據(jù)重復(fù)和其它異常的情況下實(shí)現(xiàn)最終一致性。讓我們看看這些原則如何應(yīng)用到Cassandra上。我將只討論部分失敗的情況,降低強(qiáng)一致性需求放到后續(xù)文章里講,因?yàn)樗浅R蕾囉美?/p>

因?yàn)镃assandra具有完全分布式(多個(gè)master)的特性,寫(xiě)失敗不能確保數(shù)據(jù)沒(méi)有被寫(xiě)入,這與關(guān)系型數(shù)據(jù)庫(kù)不同。換句話說(shuō),即使客戶端接收到一個(gè)寫(xiě)入操作失敗的響應(yīng),數(shù)據(jù)仍可能被寫(xiě)入其中一個(gè)副本,數(shù)據(jù)將最終被傳播到其它副本。沒(méi)有回滾或者清理動(dòng)作來(lái)處理已經(jīng)寫(xiě)入的數(shù)據(jù)。因此,雖然客戶端出現(xiàn)寫(xiě)失敗,但數(shù)據(jù)最終是成功寫(xiě)入的。所以如果你的模型不具有更新冪等性,錯(cuò)誤的重試將導(dǎo)致未知的結(jié)果。

注意:

  • 這里的“更新冪等性”意味著模型的操作是冪等的。如果一個(gè)操作被多次調(diào)用卻不影響最終結(jié)果,那它就具有冪等性。
  • 在大多數(shù)情況,冪等性不會(huì)受到關(guān)注,因?yàn)閷?shù)據(jù)寫(xiě)入正常的Colum Family總是更新冪等的,Counter column family是比較特殊的例子,后面我們會(huì)說(shuō)到。有時(shí)你的用例可以設(shè)計(jì)為非更新冪等的。比如我們第一部分文章中,最終方案的模型User_by_Item和Item_by_User就不具有更新冪等性,因?yàn)楫?dāng)“User喜愛(ài)某個(gè)Item”的操作被執(zhí)行多次將導(dǎo)致數(shù)據(jù)時(shí)間戳發(fā)生改變,從而無(wú)法獲知真實(shí)的User喜愛(ài)某個(gè)Item的時(shí)間。但是,“User喜愛(ài)某個(gè)Item”的操作仍然是冪等的,因?yàn)槲覀冊(cè)诔霈F(xiàn)錯(cuò)誤的時(shí)候重試多次。更多具體的例子,我可能會(huì)在后面講到。
  • 即使一致性層級(jí)為“ONE”,寫(xiě)入失敗仍然不能確保數(shù)據(jù)沒(méi)有被寫(xiě)入。數(shù)據(jù)仍然有可能最終傳播到其它副本。

示例:

假設(shè)我們想計(jì)算某個(gè)Item被多少User所喜愛(ài),一種方式是使用counter column family保存多少個(gè)user喜歡某個(gè)item。因?yàn)閏ounter增加(減少)特性不是更新冪等的,當(dāng)出現(xiàn)失敗并重試的時(shí)候就會(huì)導(dǎo)致數(shù)量被重復(fù)累加的情況。讓模型具有更新冪等性可以通過(guò)維護(hù)user id來(lái)代替增加counter記數(shù)。無(wú)論何時(shí)user喜愛(ài)某個(gè)item,我們都將user id寫(xiě)入item,如果寫(xiě)入失敗,我們可以安全的重試。如果希望獲取所有喜愛(ài)某個(gè)item的user,我們只需要讀取item中user id信息手動(dòng)累加就行。

在上面更新冪等(Update idempotent)模型中,獲取counter值要求讀取所有user id值,這樣的實(shí)現(xiàn)可能不夠好(因?yàn)樗赡苡猩习偃f(wàn)個(gè))。在本用例中,如果counter讀操作很頻繁,同時(shí)你能接受一個(gè)與真實(shí)值接近的值,counter column將是一個(gè)更好的、更高效的選擇。如果需要,counter值也可以周期的通過(guò)user id計(jì)算出來(lái)并更新,這樣的設(shè)計(jì)也是具有更新冪等性。

注意:Cassandra-2495可能會(huì)為失敗的counter請(qǐng)求添加一個(gè)合適的重試機(jī)制。但是,這個(gè)實(shí)踐仍然有效。所以記得經(jīng)常測(cè)試模型更新冪等性。

根據(jù)需要,圍繞事務(wù)建模

但這可能不總是能夠?qū)崿F(xiàn),具體情況具體分析

Cassandra沒(méi)有多行、集群范圍的事務(wù)或者回滾機(jī)制,取而代之,它提供行級(jí)別原子性。換句話說(shuō),對(duì)某個(gè)row key的一次mutation操作是原子的。所以當(dāng)你需要事務(wù)性的時(shí)候,嘗試設(shè)計(jì)你的模型,讓它一次永遠(yuǎn)只更新一行。但還是要考慮你的用例,這樣的設(shè)計(jì)不總是有效,如果你的系統(tǒng)需要ACID事務(wù),那你需要重新考慮數(shù)據(jù)庫(kù)的選擇了。

(譯者注:Cassandra2.0.2支持多行事務(wù),詳見(jiàn)CASSANDRA-5633。)

如果可以的話,預(yù)先設(shè)計(jì)好合適的TTL

因?yàn)楹茈y改變既有數(shù)據(jù)TTL

在Cassandra中,TTL(存活時(shí)間)不是設(shè)置在column family上,它設(shè)置于每個(gè)column value,一旦設(shè)置后就很難改變?;蛘哒f(shuō),如果創(chuàng)建column時(shí)候沒(méi)有設(shè)置,那之后就很難對(duì)其設(shè)置TTL。對(duì)于既有數(shù)據(jù)修改TTL唯一的方式就是讀取然后再次插入所有數(shù)據(jù),并賦予TTL。所以要考慮好如何清除你的數(shù)據(jù),如果可能進(jìn)來(lái)在創(chuàng)建數(shù)據(jù)的時(shí)候設(shè)置合適的TTL。

不要使用counter column family生成key信息

它不是干這個(gè)用的

counter column family保存分布式counter信息,這意味著它要做分布式的累加(遞減)運(yùn)算。不要使用counter生成序列編號(hào)(比如oracle的sequence或者M(jìn)ySQL的自增列)來(lái)生成你的rowkey(column key),否則你將可能得到重復(fù)序列編號(hào),從而導(dǎo)致數(shù)據(jù)覆蓋。大多數(shù)時(shí)間你真的不需要全局序列編號(hào),更好的選擇是使用timeuuid (type-1 uuid)來(lái)生成key信息。如果你真的需要一個(gè)全局序列編號(hào)生成器,這里有個(gè)可行的辦法,就是需要一個(gè)中央?yún)f(xié)調(diào)器,但這會(huì)影響系統(tǒng)的擴(kuò)展性和可用性。

composite columns 優(yōu)于 super columns

使用super columns可能會(huì)產(chǎn)生性能瓶頸

在Cassandra中,super column常被用于對(duì)column key進(jìn)行分組,或者建立兩層數(shù)據(jù)結(jié)構(gòu)。但是super column有下列實(shí)現(xiàn)問(wèn)題導(dǎo)致它并不那么美好:

問(wèn)題:

  • Super column的子column不能被索引,讀取一個(gè)字column意味著要反序列化整個(gè)super column
  • 子column無(wú)法使用內(nèi)建二級(jí)索引
  • Super column無(wú)法實(shí)現(xiàn)超過(guò)兩層的結(jié)構(gòu)

類(lèi)似的功能,可以通過(guò)Composite column實(shí)現(xiàn),它是包含子column的標(biāo)準(zhǔn)的column,因此標(biāo)準(zhǔn)column所有的好處它都具備,比如排序、范圍查詢,同時(shí)你可以設(shè)計(jì)出多層級(jí)的結(jié)構(gòu)。

注意composite columns中子column順序

因?yàn)榕判驔Q定數(shù)據(jù)存儲(chǔ)位置

舉個(gè)例子,一個(gè)composite column key為<state | city>,將被先按照state然后按照city的順序存儲(chǔ),換句話說(shuō),一個(gè)state的所有cities在磁盤(pán)存儲(chǔ)上是緊挨著的。

優(yōu)先使用內(nèi)置的composite types,而不是自定義類(lèi)型

因?yàn)樽远x類(lèi)型不總是可用

避免使用字符串連接(如果通過(guò)分隔符“:”或者“|”)的composite column key,取而代之,應(yīng)該使用內(nèi)置composite types (以及 comparators),它在cassandra0.8.1版本以上被支持。

Why?

  • 如果sub-columns是不同的數(shù)據(jù)類(lèi)型,自定義類(lèi)型將不能正常工作。比如,composite key<state|zip|timeuuid>將不能適用于根據(jù)類(lèi)型感知排序(state是字符串,zip是整型,timeuuid是時(shí)間類(lèi)型)。
  • 你不能針對(duì)每個(gè)sub-columns進(jìn)行不同的順序查找。比如,上面的例子中,不能根據(jù)state升序,zip進(jìn)行降序。

注意:Cassandra內(nèi)置composite types有兩種使用方法:

  • 靜態(tài) composite type:composite column的每部分的數(shù)據(jù)類(lèi)型都在column family中被提前定義好。Column family中所有column name 必須是之前定義好的類(lèi)型。
  • 動(dòng)態(tài)composite type:這個(gè)類(lèi)型允許你將不同的composite type的column name在一個(gè)column family中混合使用,甚至在一行中。

關(guān)于composite type更多信息,請(qǐng)查看這里: Introduction to composite columns

無(wú)論何時(shí),盡量?jī)?yōu)先使用靜態(tài)composite type

因?yàn)閯?dòng)態(tài)composite太靈活

如果一個(gè)column family中的column keys都是相同的composite type,則一定要使用靜態(tài)composite type。創(chuàng)建動(dòng)態(tài)composite type最初的目的是為了在一個(gè)column family中保存多用戶自定義索引。如果可能,請(qǐng)不要在一行中使用不同的composite type,除非真的有必要這么做。Cassandra-3625已經(jīng)修復(fù)了一些動(dòng)態(tài)composite的嚴(yán)重問(wèn)題。

注意:CQL3支持column name使用靜態(tài)composite type。如果想知道CQL3如何處理wide row,請(qǐng)參考這篇文章DataStax docs

就這么多,如果您能從這些最佳實(shí)踐中獲益,非常歡迎看到您的回復(fù),這就是我們Cassandra今天的使用情況。

Jay Patel, architect@eBay.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多