Redis各個數據類型的使用場景

                                                    Redis各個數據類型的使用場景

Redis支持五種數據類型:
string(字符串)
hash(哈希)
list(列表)
set(集合)
zset(sorted set:有序集合)。

Redis列表命令
參考:http://www.redis.net.cn/tutorial/3501.html

使用場景

String

String數據結構是簡單的key-value類型,value其實不僅可以是String,也可以是數字。
常規key-value緩存應用;
常規計數:微博數,粉絲數等。

hash

Redis hash是一個string類型的field和value的映射表,hash特別適合用於存儲對象。
存儲部分變更的數據,如用戶信息等。

list

list就是鏈表,略有數據結構知識的人都應該能理解其結構。使用Lists結構,我們可以輕鬆地實現最新消息排行等功能。List的另一個應用就是消息隊列,可以利用List的PUSH操作,將任務存在List中,然後工作線程再用POP操作將任務取出進行執行。Redis還提供了操作List中某一段的api,你可以直接查詢,刪除List中某一段的元素。
Redis的list是每個子元素都是String類型的雙向鏈表,可以通過push和pop操作從列表的頭部或者尾部添加或者刪除元素,這樣List即可以作爲棧,也可以作爲隊列。

消息隊列系統
使用list可以構建隊列系統,使用sorted set甚至可以構建有優先級的隊列系統。
比如:將Redis用作日誌收集器
實際上還是一個隊列,多個端點將日誌信息寫入Redis,然後一個worker統一將所有日誌寫到磁盤。

取最新N個數據的操作

//把當前登錄人添加到鏈表裏
ret = r.lpush("login:last_login_times", uid)
//保持鏈表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)
//獲得前N個最新登陸的用戶Id列表

last_login_list = r.lrange("login:last_login_times", 0, N-1)
1
2
3
4
5
6

比如sina微博:
在Redis中我們的最新微博ID使用了常駐緩存,這是一直更新的。但是做了限制不能超過5000個ID,因此獲取ID的函數會一直詢問Redis。只有在start/count參數超出了這個範圍的時候,才需要去訪問數據庫。
系統不會像傳統方式那樣“刷新”緩存,Redis實例中的信息永遠是一致的。SQL數據庫(或是硬盤上的其他類型數據庫)只是在用戶需要獲取“很遠”的數據時纔會被觸發,而主頁或第一個評論頁是不會麻煩到硬盤上的數據庫了。

set

set就是一個集合,集合的概念就是一堆不重複值的組合。利用Redis提供的set數據結構,可以存儲一些集合性的數據。set中的元素是沒有順序的。
案例:
在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還爲集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給客戶端還是存集到一個新的集合中。

交集,並集,差集

//book表存儲book名稱

set book:1:name "The Ruby Programming Language"
set book:2:name "Ruby on rail"
set book:3:name "Programming Erlang"
//tag表使用集合來存儲數據,因爲集合擅長求交集、並集
sadd tag:ruby 1
sadd tag:ruby 2
sadd tag:web 2
sadd tag:erlang 3

//即屬於ruby又屬於web的書?
inter_list = redis.sinter("tag:web", "tag:ruby")
//即屬於ruby,但不屬於web的書?
diff_list = redis.sdiff("tag:ruby", "tag:web")
//屬於ruby和屬於web的書的合集?

 union_list = redis.sunion("tag:ruby", "tag:web")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

獲取某段時間所有數據去重值
這個使用Redis的set數據結構最合適了,只需要不斷地將數據往set中扔就行了,set意爲集合,所以會自動排重。

sorted set

和set相比,sorted set增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列,比如一個存儲全班同學成績的sorted set,其集合value可以是同學的學號,而score就可以是其考試得分,這樣在數據插入集合的時候,就已經進行了天然的排序。可以用sorted set來做帶權重的隊列,比如普通消息的score爲1,重要消息的score爲2,然後工作線程可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

排行榜應用,取TOP N操作
這個需求與上面需求的不同之處在於,前面操作以時間爲權重,這個是以某個條件爲權重,比如按頂的次數排序,這時候就需要我們的sorted set出馬了,將你要排序的值設置成sorted set的score,將具體的數據設置成相應的value,每次只需要執行一條ZADD命令即可。

//將登錄次數和用戶統一存儲在一個sorted set裏

zadd login:login_times 5 1
zadd login:login_times 1 2
zadd login:login_times 2 3

//當用戶登錄時,對該用戶的登錄次數自增1
ret = r.zincrby("login:login_times", 1, uid)
//那麼如何獲得登錄次數最多的用戶呢,逆序排列取得排名前N的用戶

ret = r.zrevrange("login:login_times", 0, N-1)
1
2
3
4
5
6
7
8
9

比如在線遊戲的排行榜,根據得分你通常想要:

 - 列出前100名高分選手

 - 列出某用戶當前的全球排名

這些操作對於Redis來說小菜一碟,即使你有幾百萬個用戶,每分鐘都會有幾百萬個新的得分。
模式是這樣的,每次獲得新得分時,我們用這樣的代碼:

ZADD leaderboard <score> <username>
1

你可能用userID來取代username,這取決於你是怎麼設計的。
得到前100名高分用戶很簡單:

ZREVRANGE leaderboard 0 99
1

用戶的全球排名也相似,只需要:

ZRANK leaderboard <username>
1

需要精準設定過期時間的應用
比如你可以把上面說到的sorted set的score值設置成過期時間的時間戳,那麼就可以簡單地通過過期時間排序,定時清除過期數據了,不僅是清除Redis中的過期數據,你完全可以把Redis裏這個過期時間當成是對數據庫中數據的索引,用Redis來找出哪些數據需要過期刪除,然後再精準地從數據庫中刪除相應的記錄。

範圍查找
來自Redis在Google Group上的一個問題,有一位同學發貼求助,說要解決如下的一個問題:他有一個IP範圍對應地址的列表,現在需要給出一個IP的情況下,迅速的查找到這個IP在哪個範圍,也就是要判斷此IP的所有地。這個問題引來了Redis作者Salvatore Sanfilippo(@antirez)的回答。解答如下:
例如有下面兩個範圍,10-20和30-40

  • A_start 10, A_end 20
  • B_start 30, B_end 40
    我們將這兩個範圍的起始位置存在Redis的sorted set數據結構中,基本範圍起始值作爲score,範圍名加start和end爲其value值:
redis 127.0.0.1:6379> zadd ranges 10 A_start
1
redis 127.0.0.1:6379> zadd ranges 20 A_end
1
redis 127.0.0.1:6379> zadd ranges 30 B_start
1
redis 127.0.0.1:6379> zadd ranges 40 B_end
1
1
2
3
4
5
6
7
8

這樣數據在插入sorted set後,相當於是將這些起始位置按順序排列好了。
現在我需要查找15這個值在哪一個範圍中,只需要進行如下的zrangbyscore查找:

redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1
1) "A_end"
1
2

這個命令的意思是在Sorted Sets中查找大於15的第一個值。(+inf在Redis中表示正無窮大,15前面的括號表示>15而非>=15)
查找的結果是A_end,由於所有值是按順序排列的,所以可以判定15是在A_start到A_end區間上,也就是說15是在A這個範圍裏。至此大功告成。
當然,如果你查找到的是一個start,比如咱們用25,執行下面的命令:


redis 127.0.0.1:6379> zrangebyscore ranges (25 +inf LIMIT 0 1
1) "B_start"
1
2

返回結果表明其下一個節點是一個start節點,也就是說25這個值不處在任何start和end之間,不屬於任何範圍。
當然,這個例子僅適用於類似上面的IP範圍查找的案例,因爲這些值範圍之間沒有重合。如果是有重合的情況,這個問題本身也就變成了一個一對多的問題。

Pub/Sub

Pub/Sub 從字面上理解就是發佈(Publish)與訂閱(Subscribe),在Redis中,你可以設定對某一個key值進行消息發佈及消息訂閱,當一個key值上進行了消息發佈後,所有訂閱它的客戶端都會收到相應的消息。這一功能最明顯的用法就是用作實時消息系統,比如普通的即時聊天,羣聊等功能。

使用場景

Pub/Sub構建實時消息系統

Redis的Pub/Sub系統可以構建實時的消息系統
比如很多用Pub/Sub構建的實時聊天系統的例子。

參考:
http://www.redis.net.cn/tutorial/3501.html
http://www.cnblogs.com/markhe/p/5689356.html
http://www.cnblogs.com/ggjucheng/p/3349102.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章