天天看點

Red KV資料 庫設計模式

轉:http://blog.nosqlfan.com/html/3033.html

豐富的資料結構使得redis的設計非常的有趣。不像關系型資料庫那樣,DEV和DBA需要深度溝通,review每行sql語句,也不像memcached那樣,不需要DBA的參與。redis的DBA需要熟悉資料結構,并能了解使用場景。 下面舉一些常見适合kv資料庫的例子來談談鍵值的設計,并與關系型資料庫做一個對比,發現關系型的不足之處。 記錄使用者登入資訊的一個系統, 我們簡化業務後隻留下一張表。

這樣在已知主鍵的情況下,通過get、set就可以獲得或者修改使用者的登入次數和最後登入時間和姓名。 一般使用者是無法知道自己的id的,隻知道自己的使用者名,是以還必須有一個從name到id的映射關系,這裡的設計與上面的有所不同。

這樣每次使用者登入的時候業務邏輯如下(python版),r是redis對象,name是已經獲知的使用者名。

如果需求僅僅是已知id,更新或者擷取某個使用者的最後登入時間,登入次數,關系型和kv資料庫無啥差別。一個通過btree pk,一個通過hash,效果都很好。 假設有如下需求,查找最近登入的N個使用者。開發人員看看,還是比較簡單的,一個sql搞定。

DBA了解需求後,考慮到以後表如果比較大,是以在last_login_time上建個索引。執行計劃從索引leafblock 的最右邊開始通路N條記錄,再回表N次,效果很好。 過了兩天,又來一個需求,需要知道登入次數最多的人是誰。同樣的關系型如何處理?DEV說簡單

DBA一看,又要在login_time上建立一個索引。有沒有覺得有點問題呢,表上每個字段上都有素引。 關系型資料庫的資料存儲的的不靈活是問題的源頭,資料僅有一種儲存方法,那就是按行排列的堆表。統一的資料結構意味着你必須使用索引來改變sql的通路路徑來快速通路某個列的,而通路路徑的增加又意味着你必須使用統計資訊來輔助,于是一大堆的問題就出現了。 沒有索引,沒有統計計劃,沒有執行計劃,這就是kv資料庫。 redis裡如何滿足以上的需求呢? 對于求最新的N條資料的需求,連結清單的後進後出的特點非常适合。我們在上面的登入代碼之後添加一段代碼,維護一個登入的連結清單,控制他的長度,使得裡面永遠儲存的是最近的N個登入使用者。

這樣需要獲得最新登入人的id,如下的代碼即可

另外,求登入次數最多的人,對于排序,積分榜這類需求,sorted set非常的适合,我們把使用者和登入次數統一存儲在一個sorted set裡。

這樣假如某個使用者登入,額外維護一個sorted set,代碼如此

那麼如何獲得登入次數最多的使用者呢,逆序排列取的排名第N的使用者即可

tag表我們使用集合來存儲資料,因為集合擅長求交集、并集

那麼,即屬于ruby又屬于web的書?

即屬于ruby,但不屬于web的書?

屬于ruby和屬于web的書的合集?

簡單到不行阿。 從以上2個例子可以看出在某些場景裡,關系型資料庫是不太适合的,你可能能夠設計出滿足需求的系統,但總是感覺的怪怪的,有種生搬硬套的感覺。 尤其登入系統這個例子,頻繁的為業務建立索引。放在一個複雜的系統裡,ddl(建立索引)有可能改變執行計劃。導緻其它的sql采用不同的執行計 劃,業務複雜的老系統,這個問題是很難預估的,sql千奇百怪。要求DBA對這個系統裡所有的sql都了解,這點太難了。這個問題在oracle裡尤其嚴 重,每個DBA估計都碰到過。對于MySQL這類系統,ddl又不友善(雖然現在有online ddl的方法)。碰到大表,DBA淩晨爬起來在業務低峰期操作,這事我沒少幹過。而這種需求放到redis裡就很好處理,DBA僅僅對容量進行預估即可。 未來的OLTP系統應該是kv和關系型的緊密結合。