string(字符串)
常用命令:
set,get,decr,incr,mget 等。
使用SETBIT、GETBIT 實(shí)現(xiàn)日活,月活的統(tǒng)計(jì)
Redis Setbit 命令用于對 key 所儲存的字符串值,設(shè)置或清除指定偏移量上的位(bit)。
假如:
日活的 數(shù)據(jù)格式 是這樣的 1101010(取七天的數(shù)據(jù)) 1為 簽到 0為未簽到。
只要統(tǒng)計(jì) 1的個數(shù) 即可知道 該用戶這個月(或周,年)的簽到次數(shù)。
如 1101010 可表示 該月1,2,4,6號該用戶進(jìn)行了簽到, 其他時間未簽到。
簽到時,只修改特定位置的數(shù)據(jù)即可。
如 源數(shù)據(jù) 1101010 第七天為未簽到 修改為 已簽到時。
只需要 修改字符串的 第七個位置 設(shè)置為1 即可。
即:1101011
語法
redis Setbit 命令基本語法如下:
redis 127.0.0.1:6379> Setbit KEY_NAME OFFSET
可用版本
>= 2.2.0
返回值
指定偏移量原來儲存的位。
實(shí)例
redis> SETBIT bit 10086 1
(integer) 0
redis> GETBIT bit 10086
(integer) 1
redis> GETBIT bit 100 # bit 默認(rèn)被初始化為 0
(integer) 0
hash(哈希)
Redis hash 是一個string類型的field和value的映射表,hash特別適合用于存儲對象。
常用命令:
hget,hset,hgetall 等。
使用 hash 的特性 做 數(shù)據(jù)緩存(用戶信息緩存)
# 添加測試數(shù)據(jù)
127.0.0.1:6379> HMSET user:1 name 'zhangsan' age '16' sex '1'
OK
127.0.0.1:6379> HMSET user:2 name 'lisi' age '18' sex '0'
OK
127.0.0.1:6379> HMSET user:3 name 'wangwu' age '20' sex '1'
OK
127.0.0.1:6379> HMSET user:4 name 'zhaoliu' age '22' sex '0'
OK
127.0.0.1:6379> HMSET user:5 name 'tianqi' age '23' sex '1'
OK
# 獲取user:5 的所有信息
127.0.0.1:6379> HGETALL user:5
1) "name"
2) "tianqi"
3) "age"
4) "11"
5) "sex"
6) "0"
# 修改 user:5 的年齡
127.0.0.1:6379> HSET user:5 age "20"
(integer) 0
# 獲取 user:5 的所有信息
127.0.0.1:6379> HGET user:5 age
"20"
127.0.0.1:6379>
list(列表)
常用命令:
lpush,rpush,lpop,rpop,lrange等。
應(yīng)用場景:
Redis list的應(yīng)用場景非常多,也是Redis最重要的數(shù)據(jù)結(jié)構(gòu)之一,比如twitter的關(guān)注列表,粉絲列表等都可以用Redis的list結(jié)構(gòu)來實(shí)現(xiàn)。
實(shí)現(xiàn)方式:
Redis list的實(shí)現(xiàn)為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內(nèi)存開銷,Redis內(nèi)部的很多實(shí)現(xiàn),包括發(fā)送緩沖隊(duì)列等也都是用的這個數(shù)據(jù)結(jié)構(gòu)。
可以使用 redis + php 做郵件隊(duì)列
例如:
在使用 通過郵箱找回密碼的功能時,通常郵件不是即時發(fā)送的。
如果是即時發(fā)送,會造成用戶體驗(yàn)不好(延遲),程序耦合等。
這時候 可以使用隊(duì)列 ,先把要發(fā)送的郵箱 通過隊(duì)列存儲,再通過隊(duì)列腳本來處理隊(duì)列。這樣異步操作會好很多。
set(集合)
Redis的Set是string類型的無序集合。集合成員是唯一的,這就意味著集合中不能出現(xiàn)重復(fù)的數(shù)據(jù)。
Redis 中 集合是通過哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是O(1)。
常用命令:
sadd,spop,smembers,sunion 等。
應(yīng)用場景:
Redis set對外提供的功能與list類似是一個列表的功能,
特殊之處在于set是可以自動排重的,當(dāng)你需要存儲一個列表數(shù)據(jù),又不希望出現(xiàn)重復(fù)數(shù)據(jù)時,set是一個很好的選擇,
并且set提供了判斷某個成員是否在一個set集合內(nèi)的重要接口,這個也是list所不能提供的。
利用集合成員是唯一的特性 。可以用來做訂票系統(tǒng)。
用集合來存儲定已經(jīng)被預(yù)定的票的編號。如果有多個用戶預(yù)定了同一張票,只能有一個成功。
zset(sorted set:有序集合)
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復(fù)的成員。
不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
有序集合的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
常用命令:
zadd,zrange,zrem,zcard等。
使用場景:
Redis sorted set的使用場景與set類似,區(qū)別是set不是自動有序的,
而sorted set可以通過用戶額外提供一個優(yōu)先級(score)的參數(shù)來為成員排序,并且是插入有序的,即自動排序。
當(dāng)你需要一個有序的并且不重復(fù)的集合列表,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu),
比如twitter 的public timeline可以以發(fā)表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。
利用有序集合的特性 來做 排行榜
例如:現(xiàn)在有一個需求就是對 所有用戶的錢包金額進(jìn)行排序,取最富有的前十位用戶。
那么redis的有序集合,就可以滿足要求了。
像 日榜,周榜,月榜等等 都可以用這個做。
周榜 和 月榜 都可以通過 日榜推算。
榜單的即時性 不強(qiáng),可以用mysql 在今天凌晨時 統(tǒng)計(jì)昨天的數(shù)據(jù) 再存入 redis的有序集合。
HyperLogLog(是用來做基數(shù)統(tǒng)計(jì)的算法)
Redis 在 2.8.9 版本添加了 HyperLogLog 結(jié)構(gòu)。
Redis HyperLogLog 是用來做基數(shù)統(tǒng)計(jì)的算法,HyperLogLog 的優(yōu)點(diǎn)是,在輸入元素的數(shù)量或者體積非常非常大時,計(jì)算基數(shù)所需的空間總是固定 的、并且是很小的。
在 Redis 里面,每個 HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 2^64 個不同元素的基 數(shù)。這和計(jì)算基數(shù)時,元素越多耗費(fèi)內(nèi)存就越多的集合形成鮮明對比。
但是,因?yàn)?HyperLogLog 只會根據(jù)輸入元素來計(jì)算基數(shù),而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
常用命令:
PFADD key element [element ...]
添加指定元素到 HyperLogLog 中。
PFCOUNT key [key ...]
返回給定 HyperLogLog 的基數(shù)估算值。
PFMERGE destkey sourcekey [sourcekey ...]
將多個 HyperLogLog 合并為一個 HyperLogLog
什么是基數(shù)?
比如數(shù)據(jù)集 {1, 3, 5, 7, 5, 7, 8}, 那么這個數(shù)據(jù)集的基數(shù)集為 {1, 3, 5 ,7, 8}, 基數(shù)(不重復(fù)元素)為5。
基數(shù)就是在誤差可接受的范圍內(nèi),快速計(jì)算基數(shù)。
實(shí)例
以下實(shí)例演示了 HyperLogLog 的工作過程:
redis 127.0.0.1:6379> PFADD runoobkey "redis"
1) (integer) 1
redis 127.0.0.1:6379> PFADD runoobkey "mongodb"
1) (integer) 1
redis 127.0.0.1:6379> PFADD runoobkey "mysql"
1) (integer) 1
redis 127.0.0.1:6379> PFCOUNT runoobkey
(integer) 3
取最新N個數(shù)據(jù)的操作
比如典型的取你網(wǎng)站的最新文章,通過下面方式,我們可以將最新的5000條評論的ID放在Redis的List集合中,并將超出集合部分從數(shù)據(jù)庫獲取
使用LPUSH latest.comments<ID>命令,向list集合中插入數(shù)據(jù)
插入完成后再用LTRIM latest.comments 0 5000命令使其永遠(yuǎn)只保存最近5000個ID
然后我們在客戶端獲取某一頁評論時可以用下面的邏輯(偽代碼)
FUNCTION get_latest_comments(start,num_items):
id_list = redis.lrange("latest.comments",start,start+num_items-1)
IF id_list.length < num_items
id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
END
RETURN id_list
END
如果你還有不同的篩選維度,比如某個分類的最新N條,那么你可以再建一個按此分類的List,只存ID的話,Redis是非常高效的
排行榜應(yīng)用,取TOP N操作
這個需求與上面需求的不同之處在于,前面操作以時間為權(quán)重,這個是以某個條件為權(quán)重,比如按頂?shù)拇螖?shù)排序,這時候就需要我們的sorted set出馬了,將你要排序的值設(shè)置成sorted set的score,將具體的數(shù)據(jù)設(shè)置成相應(yīng)的value,每次只需要執(zhí)行一條ZADD命令即可。
需要精準(zhǔn)設(shè)定過期時間的應(yīng)用
比如你可以把上面說到的sorted set的score值設(shè)置成過期時間的時間戳,那么就可以簡單地通過過期時間排序,定時清除過期數(shù)據(jù)了,不僅是清除Redis中的過期數(shù)據(jù),你完全可以把Redis里這個過期時間當(dāng)成是對數(shù)據(jù)庫中數(shù)據(jù)的索引,用Redis來找出哪些數(shù)據(jù)需要過期刪除,然后再精準(zhǔn)地從數(shù)據(jù)庫中刪除相應(yīng)的記錄。
計(jì)數(shù)器應(yīng)用
Redis的命令都是原子性的,你可以輕松地利用INCR,DECR命令來構(gòu)建計(jì)數(shù)器系統(tǒng)。
Uniq操作,獲取某段時間所有數(shù)據(jù)排重值
這個使用Redis的set數(shù)據(jù)結(jié)構(gòu)最合適了,只需要不斷地將數(shù)據(jù)往set中扔就行了,set意為集合,所以會自動排重。
Pub/Sub構(gòu)建實(shí)時消息系統(tǒng)
Redis的Pub/Sub系統(tǒng)可以構(gòu)建實(shí)時的消息系統(tǒng),比如很多用Pub/Sub構(gòu)建的實(shí)時聊天系統(tǒng)的例子。
構(gòu)建隊(duì)列系統(tǒng)
使用list可以構(gòu)建隊(duì)列系統(tǒng),使用sorted set甚至可以構(gòu)建有優(yōu)先級的隊(duì)列系統(tǒng)。