Redis提供了非常豐富的數據結構,那么利用好每種數據結構變可提高web應用的訪問速度。
應用場景:
1.取最新N個數據的操作:(Linked List)
記錄前20個最新登陸的用戶Id列表,超出的范圍可以從數據庫中獲得。
//把當前登錄人添加到鏈表里 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)
2.取 TOP N 操作:(Sorted Set)
這個需求與上面需求的不同之處在於,取最新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)
3.查找某個值所在的區間(區間無重合) :(Sorted Set)
例如有下面兩個范圍,10-20和30-40
- A_start 10, A_end 20
- B_start 30, B_end 40
我們將這兩個范圍的起始位置存在Redis的Sorted Sets數據結構中,基本范圍起始值作為score,范圍名加start和end為其value值:
redis 127.0.0.1:6379> zadd ranges 10 A_start (integer) 1 redis 127.0.0.1:6379> zadd ranges 20 A_end (integer) 1 redis 127.0.0.1:6379> zadd ranges 30 B_start (integer) 1 redis 127.0.0.1:6379> zadd ranges 40 B_end (integer) 1
這樣數據在插入Sorted Sets后,相當於是將這些起始位置按順序排列好了。
現在我需要查找15這個值在哪一個范圍中,只需要進行如下的zrangbyscore查找:
redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1 1) "A_end"
這個命令的意思是在Sorted Sets中查找大於15的第一個值。(+inf在Redis中表示正無窮大,15前面的括號表示>15而非>=15)
查找的結果是A_end,由於所有值是按順序排列的,所以可以判定15是在A_start到A_end區間上,也就是說15是在A這個范圍里。至此大功告成。
4.交集,並集,差集:(Set)
//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的書? inter_list = redis.sdiff("tag.ruby", "tag:web") //屬於ruby和屬於web的書的合集? inter_list = redis.sunion("tag.ruby", "tag:web")
5.統計每天登陸過的活躍用戶:(bitmaps)
Redis支持對String類型的value進行基於二進制位的置位操作。通過將一個用戶的id對應value上的一位,通過對活躍用戶對應的位進行置位,就能夠用一個value記錄所有活躍用戶的信息。如下圖所未,下圖中的bitmap有9個位被置為1,表示這9個位上對應的用戶是今天的活躍用戶。其中第15位表示uid為15的用戶,第一位表示uid為0的用戶。


下面表格表示對應一天,一周,一個月統計時所花費的時間。
| Period | Time(ms) |
| Daily | 50.2 |
| Weekly | 392.0 |
| Monthly | 1624.8 |
//下面是具體的java代碼片斷: //1.算出一天的活躍用戶數量 import redis.clients.jedis.Jedis; import java.util.BitSet; ... Jedis redis = new Jedis("localhost"); ... public int uniqueCount(String action, String date) { String key = action + ":" + date; BitSet users = BitSet.valueOf(redis.get(key.getBytes())); return users.cardinality(); } //2.計算某幾個內活躍用戶的數量(某一天活躍就算,所以是取並集) import redis.clients.jedis.Jedis; import java.util.BitSet; ... Jedis redis = new Jedis("localhost"); ... public int uniqueCount(String action, String... dates) { BitSet all = new BitSet(); for (String date : dates) { String key = action + ":" + date; BitSet users = BitSet.valueOf(redis.get(key.getBytes())); all.or(users); } return all.cardinality(); }
