標籤:
文章來源:http://jingyan.baidu.com/article/db55b60996d0124ba30a2f92.html
Redis是一個基於key-value的快取系統,類似於memcached,但是支援更複雜的資料結構List、Set、Sorted Set,並且有持久化的功能。
由於近期工作很多地方都用到了它,所以花了不少時間來閱讀文章、編碼實驗,瞭解一下Redis都能做些什麼,能有什麼樣的效能表現。
首先遇到的第一個問題就是,Redis究竟是什嗎?
這個問題看似可笑,其實不然,我很贊同Timyang的觀點,架構者對Redis的理解不同、定位也不同,決定了Redis在整個系統結構中會扮演什麼樣的角色。我總結一下,主流有3種理解:
1.key value store.是一個以key-value形式儲存的資料庫,定位直指MySQL,用來作為唯一的儲存系統。
2.memory cache.是一個把資料存放區在記憶體中的快取,用來在應用和資料庫間提供緩衝,替代memcachd。
3.data structrue server.把它支援對複雜資料結構的高速操作作為賣點,提供某些特殊業務情境的計算和展現需求。比如熱門排行榜應用,Top 10之類的。
目前更多的人還是把它定位為一個memcached的升級版,提供更多的資料結構操作,仍然是一個cache。
傳統的memcached在類似於SNS社區這樣的業務情境下,有一些弊端。比如儲存好友關係,不得不使用特殊字元分隔的長字串來儲存。在好友關係沒有上限的業務需求下,操作效能低下,達不到緩衝系統應有的效能水平。而且從資料庫中的關係型結構映射到cache中的長字串形式,很明顯也是架構中很蹩腳的一個環節。
而Redis提供的List、Set和Sorted Set就可以很好的業務模型映射到相應的資料結構上,契合度很高。按我的理解,關聯式資料庫理論幾乎可以照搬到Redis的應用中來。
Redis官方教程中的仿Twitter案例就是一個非常好的入手點。用Set結構來儲存follower和following,用List結構來儲存每個人的所有post,再加上一些普通的key-value來儲存使用者基本資料,很直觀和清晰。
我再來舉一個好友關係的業務情境來描述一下我的理解,標準關係型資料庫結構是怎麼和Redis儲存結構實現一一映射的。
資料庫中有3張表:
1.使用者表有兩列:id、暱稱
2.好友關係表有列:使用者id、好友id、好友所屬分組id、好友備忘、添加好友時間
3.分組表:分組id、分組名稱、所屬使用者id
增加、刪除一個好友,就是在好友關係表裡insert或delete一條記錄。
擷取某使用者的所有好友分組,及分組內的好友數:
1 select g.gid, g.gname,count(f.fuid)2 3 from groups g left join friends f4 5 ong.gid=f.gid6 7 where g.uid=#uid#8 9 group by g.gid, g.gname
擷取某使用者某分組下的好友名單:
1 select f.fuid, u.nickname, f.remark, f.time 2 3 from friends f left join users u 4 5 onf.fuid=u.id 6 7 where f.uid=#uid#andf.gid=#gid# 8 9 order by f.time10 11 limit #start#, #count#
再來看看Redis如何?類似的業務情境。
使用者暱稱:uid:xxxxx:nickname,以String結構儲存,相當於user表
分組名稱:gid:yyyyy:gname,以String結構儲存
使用者所有分組:uid:xxxxx:groups,以Set結構儲存gid的集合
分組下好友:gid:yyyyy:friends,以Set結構儲存,儲存fuid的集合
好友:uid:xxxxx:fuid:zzzzz:gid、uid:xxxxx:fuid:zzzzz:remark、uid:xxxxx:fuid:zzzzz:time各自使用String結構儲存,相當於friends表的每個欄位
添加一個好友需要把uid:xxxxx:fuid:zzzzz:gid、uid:xxxxx:fuid:zzzzz:remark、uid:xxxxx:fuid:zzzzz:time這三個欄位set好,再sadd gid:yyyyy:friends zzzzz,把好友加到這個組的集合內
擷取某使用者的所有好友分組,及分組內的好友數,需要用smembers擷取uid:xxxxx:groups集合中的gid,再用這些gid來分別scard gid:yyyyy:friends擷取該分組下有多少好友。
擷取使用者123456在分組1001下的好友名單:
1 sort gid:1001:friends 2 3 by uid:123456:fuid:*:time 4 5 limit 0 10 6 7 get # 8 9 get uid:*:nickname10 11 get uid:123456:fuid:*:remark12 13 get uid:123456:fuid:*:time
很有意思是不是,很像sql語句,key中的*符號是個預留位置,可以被sort出的結果替換,進而get到動態key裡面的value。
我們可以總結一下,傳統的關係型資料庫,處理一對多的問題,需要把外鍵放在多的一端,因為RDBMS理論中沒有集合這個直接概念。而使用Redis,我們可以很直覺的在一的一端來管理一對多的關係,使用Set。
這隻是使用上的區別,而理論上,RDBMS的理論完全可以套用在Redis上,所有用關係型資料庫理論可以描述的結構,用Redis的資料結構,都可以實現。
最關鍵的是,如果使用MySQL,當資料規模非常大時,上面兩個查詢操作都需要藉助表關聯技術,而大表間的join在大型系統中是需要極力避免的操作。相反Redis的每個操作都會局限在一個較小的資料集範圍內,而且key-value的儲存形式,定位key只是一個複雜度為O(1)的操作。在very huge的資料量下,Redis效能效果非常優異,這就是NoSQL的優勢所在!
Redis的概述和簡單使用(轉載)