Redis原理介紹

 

Redis是一個基於key-value的高速緩存系統,相似於memcached,可是支持更復雜的數據結構List、Set、SortedSet,而且有持久化的功能。redis

因爲近期工做不少地方都用到了它,因此花了很多時間來閱讀文章、編碼實驗,瞭解一下Redis都能作些什麼,能有什麼樣的性能表現。sql

首先遇到的第一個問題就是,Redis到底是什麼?數據庫

這個問題看似好笑,其實否則,我很贊同Timyang的觀點,架構者對Redis的理解不一樣、定位也不一樣,決定了Redis在整個系統結構中會扮演什麼樣的角色。我總結一下,主流有3種理解:緩存

1.key value store.是一個以key-value形式存儲的數據庫,定位直指MySQL,用來做爲惟一的存儲系統。數據結構

2.memory cache.是一個把數據存儲在內存中的高速緩存,用來在應用和數據庫間提供緩衝,替代memcachd。架構

3.data structrue server.把它支持對複雜數據結構的高速操做做爲賣點,提供某些特殊業務場景的計算和展示需求。好比排行榜應用,Top 10之類的。memcached

目前更多的人仍是把它定位爲一個memcached的升級版,提供更多的數據結構操做,仍然是一個cache。post

傳統的memcached在相似於SNS社區這樣的業務場景下,有一些弊端。好比存儲好友關係,不得不使用特殊字符分隔的長字符串來保存。在好友關係沒有上限的業務需求下,操做性能低下,達不到緩存系統應有的性能水平。並且從數據庫中的關係型結構映射到cache中的長字符串形式,很明顯也是架構中很蹩腳的一個環節。性能

而Redis提供的List、Set和Sorted Set就能夠很好的業務模型映射到相應的數據結構上,契合度很高。按個人理解,關係數據庫理論幾乎能夠照搬到Redis的應用中來。ui

Redis官方教程中的仿Twitter案例就是一個很是好的入手點。用Set結構來存儲follower和following,用List結構來保存每一個人的全部post,再加上一些普通的key-value來存儲用戶基本信息,很直觀和清晰。

我再來舉一個好友關係的業務場景來描述一下個人理解,標準關係型數據庫結構是怎麼和Redis存儲結構實現一一映射的。

數據庫中有3張表:

1.用戶表有兩列:id、暱稱

2.好友關係表有列:用戶id、好友id、好友所屬分組id、好友備註、添加好友時間

3.分組表:分組id、分組名稱、所屬用戶id

增長、刪除一個好友,就是在好友關係表裏insert或delete一條記錄。

獲取某用戶的全部好友分組,及分組內的好友數:

1

2

3

4

5

select g.gid, g.gname, count(f.fuid)

from groups g left join friends f

on g.gid=f.gid

where g.uid=#uid#

group by g.gid, g.gname

獲取某用戶某分組下的好友列表:

1

2

3

4

5

6

select f.fuid, u.nickname, f.remark, f.time

from friends f left join users u

on f.fuid=u.id

where f.uid=#uid# and f.gid=#gid#

order by f.time

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

2

3

4

5

6

7

sort gid:1001:friends

by uid:123456:fuid:*:time

limit 0 10

get #

get uid:*:nickname

get uid:123456:fuid:*:remark

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的優點所在!

相關文章
相關標籤/搜索