phpredis是redis的php的一個(gè)擴(kuò)展,效率是相當(dāng)高有鏈表排序功能,對(duì)創(chuàng)建內(nèi)存級(jí)的模塊業(yè)務(wù)關(guān)系
非常實(shí)用;下面是redis官方提供的命令使用技巧:
下載地址例如以下:
https://github.com/owlient/phpredis(支持redis 2.0.4)
Redis::__construct構(gòu)造函數(shù)
$redis = new Redis();
connect, open 鏈接redis服務(wù)
參數(shù)
host: string,服務(wù)地址
port: int,端口號(hào)
timeout: float,鏈接時(shí)長(zhǎng) (可選, 默覺(jué)得 0 ,不限鏈接時(shí)間)
注: 在redis.conf中也有時(shí)間,默覺(jué)得300
pconnect, popen 不會(huì)主動(dòng)關(guān)閉的鏈接
參考上面
setOption 設(shè)置redis模式
getOption 查看redis設(shè)置的模式
ping 查看連接狀態(tài)
?
KEY相關(guān)操作
DEL
移除給定的一個(gè)或多個(gè)key。
假設(shè)key不存在,則忽略該命令。
時(shí)間復(fù)雜度:
? ? O(N),N為要移除的key的數(shù)量。
? ? 移除單個(gè)字符串類型的key,時(shí)間復(fù)雜度為O(1)。
? ? 移除單個(gè)列表、集合、有序集合或哈希表類型的key,時(shí)間復(fù)雜度為O(M),M為以上數(shù)據(jù)結(jié)構(gòu)內(nèi)的元素?cái)?shù)量。
返回值:
? ? 被移除key的數(shù)量。
?
//DEL
# 情況1: 刪除單個(gè)key
$redis->set('myname','ikodota');
echo $redis->get('myname').'<br>'; # 返回:ikodota
$redis->del('myname');# 返回 TRUE(1)
var_dump($redis->get('myname')); # 返回 bool(false)
# 情況2: 刪除一個(gè)不存在的key
if(!$redis->exists('fake_key')) # 不存在
var_dump($redis->del('fake_key')); # 返回 int(0)
# 情況3: 同一時(shí)候刪除多個(gè)key
$array_mset=array('first_key'=>'first_val',
? ? ? ? ? 'second_key'=>'second_val',
? ? ? ? ? 'third_key'=>'third_val');
$redis->mset($array_mset); #用MSET一次儲(chǔ)存多個(gè)值
$array_mget=array('first_key','second_key','third_key');
var_dump($redis->mget($array_mget)); #一次返回多個(gè)值 //array(3) { [0]=> string(9) "first_val" [1]=> string(10) "second_val" [2]=> string(9) "third_val" }
$redis->del($array_mget); #同一時(shí)候刪除多個(gè)key
var_dump($redis->mget($array_mget)); #返回 array(3) { [0]=> bool(false) [1]=> bool(false) [2]=> bool(false) }
?
KEYS
KEYS pattern?
查找符合給定模式的key。
KEYS *命中數(shù)據(jù)庫(kù)中全部key。
KEYS h?llo命中hello, hallo and hxllo等。
KEYS h*llo命中hllo和heeeeello等。
KEYS h[ae]llo命中hello和hallo,但不命中hillo。
特殊符號(hào)用"\"隔開(kāi)
時(shí)間復(fù)雜度:
? ? O(N),N為數(shù)據(jù)庫(kù)中key的數(shù)量。
返回值:
? ? 符合給定模式的key列表。
警告 :KEYS的速度很快,但在一個(gè)大的數(shù)據(jù)庫(kù)中使用它仍然可能造成性能問(wèn)題,假設(shè)你須要從一個(gè)數(shù)據(jù)集中查找特定的key,你不妨用集合(Set)。
?
//KEYS
#$redis->FLUSHALL();
$array_mset_keys=array('one'=>'1',
? ? ? ? ? 'two'=>'2',
? ? ? ? ? 'three '=>'3',
? ? ? ? ? 'four'=>'4');
$redis->mset($array_mset_keys); #用MSET一次儲(chǔ)存多個(gè)值
var_dump($redis->keys('*o*')); //array(3) { [0]=> string(4) "four" [1]=> string(3) "two" [2]=> string(3) "one" }
var_dump($redis->keys('t??')); //array(1) { [0]=> string(3) "two" }
var_dump($redis->keys('t[w]*')); //array(1) { [0]=> string(3) "two" }
print_r($redis->keys('*')); //Array ( [0] => four [1] => three [2] => two [3] => one )
?
RANDOMKEY
從當(dāng)前數(shù)據(jù)庫(kù)中隨機(jī)返回(不刪除)一個(gè)key。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)數(shù)據(jù)庫(kù)不為空時(shí),返回一個(gè)key。
? ? 當(dāng)數(shù)據(jù)庫(kù)為空時(shí),返回nil。
?
//RANDOMKEY
$redis->FLUSHALL();
# 情況1:數(shù)據(jù)庫(kù)不為空
$array_mset_randomkey=array('fruit'=>'apple',
? ? ? ? ? ? ? ? 'drink'=>'beer',
? ? ? ? ? ? ? ? 'food'=>'cookis');
$redis->mset($array_mset_randomkey);
echo $redis->randomkey();?
print_r($redis->keys('*')); # 查看數(shù)據(jù)庫(kù)內(nèi)全部key,證明RANDOMKEY并不刪除key//Array ( [0] => food [1] => drink [2] => fruit )
# 情況2:數(shù)據(jù)庫(kù)為空
$redis->flushdb(); ?# 刪除當(dāng)前數(shù)據(jù)庫(kù)全部key
var_dump($redis-> randomkey()); //bool(false)
?
TTL
TTL key
返回給定key的剩余生存時(shí)間(time to live)(以秒為單位)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? key的剩余生存時(shí)間(以秒為單位)。
? ? 當(dāng)key不存在或沒(méi)有設(shè)置生存時(shí)間時(shí),返回-1 。
//TTL
# 情況1:帶TTL的key
$redis->flushdb();
//$redis->set('name','ikodota'); # 設(shè)置一個(gè)key
$redis->expire('name',30); ?# 設(shè)置生存時(shí)間為30秒 //return (integer) 1
echo $redis->get('name'); //return ikodota
echo $redis->ttl('name'); //(integer) 25
//echo $redis->ttl('name'); ?# 30秒過(guò)去,name過(guò)期 //(integer) -1
var_dump($redis->get('name')); # 過(guò)期的key將被刪除 //return bool(false);
# 情況2:不帶TTL的key
$redis->set('site','wikipedia.org');//OK
var_dump($redis->ttl('site'));//int(-1)
# 情況3:不存在的key
$redis->EXISTS('not_exists_key');//int(0)
var_dump($redis->TTL('not_exists_key'));//int(-1)
EXISTS
EXISTS key
檢查給定key是否存在。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 若key存在,返回1,否則返回0。
//EXISTS
echo '<br>EXISTS<br>';
$redis->set('db',"redis"); //bool(true)?
var_dump($redis->exists('db')); ?# key存在 //bool(true)?
$redis->del('db'); ? # 刪除key //int(1)
var_dump($redis->exists('db')) ?# key不存在 //bool(false)
?
MOVE
MOVE key db
將當(dāng)前數(shù)據(jù)庫(kù)(默覺(jué)得0)的key移動(dòng)到給定的數(shù)據(jù)庫(kù)db其中。
假設(shè)當(dāng)前數(shù)據(jù)庫(kù)(源數(shù)據(jù)庫(kù))和給定數(shù)據(jù)庫(kù)(目標(biāo)數(shù)據(jù)庫(kù))有同樣名字的給定key,或者key不存在于當(dāng)前數(shù)據(jù)庫(kù),那么MOVE沒(méi)有不論什么效果。
因此,也能夠利用這一特性,將MOVE當(dāng)作鎖(locking)原語(yǔ)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 移動(dòng)成功返回1,失敗則返回0。
//MOVE
echo '<br><br>MOVE<br>';
# 情況1: key存在于當(dāng)前數(shù)據(jù)庫(kù)
$redis->SELECT(0); ?# redis默認(rèn)使用數(shù)據(jù)庫(kù)0,為了清晰起見(jiàn),這里再顯式指定一次。//OK
$redis->SET('song',"secret base - Zone"); //OK
var_dump ($redis->MOVE('song',1)); ?# 將song移動(dòng)到數(shù)據(jù)庫(kù)1 //bool(true)
# 情況2:當(dāng)key不存在的時(shí)候
$redis->SELECT(1);
var_dump ($redis->EXISTS('fake_key'));//bool(false);
var_dump($redis->MOVE('fake_key', 0)); ?# 試圖從數(shù)據(jù)庫(kù)1移動(dòng)一個(gè)不存在的key到數(shù)據(jù)庫(kù)0,失敗) //bool(false)
$redis->SELECT(0); # 使用數(shù)據(jù)庫(kù)0
var_dump($redis->EXISTS('fake_key')); ?# 證實(shí)fake_key不存在 //bool(false)
# 情況3:當(dāng)源數(shù)據(jù)庫(kù)和目標(biāo)數(shù)據(jù)庫(kù)有同樣的key時(shí)
$redis->SELECT(0); ?# 使用數(shù)據(jù)庫(kù)0
$redis->SET('favorite_fruit',"banana");
$redis->SELECT(1); ?# 使用數(shù)據(jù)庫(kù)1
$redis->SET('favorite_fruit',"apple");
$redis->SELECT(0); ?# 使用數(shù)據(jù)庫(kù)0,并試圖將favorite_fruit移動(dòng)到數(shù)據(jù)庫(kù)1
var_dump($redis->MOVE('favorite_fruit',1)); ?# 由于兩個(gè)數(shù)據(jù)庫(kù)有同樣的key,MOVE失敗 //return bool(false)
echo $redis->GET('favorite_fruit'); ?# 數(shù)據(jù)庫(kù)0的favorite_fruit沒(méi)變 //return banana
$redis->SELECT(1);
echo $redis->GET('favorite_fruit'); ? # 數(shù)據(jù)庫(kù)1的favorite_fruit也是 //return apple
?
RENAME?
RENAME key newkey
將key改名為newkey。
當(dāng)key和newkey同樣或者key不存在時(shí),返回一個(gè)錯(cuò)誤。
當(dāng)newkey已經(jīng)存在時(shí),RENAME命令將覆蓋舊值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 改名成功時(shí)提示OK,失敗時(shí)候返回一個(gè)錯(cuò)誤。
//RENAME
echo '<br><br>RENAME<br>';
# 情況1:key存在且newkey不存在
$redis->SET('message',"hello world");
var_dump($redis->RENAME('message','greeting')); ?//bool(true)
var_dump($redis->EXISTS('message')); ?# message不復(fù)存在 //bool(false)
var_dump($redis->EXISTS('greeting')); ? # greeting取而代之 //bool(true)
# 情況2:當(dāng)key不存在時(shí),返回錯(cuò)誤 ,php返回false;
var_dump($redis->RENAME('fake_key','never_exists')); ?//bool(false)
# 情況3:newkey已存在時(shí),RENAME會(huì)覆蓋舊newkey
$redis->SET('pc',"lenovo");
$redis->SET('personal_computer',"dell");?
var_dump($redis->RENAME('pc','personal_computer')); //bool(true)
var_dump($redis->GET('pc')); //(nil) ? bool(false)
var_dump($redis->GET('personal_computer')); ?# dell“沒(méi)有”了 //string(6) "lenovo"
?
RENAMENX?
RENAMENX key newkey
當(dāng)且僅當(dāng)newkey不存在時(shí),將key改為newkey。
出錯(cuò)的情況和RENAME一樣(key不存在時(shí)報(bào)錯(cuò))。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 改動(dòng)成功時(shí),返回1。
? ? 假設(shè)newkey已經(jīng)存在,返回0。
//RENAMENX
echo '<br><br>RENAMENX<br>';
# 情況1:newkey不存在,成功
$redis->SET('player',"MPlyaer");
$redis->EXISTS('best_player'); //int(0)
var_dump($redis->RENAMENX('player','best_player')); // bool(true)?
# 情況2:newkey存在時(shí),失敗
$redis->SET('animal',"bear");
$redis->SET('favorite_animal', "butterfly");
var_dump($redis->RENAMENX('animal', 'favorite_animal'));// bool(false)
var_dump($redis->get('animal')); //string(4) "bear"
var_dump($redis->get('favorite_animal')); //string(9) "butterfly"
TYPE
TYPE key
返回key所儲(chǔ)存的值的類型。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? none(key不存在) int(0)
? ? string(字符串) int(1)
? ? list(列表) int(3)
? ? set(集合) int(2)
? ? zset(有序集) int(4)
? ? hash(哈希表) int(5)
?
//TYPE
$redis->flushALL();
echo '<br><br>TYPE<br>';
var_dump($redis->TYPE('fake_key')); //none /int(0)
$redis->SET('weather',"sunny"); ?# 構(gòu)建一個(gè)字符串
var_dump($redis->TYPE('weather'));//string / int(1)
$redis->SADD('pat',"dog"); ?# 構(gòu)建一個(gè)集合
var_dump($redis->TYPE('pat')); //set /int(2)
$redis->LPUSH('book_list',"programming in scala"); ?# 構(gòu)建一個(gè)列表
var_dump($redis->TYPE('book_list'));//list / int(3)?
$redis->ZADD('pats',1,'cat'); ?# 構(gòu)建一個(gè)zset (sorted set) // int(1)
$redis->ZADD('pats',2,'dog');
$redis->ZADD('pats',3,'pig');
var_dump($redis->zRange('pats',0,-1)); // array(3) { [0]=> string(3) "cat" [1]=> string(3) "dog" [2]=> string(3) "pig" }
var_dump($redis->TYPE('pats')); //zset / int(4)
$redis->HSET('website','google','www.g.cn'); ? # 一個(gè)新域
var_dump($redis->HGET('website','google')); //string(8) "www.g.cn"
var_dump($redis->TYPE('website')); //hash /int(5)
EXPIRE
EXPIRE key seconds
為給定key設(shè)置生存時(shí)間。
當(dāng)key過(guò)期時(shí),它會(huì)被自己主動(dòng)刪除。
在Redis中,帶有生存時(shí)間的key被稱作“易失的”(volatile)。
?
在低于2.1.3版本號(hào)的Redis中,已存在的生存時(shí)間不可覆蓋。
從2.1.3版本號(hào)開(kāi)始,key的生存時(shí)間能夠被更新,也能夠被PERSIST命令移除。(詳情參見(jiàn) http://redis.io/topics/expire)。
?
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功返回1。
? ? 當(dāng)key不存在或者不能為key設(shè)置生存時(shí)間時(shí)(比方在低于2.1.3中你嘗試更新key的生存時(shí)間),返回0。
//EXPIRE
$redis->select(7);
//$redis->flushdb();
echo '<br><br>EXPIRE<br>';
$redis->SET('cache_page',"www.cnblogs.com/ikodota");
$redis->EXPIRE('cache_page', 30); ?# 設(shè)置30秒后過(guò)期
sleep(6);
echo $redis->TTL('cache_page').'<br>'; ? # 查看給定key的剩余生存時(shí)間 //(integer) 24
$redis->EXPIRE('cache_page', 3000); ?# 更新生存時(shí)間,3000秒
sleep(4);
echo $redis->TTL('cache_page').'<br>'; ? //(integer) 2996
?
?
EXPIREAT?
EXPIREAT key timestamp
EXPIREAT的作用和EXPIRE一樣,都用于為key設(shè)置生存時(shí)間。
不同在于EXPIREAT命令接受的時(shí)間參數(shù)是UNIX時(shí)間戳(unix timestamp)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)生存時(shí)間設(shè)置成功,返回1。
? ? 當(dāng)key不存在或沒(méi)辦法設(shè)置生存時(shí)間,返回0。
?
//EXPIREAT
echo '<br><br>EXPIREAT<br>';
$redis->SET('cache','www.google.com');
echo $redis->EXPIREAT('cache','1355292000'); # 這個(gè)key將在2012.12.12過(guò)期
echo ($redis->TTL('cache')); //return 124345085
?
OBJECT?
OBJECT subcommand [arguments [arguments]]
OBJECT命令同意從內(nèi)部察看給定key的Redis對(duì)象。
它通經(jīng)常使用在除錯(cuò)(debugging)或者了解為了節(jié)省空間而對(duì)key使用特殊編碼的情況。
當(dāng)將Redis用作緩存程序時(shí),你也能夠通過(guò)OBJECT命令中的信息,決定key的驅(qū)趕策略(eviction policies)。
OBJECT命令有多個(gè)子命令:
? ? OBJECT REFCOUNT <key>返回給定key引用所儲(chǔ)存的值的次數(shù)。此命令主要用于除錯(cuò)。
? ? OBJECT ENCODING <key>返回給定key鎖儲(chǔ)存的值所使用的內(nèi)部表示(representation)。
? ? OBJECT IDLETIME <key>返回給定key自儲(chǔ)存以來(lái)的空轉(zhuǎn)時(shí)間(idle, 沒(méi)有被讀取也沒(méi)有被寫入),以秒為單位。
對(duì)象能夠以多種方式編碼:
? ? 字符串能夠被編碼為raw(一般字符串)或int(用字符串表示64位數(shù)字是為了節(jié)約空間)。
? ? 列表能夠被編碼為ziplist或linkedlist。ziplist是為節(jié)約大小較小的列表空間而作的特殊表示。
? ? 集合能夠被編碼為intset或者h(yuǎn)ashtable。intset是僅僅儲(chǔ)存數(shù)字的小集合的特殊表示。
? ? 哈希表能夠編碼為zipmap或者h(yuǎn)ashtable。zipmap是小哈希表的特殊表示。
? ? 有序集合能夠被編碼為ziplist或者skiplist格式。ziplist用于表示小的有序集合,而skiplist則用于表示不論什么大小的有序集合。
假如你做了什么讓Redis沒(méi)辦法再使用節(jié)省空間的編碼時(shí)(比方將一個(gè)僅僅有1個(gè)元素的集合擴(kuò)展為一個(gè)有100萬(wàn)個(gè)元素的集合),特殊編碼類型(specially encoded types)會(huì)自己主動(dòng)轉(zhuǎn)換成通用類型(general type)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? REFCOUNT和IDLETIME返回?cái)?shù)字。
? ? ENCODING返回對(duì)應(yīng)的編碼類型。
//OBJECT
$redis->select(8);
echo '<br><br>OBJECT<br>';
$redis->SET('game',"WOW"); ?# 設(shè)置一個(gè)字符串
$redis->OBJECT('REFCOUNT','game'); ?# 僅僅有一個(gè)引用
//sleep(5);
echo $redis->OBJECT('IDLETIME','game'); ?# 等待一陣。。。然后查看空轉(zhuǎn)時(shí)間 //(integer) 10
//echo $redis->GET('game'); ?# 提取game, 讓它處于活躍(active)狀態(tài) ?//return WOW
//echo $redis->OBJECT('IDLETIME','game'); ?# 不再處于空轉(zhuǎn) //(integer) 0
var_dump($redis->OBJECT('ENCODING','game')); ?# 字符串的編碼方式 //string(3) "raw"
$redis->SET('phone',15820123123); ?# 大的數(shù)字也被編碼為字符串
var_dump($redis->OBJECT('ENCODING','phone')); //string(3) "raw"
$redis->SET('age',20); ?# 短數(shù)字被編碼為int
var_dump($redis->OBJECT('ENCODING','age')); //string(3) "int"
?
PERSIST?
PERSIST key
?
移除給定key的生存時(shí)間。
?
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)生存時(shí)間移除成功時(shí),返回1.
? ? 假設(shè)key不存在或key沒(méi)有設(shè)置生存時(shí)間,返回0。
?
//PERSIST
echo '<br><br>PERSIST<br>';
$redis->SET('time_to_say_goodbye',"886...");
$redis->EXPIRE('time_to_say_goodbye', 300);
sleep(3);
echo $redis->TTL('time_to_say_goodbye'); # (int) 297
echo '<br>';
$redis->PERSIST('time_to_say_goodbye'); ?# 移除生存時(shí)間
echo $redis->TTL('time_to_say_goodbye'); ?# 移除成功 ?//int(-1)
SORT
?
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]
排序,分頁(yè)等
參數(shù)
array(
‘by’ => ‘some_pattern_*’,
‘limit’ => array(0, 1),
‘get’ => ‘some_other_pattern_*’ or an array of patterns,
‘sort’ => ‘a(chǎn)sc’ or ‘desc’,
‘a(chǎn)lpha’ => TRUE,
‘store’ => ‘external-key’
)
返回或保存給定列表、集合、有序集合key中經(jīng)過(guò)排序的元素。
排序默認(rèn)以數(shù)字作為對(duì)象,值被解釋為雙精度浮點(diǎn)數(shù),然后進(jìn)行比較。
?
一般SORT使用方法
最簡(jiǎn)單的SORT用法是SORT key。
如果today_cost是一個(gè)保存數(shù)字的列表,SORT命令默認(rèn)會(huì)返回該列表值的遞增(從小到大)排序結(jié)果。
?
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('today_cost', 30);
$redis->LPUSH('today_cost', 1.5);
$redis->LPUSH('today_cost', 10);
$redis->LPUSH('today_cost', 8);
# 排序
var_dump($redis->SORT('today_cost')); //array(4) { [0]=> string(3) "1.5" [1]=> string(1) "8" [2]=> string(2) "10" [3]=> string(2) "30" }
當(dāng)數(shù)據(jù)集中保存的是字符串值時(shí),你能夠用ALPHA修飾符(modifier)進(jìn)行排序。
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('website', "www.reddit.com");
$redis->LPUSH('website', "www.slashdot.com");
$redis->LPUSH('website', "www.infoq.com");
# 默認(rèn)排序
var_dump($redis->SORT('website'));//array(3) { [0]=> string(13) "www.infoq.com" [1]=> string(16) "www.slashdot.com" [2]=> string(14) "www.reddit.com" }
# 按字符排序 ALPHA=true
var_dump($redis->SORT('website', array('ALPHA'=>TRUE))); //array(3) { [0]=> string(13) "www.infoq.com" [1]=> string(14) "www.reddit.com" [2]=> string(16) "www.slashdot.com" }
假設(shè)你正確設(shè)置了!LC_COLLATE環(huán)境變量的話,Redis能識(shí)別UTF-8編碼。
排序之后返回的元素?cái)?shù)量能夠通過(guò)LIMIT修飾符進(jìn)行限制。
LIMIT修飾符接受兩個(gè)參數(shù):offset和count。
offset指定要跳過(guò)的元素?cái)?shù)量,count指定跳過(guò)offset個(gè)指定的元素之后,要返回多少個(gè)對(duì)象。
下面樣例返回排序結(jié)果的前5個(gè)對(duì)象(offset為0表示沒(méi)有元素被跳過(guò))。
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('rank', 30); //(integer) 1
$redis->LPUSH('rank', 56); //(integer) 2
$redis->LPUSH('rank', 42); //(integer) 3
$redis->LPUSH('rank', 22); //(integer) 4
$redis->LPUSH('rank', 0); ?//(integer) 5
$redis->LPUSH('rank', 11); //(integer) 6
$redis->LPUSH('rank', 32); //(integer) 7
$redis->LPUSH('rank', 67); //(integer) 8
$redis->LPUSH('rank', 50); //(integer) 9
$redis->LPUSH('rank', 44); //(integer) 10
$redis->LPUSH('rank', 55); //(integer) 11
# 排序
$redis_sort_option=array('LIMIT'=>array(0,5));
var_dump($redis->SORT('rank',$redis_sort_option)); ? # 返回排名前五的元素 // array(5) { [0]=> string(1) "0" [1]=> string(2) "11" [2]=> string(2) "22" [3]=> string(2) "30" [4]=> string(2) "32" }
修飾符能夠組合使用。下面樣例返回降序(從大到小)的前5個(gè)對(duì)象。
$redis_sort_option=array(
? ? ? ? ? ? 'LIMIT'=>array(0,5),
? ? ? ? ? ? 'SORT'=>'DESC'
? ? ? ? ? ? );
var_dump($redis->SORT('rank',$redis_sort_option)); //array(5) { [0]=> string(2) "67" [1]=> string(2) "56" [2]=> string(2) "55" [3]=> string(2) "50" [4]=> string(2) "44" }
?
使用外部key進(jìn)行排序
有時(shí)候你會(huì)希望使用外部的key作為權(quán)重來(lái)比較元素,取代默認(rèn)的對(duì)例如法。
如果如今實(shí)用戶(user)數(shù)據(jù)例如以下:
id ?name level
-------------------------------
1 admin ?9999
2 huangz 10
59230 jack ? ?3
222 hacker ? 9999
id數(shù)據(jù)保存在key名為user_id的列表中。
name數(shù)據(jù)保存在key名為user_name_{id}的列表中
level數(shù)據(jù)保存在user_level_{id}的key中。
# 先將要使用的數(shù)據(jù)增加到數(shù)據(jù)庫(kù)中
# admin
$redis->LPUSH('user_id', 1);//(integer) 1
$redis->SET('user_name_1', 'admin');
$redis->SET('user_level_1',9999);
# huangz
$redis->LPUSH('user_id', 2);//(integer) 2
$redis->SET('user_name_2', 'huangz');
$redis->SET('user_level_2', 10);
# jack
$redis->LPUSH('user_id', 59230);//(integer) 3
$redis->SET('user_name_59230','jack');
$redis->SET('user_level_59230', 3);
# hacker
$redis->LPUSH('user_id', 222); ?//(integer) 4
$redis->SET('user_name_222', 'hacker');
$redis->SET('user_level_222', 9999);
?
假設(shè)希望按level從大到小排序user_id,能夠使用下面命令:
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option)); //array(4) { [0]=> string(3) "222" [1]=> string(1) "1" [2]=> string(1) "2" [3]=> string(5) "59230" }
#---------------------------
#1) "222" ? ?# hacker
#2) "1" ? ? ?# admin
#3) "2" ? ? ?# huangz
#4) "59230" ?# jack
可是有時(shí)候僅僅是返回相應(yīng)的id沒(méi)有什么用,你可能更希望排序后返回id相應(yīng)的username,這樣更友好一點(diǎn),使用GET選項(xiàng)能夠做到這一點(diǎn):
?
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>'user_name_*'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id', $redis_sort_option)); //array(4) { [0]=> string(6) "hacker" [1]=> string(5) "admin" [2]=> string(6) "huangz" [3]=> string(4) "jack" }
#1) "hacker"
#2) "admin"
#3) "huangz"
#4) "jack"
能夠多次地、有序地使用GET操作來(lái)獲取很多其它外部key。
比方你不但希望獲取username,還希望連用戶的password也一并列出,能夠使用下面命令:
?
# 先加入一些測(cè)試數(shù)據(jù)
$redis->SET('user_password_222', "hey,im in");
$redis->SET('user_password_1', "a_long_long_password");
$redis->SET('user_password_2', "nobodyknows");
$redis->SET('user_password_59230', "jack201022");
# 獲取name和password
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('user_name_*','user_password_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(8) { [0]=> string(6) "hacker" [1]=> string(9) "hey,im in" [2]=> string(5) "admin" [3]=> string(20) "a_long_long_password" [4]=> string(6) "huangz" [5]=> string(11) "nobodyknows" [6]=> string(4) "jack" [7]=> string(10) "jack201022" }
#------------------------------------
#1) "hacker" ? ? ? # username
#2) "hey,im in" ? ?# password
#3) "jack"
#4) "jack201022"
#5) "huangz"
#6) "nobodyknows"
#7) "admin"
#8) "a_long_long_password"
# 注意GET操作是有序的,GET user_name_* GET user_password_* 和 GET user_password_* GET user_name_*返回的結(jié)果位置不同
?
# 獲取name和password 注意GET操作是有序的
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('user_password_*','user_name_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));// array(8) { [0]=> string(9) "hey,im in" [1]=> string(6) "hacker" [2]=> string(20) "a_long_long_password" [3]=> string(5) "admin" [4]=> string(11) "nobodyknows" [5]=> string(6) "huangz" [6]=> string(10) "jack201022" [7]=> string(4) "jack" }
GET另一個(gè)特殊的規(guī)則——"GET #",用于獲取被排序?qū)ο?我們這里的樣例是user_id)的當(dāng)前元素。
比方你希望user_id按level排序,還要列出id、name和password,能夠使用下面命令:
?
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('#','user_password_*','user_name_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(12) { [0]=> string(3) "222" [1]=> string(9) "hey,im in" [2]=> string(6) "hacker" [3]=> string(1) "1" [4]=> string(20) "a_long_long_password" [5]=> string(5) "admin" [6]=> string(1) "2" [7]=> string(11) "nobodyknows" [8]=> string(6) "huangz" [9]=> string(5) "59230" [10]=> string(10) "jack201022" [11]=> string(4) "jack" }
#--------------------------------------------------------------
#1) "222" ? ? ? ? ?# id
#2) "hacker" ? ? ? # name
#3) "hey,im in" ? ?# password
#4) "1"
#5) "admin"
#6) "a_long_long_password"
#7) "2"
#8) "huangz"
#9) "nobodyknows"
#10) "59230"
#11) "jack"
#12) "jack201022"
僅僅獲取對(duì)象而不排序
BY修飾符能夠?qū)⒁粋€(gè)不存在的key當(dāng)作權(quán)重,讓SORT跳過(guò)排序操作。
該方法用于你希望獲取外部對(duì)象而又不希望引起排序開(kāi)銷時(shí)使用。
?
# 確保fake_key不存在
$redis->EXISTS('fake_key');//(integer) 0
# 以fake_key作BY參數(shù),不排序,僅僅GET name 和 GET password
$redis_sort_option=array('BY'=>'fake_key',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('#','user_name_*','user_password_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(12) { [0]=> string(3) "222" [1]=> string(6) "hacker" [2]=> string(9) "hey,im in" [3]=> string(5) "59230" [4]=> string(4) "jack" [5]=> string(10) "jack201022" [6]=> string(1) "2" [7]=> string(6) "huangz" [8]=> string(11) "nobodyknows" [9]=> string(1) "1" [10]=> string(5) "admin" [11]=> string(20) "a_long_long_password" }
#----------------------------------------------
#1) "222" ? ? ? ?# id
#2) "hacker" ? ? # user_name
#3) "hey,im in" ?# password
#4) "59230"
#5) "jack"
#6) "jack201022"
#7) "2"
#8) "huangz"
#9) "nobodyknows"
#10) "1"
#11) "admin"
#12) "a_long_long_password"
保存排序結(jié)果
默認(rèn)情況下,SORT操作僅僅是簡(jiǎn)單地返回排序結(jié)果,假設(shè)你希望保存排序結(jié)果,能夠給STORE選項(xiàng)指定一個(gè)key作為參數(shù),排序結(jié)果將以列表的形式被保存到這個(gè)key上。(若指定key已存在,則覆蓋。)
$redis->EXISTS('user_info_sorted_by_level'); ?# 確保指定key不存在 ? //(integer) 0
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'GET'=>array('#','user_name_*','user_password_*'),
? ? ? ? ? ? 'STORE'=>'user_info_sorted_by_level'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option)); //int(12)
var_dump($redis->LRANGE('user_info_sorted_by_level', 0 ,11)); ?# 查看排序結(jié)果 ?//array(12) { [0]=> string(5) "59230" [1]=> string(4) "jack" [2]=> string(10) "jack201022" [3]=> string(1) "2" [4]=> string(6) "huangz" [5]=> string(11) "nobodyknows" [6]=> string(3) "222" [7]=> string(6) "hacker" [8]=> string(9) "hey,im in" [9]=> string(1) "1" [10]=> string(5) "admin" [11]=> string(20) "a_long_long_password" }
#-----------------------------------------------------------------
#1) "59230"
#2) "jack"
#3) "jack201022"
#4) "2"
#5) "huangz"
#6) "nobodyknows"
#7) "222"
#8) "hacker"
#9) "hey,im in"
#10) "1"
#11) "admin"
#12) "a_long_long_password"
一個(gè)有趣的使用方法是將SORT結(jié)果保存,用EXPIRE為結(jié)果集設(shè)置生存時(shí)間,這樣結(jié)果集就成了SORT操作的一個(gè)緩存。
這樣就不必頻繁地調(diào)用SORT操作了,僅僅有當(dāng)結(jié)果集過(guò)期時(shí),才須要再調(diào)用一次SORT操作。
有時(shí)候?yàn)榱苏_實(shí)現(xiàn)這一使用方法,你可能須要加鎖以避免多個(gè)client同一時(shí)候進(jìn)行緩存重建(也就是多個(gè)client,同一時(shí)間進(jìn)行SORT操作,并保存為結(jié)果集),詳細(xì)參見(jiàn)SETNX命令。
在GET和BY中使用哈希表
能夠使用哈希表特有的語(yǔ)法,在SORT命令中進(jìn)行GET和BY操作。
# 如果如今我們的用戶表新增了一個(gè)serial項(xiàng)來(lái)為作為每一個(gè)用戶的序列號(hào)
# 序列號(hào)以哈希表的形式保存在serial哈希域內(nèi)。
$redis_hash_testdata_array=array(1=>'23131283',
? ? ? ? ? ? ? ? 2=>'23810573',
? ? ? ? ? ? ? ? 222=>'502342349',
? ? ? ? ? ? ? ? 59230=>'2435829758'
? ? ? ? ? ? ? ? );
$redis->HMSET('serial',$redis_hash_testdata_array);
# 我們希望以比較serial中的大小來(lái)作為排序user_id的方式
$redis_sort_option=array('BY'=>'*->serial');
var_dump($redis->SORT('user_id', $redis_sort_option)); //array(4) { [0]=> string(3) "222" [1]=> string(5) "59230" [2]=> string(1) "2" [3]=> string(1) "1" }
#----------------------------------------
#1) "222"
#2) "59230"
#3) "2"
#4) "1"
?
符號(hào)"->"用于切割哈希表的keyword(key name)和索引域(hash field),格式為"key->field"。
除此之外,哈希表的BY和GET操作和上面介紹的其它數(shù)據(jù)結(jié)構(gòu)(列表、集合、有序集合)沒(méi)有什么不同。
時(shí)間復(fù)雜度:
? ? O(N+M*log(M)),N為要排序的列表或集合內(nèi)的元素?cái)?shù)量,M為要返回的元素?cái)?shù)量。
? ? 假設(shè)僅僅是使用SORT命令的GET選項(xiàng)獲取數(shù)據(jù)而沒(méi)有進(jìn)行排序,時(shí)間復(fù)雜度O(N)。
返回值:
? ? 沒(méi)有使用STORE參數(shù),返回列表形式的排序結(jié)果。
? ? 使用STORE參數(shù),返回排序結(jié)果的元素?cái)?shù)量。
?
字符串(String)
SET
SET key value
將字符串值value關(guān)聯(lián)到key。
假設(shè)key已經(jīng)持有其它值,SET就覆寫舊值,無(wú)視類型。
時(shí)間復(fù)雜度:O(1)返回值:總是返回OK(TRUE),由于SET不可能失敗。
# 情況1:對(duì)字符串類型的key進(jìn)行SET
$redis->SET('apple', 'www.apple.com');#OK ?//bool(true)
$redis->GET('apple');//"www.apple.com"
# 情況2:對(duì)非字符串類型的key進(jìn)行SET
$redis->LPUSH('greet_list', "hello"); ?# 建立一個(gè)列表 #(integer) 1 //int(1)
$redis->TYPE('greet_list');#list //int(3)
$redis->SET('greet_list', "yooooooooooooooooo"); ? # 覆蓋列表類型 #OK //bool(true)
$redis->TYPE('greet_list');#string //int(1)
?
SETNX
SETNX key value
將key的值設(shè)為value,當(dāng)且僅當(dāng)key不存在。
若給定的key已經(jīng)存在,則SETNX不做不論什么動(dòng)作。
SETNX是”SET if Not eXists”(假設(shè)不存在,則SET)的簡(jiǎn)寫。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功,返回1。
? ? 設(shè)置失敗,返回0。
//SETNX
echo '<br><br>SETNX<br>';
$redis->EXISTS('job'); ?# job不存在 //bool(false);
$redis->SETNX('job', "programmer"); ?# job設(shè)置成功 //bool(true)
$redis->SETNX('job', "code-farmer"); ?# job設(shè)置失敗 //bool(false)
echo $redis->GET('job'); ?# 沒(méi)有被覆蓋 //"programmer"
設(shè)計(jì)模式(Design pattern): 將SETNX用于加鎖(locking)
SETNX能夠用作加鎖原語(yǔ)(locking primitive)。比方說(shuō),要對(duì)keyword(key)foo加鎖,client能夠嘗試下面方式:
SETNX lock.foo <current Unix time + lock timeout + 1>
假設(shè)SETNX返回1,說(shuō)明client已經(jīng)獲得了鎖,key設(shè)置的unix時(shí)間則指定了鎖失效的時(shí)間。之后client能夠通過(guò)DEL lock.foo來(lái)釋放鎖。
假設(shè)SETNX返回0,說(shuō)明key已經(jīng)被其它c(diǎn)lient上鎖了。假設(shè)鎖是非堵塞(non blocking lock)的,我們能夠選擇返回調(diào)用,或者進(jìn)入一個(gè)重試循環(huán),直到成功獲得鎖或重試超時(shí)(timeout)。
處理死鎖(deadlock)
上面的鎖算法有一個(gè)問(wèn)題:假設(shè)由于client失敗、崩潰或其它原因?qū)е聸](méi)有辦法釋放鎖的話,怎么辦?
這樣的狀況能夠通過(guò)檢測(cè)發(fā)現(xiàn)——由于上鎖的key保存的是unix時(shí)間戳,假如key值的時(shí)間戳小于當(dāng)前的時(shí)間戳,表示鎖已經(jīng)不再有效。
可是,當(dāng)有多個(gè)client同一時(shí)候檢測(cè)一個(gè)鎖是否過(guò)期并嘗試釋放它的時(shí)候,我們不能簡(jiǎn)單粗暴地刪除死鎖的key,再用SETNX上鎖,由于這時(shí)競(jìng)爭(zhēng)條件(race condition)已經(jīng)形成了:
? ? C1和C2讀取lock.foo并檢查時(shí)間戳,SETNX都返回0,由于它已經(jīng)被C3鎖上了,但C3在上鎖之后就崩潰(crashed)了。
? ? C1向lock.foo發(fā)送DEL命令。
? ? C1向lock.foo發(fā)送SETNX并成功。
? ? C2向lock.foo發(fā)送DEL命令。
? ? C2向lock.foo發(fā)送SETNX并成功。
? ? 出錯(cuò):由于競(jìng)爭(zhēng)條件的關(guān)系,C1和C2兩個(gè)都獲得了鎖。
幸好,下面算法能夠避免以上問(wèn)題。來(lái)看看我們聰明的C4client怎么辦:
? ? C4向lock.foo發(fā)送SETNX命令。
? ? 由于崩潰掉的C3還鎖著lock.foo,所以Redis向C4返回0。
? ? C4向lock.foo發(fā)送GET命令,查看lock.foo的鎖是否過(guò)期。假設(shè)不,則休眠(sleep)一段時(shí)間,并在之后重試。
? ? 還有一方面,假設(shè)lock.foo內(nèi)的unix時(shí)間戳比當(dāng)前時(shí)間戳老,C4運(yùn)行下面命令:
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
? ? 由于GETSET的作用,C4能夠檢查看GETSET的返回值,確定lock.foo之前儲(chǔ)存的舊值仍是那個(gè)過(guò)期時(shí)間戳,假設(shè)是的話,那么C4獲得鎖。
? ? 假設(shè)其它c(diǎn)lient,比方C5,比C4更快地運(yùn)行了GETSET操作并獲得鎖,那么C4的GETSET操作返回的就是一個(gè)未過(guò)期的時(shí)間戳(C5設(shè)置的時(shí)間戳)。C4僅僅好從第一步開(kāi)始重試。
注意,即便C4的GETSET操作對(duì)key進(jìn)行了改動(dòng),這對(duì)未來(lái)也沒(méi)什么影響。
(這里是不是有點(diǎn)問(wèn)題?C4的確是能夠重試,但C5怎么辦?它的鎖的過(guò)期被C4改動(dòng)了。——譯注)
? ? ?警告
? ? 為了讓這個(gè)加鎖算法更健壯,獲得鎖的client應(yīng)該經(jīng)常檢查過(guò)期時(shí)間以免鎖因諸如DEL等命令的運(yùn)行而被意外解開(kāi),由于client失敗的情況很復(fù)雜,不不過(guò)崩潰這么簡(jiǎn)單,還可能是client由于某些操作被堵塞了相當(dāng)長(zhǎng)時(shí)間,緊接著DEL命令被嘗試運(yùn)行(但這時(shí)鎖卻在另外的client手上)。
?
SETEX
SETEX key seconds value
將值value關(guān)聯(lián)到key,并將key的生存時(shí)間設(shè)為seconds(以秒為單位)。
假設(shè)key 已經(jīng)存在,SETEX命令將覆寫舊值。
這個(gè)命令類似于下面兩個(gè)命令:
$redis->SET('key', 'value');
$redis->EXPIRE('key','seconds'); ?# 設(shè)置生存時(shí)間?
不同之處是,SETEX是一個(gè)原子性(atomic)操作,關(guān)聯(lián)值和設(shè)置生存時(shí)間兩個(gè)動(dòng)作會(huì)在同一時(shí)間內(nèi)完畢,該命令在Redis用作緩存時(shí),很有用。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功時(shí)返回OK。
? ? 當(dāng)seconds參數(shù)不合法時(shí),返回一個(gè)錯(cuò)誤。
# 情況1:key不存在
$redis->SETEX('cache_user_id', 60,10086);//bool(true)
echo $redis->GET('cache_user_id'); ?# 值 //"10086"
sleep(4);
echo $redis->TTL('cache_user_id'); ?# 剩余生存時(shí)間 //int(56)
# 情況2:key已經(jīng)存在,key被覆寫
$redis->SET('cd', "timeless"); //bool(true);
$redis->SETEX('cd', 3000,"goodbye my love"); //bool(true);
echo $redis->GET('cd');//"goodbye my love"
?
SETRANGE
SETRANGE key offset value
用value參數(shù)覆寫(Overwrite)給定key所儲(chǔ)存的字符串值,從偏移量offset開(kāi)始。
不存在的key當(dāng)作空白字符串處理。
SETRANGE命令會(huì)確保字符串足夠長(zhǎng)以便將value設(shè)置在指定的偏移量上,假設(shè)給定key原來(lái)儲(chǔ)存的字符串長(zhǎng)度比偏移量小(比方字符串僅僅有5個(gè)字符長(zhǎng),但你設(shè)置的offset是10),那么原字符和偏移量之間的空白將用零比特(zerobytes,"\x00")來(lái)填充。
注意你能使用的最大偏移量是2^29-1(536870911),由于Redis的字符串被限制在512兆(megabytes)內(nèi)。假設(shè)你須要使用比這更大的空間,你得使用多個(gè)key。
時(shí)間復(fù)雜度:
? ? 對(duì)小(small)的字符串,平攤復(fù)雜度O(1)。(關(guān)于什么字符串是”小”的,請(qǐng)參考APPEND命令)
? ? 否則為O(M),M為value參數(shù)的長(zhǎng)度。
返回值:
? ? 被SETRANGE改動(dòng)之后,字符串的長(zhǎng)度。
? ? ?警告
? ? ?當(dāng)生成一個(gè)非常長(zhǎng)的字符串時(shí),Redis須要分配內(nèi)存空 間,該操作有時(shí)候可能會(huì)造成server堵塞(block)。在2010年的Macbook Pro上,設(shè)置偏移量為536870911(512MB內(nèi)存分配),耗費(fèi)約300毫秒, 設(shè)置偏移量為134217728(128MB內(nèi)存分配),耗費(fèi)約80毫秒,設(shè)置偏移量33554432(32MB內(nèi)存分配),耗費(fèi)約30毫秒,設(shè)置偏移量 為8388608(8MB內(nèi)存分配),耗費(fèi)約8毫秒。 注意若首次內(nèi)存分配成功之后,再對(duì)同一個(gè)key調(diào)用SETRANGE操作,無(wú)須再又一次內(nèi)存。
模式
由于有了SETRANGE和GETRANGE命令,你能夠?qū)edis字符串用作具有O(1)隨機(jī)訪問(wèn)時(shí)間的線性數(shù)組。這在非常多真有用例中都是非常高速且高效的儲(chǔ)存方式。
# 情況1:對(duì)非空字符串進(jìn)行SETRANGE
$redis->SET('greeting', "hello world");
$redis->SETRANGE('greeting', 6, "Redis"); //int(11)
$redis->GET('greeting');//"hello Redis"
# 情況2:對(duì)空字符串/不存在的key進(jìn)行SETRANGE
$redis->EXISTS('empty_string');//bool(false)
$redis->SETRANGE('empty_string', 5 ,"Redis!"); ?# 對(duì)不存在的key使用SETRANGE //int(11)
var_dump($redis->GET('empty_string')); ?# 空白處被"\x00"填充 ?#"\x00\x00\x00\x00\x00Redis!" ? //return string(11) "Redis!"
MSET?
MSET key value [key value ...]
同一時(shí)候設(shè)置一個(gè)或多個(gè)key-value對(duì)。
當(dāng)發(fā)現(xiàn)同名的key存在時(shí),MSET會(huì)用新值覆蓋舊值,假設(shè)你不希望覆蓋同名key,請(qǐng)使用MSETNX命令。
MSET是一個(gè)原子性(atomic)操作,全部給定key都在同一時(shí)間內(nèi)被設(shè)置,某些給定key被更新而還有一些給定key沒(méi)有改變的情況,不可能發(fā)生。
時(shí)間復(fù)雜度:
? ? O(N),N為要設(shè)置的key數(shù)量。
返回值:
? ? 總是返回OK(由于MSET不可能失敗)
#MSET
echo '<br><br>MSET<br>';
$redis->select(0);
$redis->flushdb();
$array_mset=array('date'=>'2012.3.5',
? ? ? ? 'time'=>'9.09a.m.',
? ? ? ? 'weather'=>'sunny'
? ? ? ? );
$redis->MSET($array_mset); //bool(true)
var_dump($redis->KEYS('*')); ? # 確保指定的三個(gè)key-value對(duì)被插入 //array(3) { [0]=> string(4) "time" [1]=> string(7) "weather" [2]=> string(4) "date" }
# MSET覆蓋舊值的樣例 可是經(jīng)過(guò)測(cè)試覆蓋不了
var_dump($redis->SET('google', "google.cn")); ? //bool(true)
var_dump($redis->MSET('google',"google.hk")); //bool(false)
echo $redis->GET('google'); //google.cn ?與redis手冊(cè)的演示樣例結(jié)果不符
?
MSETNX
MSETNX key value [key value ...]
同一時(shí)候設(shè)置一個(gè)或多個(gè)key-value對(duì),當(dāng)且僅當(dāng)key不存在。
即使僅僅有一個(gè)key已存在,MSETNX也會(huì)拒絕全部傳入key的設(shè)置操作
MSETNX是原子性的,因此它能夠用作設(shè)置多個(gè)不同key表示不同字段(field)的唯一性邏輯對(duì)象(unique logic object),全部字段要么全被設(shè)置,要么全不被設(shè)置。
時(shí)間復(fù)雜度:
? ? O(N),N為要設(shè)置的key的數(shù)量。
返回值:
? ? 當(dāng)全部key都成功設(shè)置,返回1。
? ? 假設(shè)全部key都設(shè)置失敗(最少有一個(gè)key已經(jīng)存在),那么返回0。
# 情況1:對(duì)不存在的key進(jìn)行MSETNX
$array_mset=array('rmdbs'=>'MySQL',
? ? ? ? 'nosql'=>'MongoDB',
? ? ? ? 'key-value-store'=>'redis'
? ? ? ? );
$redis->MSETNX($array_mset);//bool(true)
# 情況2:對(duì)已存在的key進(jìn)行MSETNX
$array_mset=array('rmdbs'=>'Sqlite',
? ? ? ? 'language'=>'python'
? ? ? ? );
var_dump($redis->MSETNX($array_mset)); ?# rmdbs鍵已經(jīng)存在,操作失敗 //bool(false)
var_dump($redis->EXISTS('language')); ?# 由于操作是原子性的,language沒(méi)有被設(shè)置 ?bool(false)
echo $redis->GET('rmdbs'); ?# rmdbs沒(méi)有被改動(dòng) //"MySQL"
$array_mset_keys=array( 'rmdbs', 'nosql', 'key-value-store');
print_r($redis->MGET($array_mset_keys)); //Array ( [0] => MySQL [1] => MongoDB [2] => redis )
?
APPEND
APPEND key value
假設(shè)key已經(jīng)存在而且是一個(gè)字符串,APPEND命令將value追加到key原來(lái)的值之后。
假設(shè)key不存在,APPEND就簡(jiǎn)單地將給定key設(shè)為value,就像運(yùn)行SET key value一樣。
時(shí)間復(fù)雜度:
? ? 平攤復(fù)雜度O(1)
返回值:
? ? 追加value之后,key中字符串的長(zhǎng)度。
# 情況1:對(duì)不存在的key運(yùn)行APPEND
$redis->EXISTS('myphone'); ?# 確保myphone不存在 //bool(false)
$redis->APPEND('myphone',"nokia"); ?# 對(duì)不存在的key進(jìn)行APPEND,等同于SET myphone "nokia" //int(5) # 字符長(zhǎng)度
# 情況2:對(duì)字符串進(jìn)行APPEND
$redis->APPEND('myphone', " - 1110");# 長(zhǎng)度從5個(gè)字符添加到12個(gè)字符 //int(12)
echo $redis->GET('myphone'); ?# 查看整個(gè)字符串 //"nokia - 1110"
GET
GET key
返回key所關(guān)聯(lián)的字符串值。
假設(shè)key不存在則返回特殊值nil。
假如key儲(chǔ)存的值不是字符串類型,返回一個(gè)錯(cuò)誤,由于GET僅僅能用于處理字符串值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? key的值。
? ? 假設(shè)key不存在,返回nil。
?
//GET
var_dump($redis->GET('fake_key')); #(nil) //return bool(false)
$redis->SET('animate', "anohana"); //return bool(true)
var_dump($redis->GET('animate')); //return string(7) "anohana"
?
MGET
MGET key [key ...]
返回全部(一個(gè)或多個(gè))給定key的值。
假設(shè)某個(gè)指定key不存在,那么返回特殊值nil。因此,該命令永不失敗。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 一個(gè)包括全部給定key的值的列表。
//MGET
echo '<br><br>MGET<br>';
$redis_mget_data_array=array('name'=>'ikodota','blog'=>'cnblogs.com/ikodota');
$redis->MSET($redis_mget_data_array);#用MSET一次儲(chǔ)存多個(gè)值?
$redis_mget_key_array=array('name','blog');
var_dump($redis->MGET($redis_mget_key_array)); //array(2) { [0]=> string(7) "ikodota" [1]=> string(19) "cnblogs.com/ikodota" }
$redis->EXISTS('fake_key'); //bool(false)
$redis_mget_key_array=array('name','fake_key');
var_dump($redis->MGET($redis_mget_key_array)); ?# 當(dāng)MGET中有不存在key的情況 ? //array(2) { [0]=> string(7) "ikodota" [1]=> bool(false) }
GETRANGE
GETRANGE key start end
返回key中字符串值的子字符串,字符串的截取范圍由start和end兩個(gè)偏移量決定(包含start和end在內(nèi))。
負(fù)數(shù)偏移量表示從字符串最后開(kāi)始計(jì)數(shù),-1表示最后一個(gè)字符,-2表示倒數(shù)第二個(gè),以此類推。
GETRANGE通過(guò)保證子字符串的值域(range)不超過(guò)實(shí)際字符串的值域來(lái)處理超出范圍的值域請(qǐng)求。
時(shí)間復(fù)雜度:
? ? O(N),N為要返回的字符串的長(zhǎng)度。
? ? 復(fù)雜度終于由返回值長(zhǎng)度決定,但由于從已有字符串中建立子字符串的操作很便宜(cheap),所以對(duì)于長(zhǎng)度不大的字符串,該操作的復(fù)雜度也可看作O(1)。
返回值:
? ? 截取得出的子字符串。
? ? 注解:在<=2.0的版本號(hào)里,GETRANGE被叫作SUBSTR。
//GETRANGE
echo '<br><br>GETRANGE<br>';
$redis->SET('greeting', "hello, my friend");
echo $redis->GETRANGE('greeting', 0, 4).'<br>'; ?# 返回索引0-4的字符,包含4。 //"hello"
echo $redis->GETRANGE('greeting', -1 ,-5).'<br>'; ?# 不支持回繞操作 ?//""
echo $redis->GETRANGE('greeting', -3 ,-1).'<br>'; ?# 負(fù)數(shù)索引 //"end"
echo $redis->GETRANGE('greeting', 0, -1).'<br>'; ?# 從第一個(gè)到最后一個(gè) //"hello, my friend"
echo $redis->GETRANGE('greeting', 0, 1008611).'<br>'; ?# 值域范圍不超過(guò)實(shí)際字符串,超過(guò)部分自己主動(dòng)被符略 //"hello, my friend"
?
GETSET
GETSET key value
將給定key的值設(shè)為value,并返回key的舊值。
當(dāng)key存在但不是字符串類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 返回給定key的舊值(old value)。
? ? 當(dāng)key沒(méi)有舊值時(shí),返回nil。
//GETSET
echo '<br><br>GETSET<br>';
var_dump($redis->EXISTS('mail'));//return bool(false);
var_dump($redis->GETSET('mail','xxx@google.com')); ?# 由于mail之前不存在,沒(méi)有舊值,返回nil ,#(nil) ? //bool(false)
var_dump($redis->GETSET('mail','xxx@yahoo.com')); ?# mail被更新,舊值被返回 //string(14) "xxx@google.com"
設(shè)計(jì)模式
GETSET能夠和INCR組合使用,實(shí)現(xiàn)一個(gè)有原子性(atomic)復(fù)位操作的計(jì)數(shù)器(counter)。
舉例來(lái)說(shuō),每次當(dāng)某個(gè)事件發(fā)生時(shí),進(jìn)程可能對(duì)一個(gè)名為mycount的key調(diào)用INCR操作,通常我們還要在一個(gè)原子時(shí)間內(nèi)同一時(shí)候完畢獲得計(jì)數(shù)器的值和將計(jì)數(shù)器值復(fù)位為0兩個(gè)操作。
能夠用命令GETSET mycounter 0來(lái)實(shí)現(xiàn)這一目標(biāo)。
$redis->SELECT(2);
echo $redis->INCR('mycount').'<br>'; #(integer) 11
if($redis->GET('mycount')>19){
? ? echo $redis->GETSET('mycount', 0).'<br>'; ?# 一個(gè)原子內(nèi)完畢GET mycount和SET mycount 0操作 #"11"?
}
echo $redis->GET('mycount'); #"0"
?
STRLEN
STRLEN key
返回key所儲(chǔ)存的字符串值的長(zhǎng)度。
當(dāng)key儲(chǔ)存的不是字符串值時(shí),返回一個(gè)錯(cuò)誤。
復(fù)雜度:
? ? O(1)
返回值:
? ? 字符串值的長(zhǎng)度。
? ? 當(dāng) key不存在時(shí),返回0。
$redis->SET('mykey', "Hello world");
echo $redis->STRLEN('mykey'); //int(11)
echo $redis->STRLEN('nonexisting'); # 不存在的key長(zhǎng)度視為0 ?//int(0)
INCR
INCR key
將key中儲(chǔ)存的數(shù)字值增一。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行INCR操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行INCR命令之后key的值。
? ? 注解:這是一個(gè)針對(duì)字符串的操作,由于Redis沒(méi)有專用的整數(shù)類型,所以key內(nèi)儲(chǔ)存的字符串被解釋為十進(jìn)制64位有符號(hào)整數(shù)來(lái)運(yùn)行INCR操作。
$redis->SET('page_view', 20);
var_dump($redis->INCR('page_view')); //int(21)?
var_dump($redis->GET('page_view')); ? ?# 數(shù)字值在Redis中以字符串的形式保存 //string(2) "21
INCRBY
INCRBY key increment
將key所儲(chǔ)存的值加上增量increment。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行INCRBY命令。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 加上increment之后,key的值。
//INCRBY
echo '<br><br>INCRBY<br>';
# 情況1:key存在且是數(shù)字值
$redis->SET('rank', 50); ?# 設(shè)置rank為50
$redis->INCRBY('rank', 20); ?# 給rank加上20
var_dump($redis->GET('rank')); #"70" ? //string(2) "70"
# 情況2:key不存在
$redis->EXISTS('counter'); //bool(false)
$redis->INCRBY('counter'); #int 30 ?//bool(false)
var_dump($redis->GET('counter')); #30 //經(jīng)測(cè)試 與手冊(cè)上結(jié)果不一樣,不能直接從bool型轉(zhuǎn)為int型。 return bool(false)?
# 情況3:key不是數(shù)字值
$redis->SET('book', "long long ago...");
var_dump($redis->INCRBY('book', 200)); #(error) ERR value is not an integer or out of range ? // bool(false)
?
DECR
DECR key
將key中儲(chǔ)存的數(shù)字值減一。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行DECR操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行DECR命令之后key的值。
//DECR
$redis->SELECT(3);
$redis->flushdb();
echo '<br><br>DECR<br>';
# 情況1:對(duì)存在的數(shù)字值key進(jìn)行DECR
$redis->SET('failure_times', 10);
$redis->DECR('failure_times'); //int(9)
echo $redis->GET('failure_times').'<br>'; ?//string(1) "9"
# 情況2:對(duì)不存在的key值進(jìn)行DECR
$redis->EXISTS('count'); #(integer) 0 //bool(false)
$redis->DECR('count'); ?//int(-1)?
echo $redis->GET('count').'<br>'; //string(2) "-1"
# 情況3:對(duì)存在但不是數(shù)值的key進(jìn)行DECR
$redis->SET('company', 'YOUR_CODE_SUCKS.LLC');
var_dump($redis->DECR('company')); #(error) ERR value is not an integer or out of range ? //bool(false)
echo $redis->GET('company').'<br>'; //YOUR_CODE_SUCKS.LLC
?
DECRBY
DECRBY key decrement
將key所儲(chǔ)存的值減去減量decrement。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行DECRBY操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 減去decrement之后,key的值。
# 情況1:對(duì)存在的數(shù)值key進(jìn)行DECRBY
$redis->SET('count', 100);
var_dump($redis->DECRBY('count', 20)); //int(80)
var_dump($redis->GET('count')); ?//string(2) "80"
# 情況2:對(duì)不存在的key進(jìn)行DECRBY
$redis->EXISTS('pages');#(integer) 0 ?//bool(false)
var_dump($redis->DECRBY('pages', 10)); ?//int(-10)
var_dump($redis->GET('pages')); //string(3) "-10"
?
SETBIT
SETBIT key offset value
對(duì)key所儲(chǔ)存的字符串值,設(shè)置或清除指定偏移量上的位(bit)。
位的設(shè)置或清除取決于value參數(shù),能夠是0也能夠是1。
當(dāng)key不存在時(shí),自己主動(dòng)生成一個(gè)新的字符串值。
字符串會(huì)增長(zhǎng)(grown)以確保它能夠?qū)alue保存在指定的偏移量上。當(dāng)字符串值增長(zhǎng)時(shí),空白位置以0填充。
offset參數(shù)必須大于或等于0,小于2^32(bit映射被限制在512MB內(nèi))。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 指定偏移量原來(lái)儲(chǔ)存的位("0"或"1").
? ? 警告:對(duì)使用大的offset的SETBIT操作來(lái)說(shuō),內(nèi)存分配可能造成Redisserver被堵塞。詳細(xì)參考SETRANGE命令,warning(警告)部分。
//SETBIT
echo '<br><br>SETBIT<br>';
$bit_val=67;
echo decbin($bit_val).'<br>'; //1000011
var_dump($redis->SETBIT('bit',1,1));//int(0) ?空位上都是0
var_dump($redis->SETBIT('bit',2,0));//int(0)
var_dump($redis->SETBIT('bit',3,0));//int(0)
var_dump($redis->SETBIT('bit',4,0));//int(0)
var_dump($redis->SETBIT('bit',5,0));//int(0)
var_dump($redis->SETBIT('bit',6,1));//int(0)
var_dump($redis->SETBIT('bit',7,1));//int(0)
var_dump($redis->GET('bit')); //string(1) "C" ,二進(jìn)制為:1000011 ,ASCII:67
var_dump($redis->GETBIT('bit', 6 )); //int(1) ?取出第6位(從左到右)為“1”
var_dump($redis->SETBIT('bit',5,1));//int(0) ?把第5位的0改為1
var_dump($redis->SETBIT('bit',6,0));//int(1) ?把第6位的1改為0
var_dump($redis->GET('bit')); //string(1) "E ,二進(jìn)制為:1000101,ASCII:69l
GETBIT
GETBIT key offset
對(duì)key所儲(chǔ)存的字符串值,獲取指定偏移量上的位(bit)。
當(dāng)offset比字符串值的長(zhǎng)度大,或者key不存在時(shí),返回0。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 字符串值指定偏移量上的位(bit)。
#參見(jiàn)SETBIT的演示樣例
?
哈希表(Hash)
HSET
HSET key field value
將哈希表key中的域field的值設(shè)為value。
假設(shè)key不存在,一個(gè)新的哈希表被創(chuàng)建并進(jìn)行HSET操作。
假設(shè)域field已經(jīng)存在于哈希表中,舊值將被覆蓋。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)field是哈希表中的一個(gè)新建域,而且值設(shè)置成功,返回1。
? ? 假設(shè)哈希表中域field已經(jīng)存在且舊值已被新值覆蓋,返回0。
?
HSETNX
HSETNX key field value
將哈希表key中的域field的值設(shè)置為value,當(dāng)且僅當(dāng)域field不存在。
若域field已經(jīng)存在,該操作無(wú)效。
假設(shè)key不存在,一個(gè)新哈希表被創(chuàng)建并運(yùn)行HSETNX命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功,返回1。
? ? 假設(shè)給定域已經(jīng)存在且沒(méi)有操作被運(yùn)行,返回0。
?
HMSET
HMSET key field value [field value ...]
同一時(shí)候?qū)⒍鄠€(gè)field - value(域-值)對(duì)設(shè)置到哈希表key中。
此命令會(huì)覆蓋哈希表中已存在的域。
假設(shè)key不存在,一個(gè)空哈希表被創(chuàng)建并運(yùn)行HMSET操作。
時(shí)間復(fù)雜度:
? ? O(N),N為field - value對(duì)的數(shù)量。
返回值:
? ? 假設(shè)命令運(yùn)行成功,返回OK。
? ? 當(dāng)key不是哈希表(hash)類型時(shí),返回一個(gè)錯(cuò)誤。
?
?
HGET
HGET key field
返回哈希表key中給定域field的值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 給定域的值。
? ? 當(dāng)給定域不存在或是給定key不存在時(shí),返回nil。
?
HMGET
HMGET key field [field ...]
返回哈希表key中,一個(gè)或多個(gè)給定域的值。
假設(shè)給定的域不存在于哈希表,那么返回一個(gè)nil值。
由于不存在的key被當(dāng)作一個(gè)空哈希表來(lái)處理,所以對(duì)一個(gè)不存在的key進(jìn)行HMGET操作將返回一個(gè)僅僅帶有nil值的表。
時(shí)間復(fù)雜度:
? ? O(N),N為給定域的數(shù)量。
返回值:
? ? 一個(gè)包括多個(gè)給定域的關(guān)聯(lián)值的表,表值的排列順序和給定域參數(shù)的請(qǐng)求順序一樣。
?
?
HGETALL
HGETALL key
返回哈希表key中,全部的域和值。
在返回值里,緊跟每一個(gè)域名(field name)之后是域的值(value),所以返回值的長(zhǎng)度是哈希表大小的兩倍。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 以列表形式返回哈希表的域和域的值。 若key不存在,返回空列表。
?
?
HDEL
HDEL key field [field ...]
刪除哈希表key中的一個(gè)或多個(gè)指定域,不存在的域?qū)⒈缓雎浴?
時(shí)間復(fù)雜度:
? ? O(N),N為要?jiǎng)h除的域的數(shù)量。
返回值:
? ? 被成功移除的域的數(shù)量,不包含被忽略的域。
? ? 注解:在Redis2.4下面的版本號(hào)里,HDEL每次僅僅能刪除單個(gè)域,假設(shè)你須要在一個(gè)原子時(shí)間內(nèi)刪除多個(gè)域,請(qǐng)將命令包括在MULTI/ EXEC塊內(nèi)。
?
HLEN
HLEN key
返回哈希表key中域的數(shù)量。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 哈希表中域的數(shù)量。
? ? 當(dāng)key不存在時(shí),返回0。
?
HEXISTS
HEXISTS key field
查看哈希表key中,給定域field是否存在。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)哈希表含有給定域,返回1。
? ? 假設(shè)哈希表不含有給定域,或key不存在,返回0。
?
HINCRBY
HINCRBY key field increment
為哈希表key中的域field的值加上增量increment。
增量也能夠?yàn)樨?fù)數(shù),相當(dāng)于對(duì)給定域進(jìn)行減法操作。
假設(shè)key不存在,一個(gè)新的哈希表被創(chuàng)建并運(yùn)行HINCRBY命令。
假設(shè)域field不存在,那么在運(yùn)行命令前,域的值被初始化為0。
對(duì)一個(gè)儲(chǔ)存字符串值的域field運(yùn)行HINCRBY命令將造成一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行HINCRBY命令之后,哈希表key中域field的值。
?
HKEYS
HKEYS key
返回哈希表key中的全部域。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 一個(gè)包括哈希表中全部域的表。
? ? 當(dāng)key不存在時(shí),返回一個(gè)空表。
?
HVALS
HVALS key
返回哈希表key中的全部值。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 一個(gè)包括哈希表中全部值的表。
? ? 當(dāng)key不存在時(shí),返回一個(gè)空表。
?
表(List)
頭元素和尾元素
頭元素指的是列表左端/前端第一個(gè)元素,尾元素指的是列表右端/后端第一個(gè)元素。
舉個(gè)樣例,列表list包括三個(gè)元素:x, y, z,當(dāng)中x是頭元素,而z則是尾元素。
空列表
指不包括不論什么元素的列表,Redis將不存在的key也視為空列表。
?
LPUSH
LPUSH key value [value ...]
將一個(gè)或多個(gè)值value插入到列表key的表頭。
假設(shè)有多個(gè)value值,那么各個(gè)value值按從左到右的順序依次插入到表頭:比方對(duì)一個(gè)空列表(mylist)運(yùn)行LPUSH mylist a b c,則結(jié)果列表為c b a,等同于運(yùn)行運(yùn)行命令LPUSH mylist a、LPUSH mylist b、LPUSH mylist c。
假設(shè)key不存在,一個(gè)空列表會(huì)被創(chuàng)建并運(yùn)行LPUSH操作。
當(dāng)key存在但不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行LPUSH命令后,列表的長(zhǎng)度。
?
? ? 注解:在Redis 2.4版本號(hào)曾經(jīng)的LPUSH命令,都僅僅接受單個(gè)value值。
?
LPUSHX
LPUSHX key value
將值value插入到列表key的表頭,當(dāng)且僅當(dāng)key存在而且是一個(gè)列表。
和LPUSH命令相反,當(dāng)key不存在時(shí),LPUSHX命令什么也不做。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? LPUSHX命令運(yùn)行之后,表的長(zhǎng)度。
?
RPUSH
RPUSH key value [value ...]
將一個(gè)或多個(gè)值value插入到列表key的表尾。
假設(shè)有多個(gè)value值,那么各個(gè)value值按從左到右的順序依次插入到表尾:比方對(duì)一個(gè)空列表(mylist)運(yùn)行RPUSH mylist a b c,則結(jié)果列表為a b c,等同于運(yùn)行命令RPUSHmylist a、RPUSH mylist b、RPUSH mylist c。
假設(shè)key不存在,一個(gè)空列表會(huì)被創(chuàng)建并運(yùn)行RPUSH操作。
當(dāng)key存在但不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行RPUSH操作后,表的長(zhǎng)度。
? ? 注解:在Redis 2.4版本號(hào)曾經(jīng)的RPUSH命令,都僅僅接受單個(gè)value值。
?
RPUSHX
RPUSHX key value
將值value插入到列表key的表尾,當(dāng)且僅當(dāng)key存在而且是一個(gè)列表。
和RPUSH命令相反,當(dāng)key不存在時(shí),RPUSHX命令什么也不做。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? RPUSHX命令運(yùn)行之后,表的長(zhǎng)度。
?
LPOP
LPOP key
移除并返回列表key的頭元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表的頭元素。
? ? 當(dāng)key不存在時(shí),返回nil。
?
RPOP
RPOP key
移除并返回列表key的尾元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表的尾元素。
? ? 當(dāng)key不存在時(shí),返回nil。
?
BLPOP
BLPOP key [key ...] timeout
BLPOP是列表的堵塞式(blocking)彈出原語(yǔ)。
它是LPOP命令的堵塞版本號(hào),當(dāng)給定列表內(nèi)沒(méi)有不論什么元素可供彈出的時(shí)候,連接將被BLPOP命令堵塞,直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止。
當(dāng)給定多個(gè)key參數(shù)時(shí),按參數(shù)key的先后順序依次檢查各個(gè)列表,彈出第一個(gè)非空列表的頭元素。
非堵塞行為
當(dāng)BLPOP被調(diào)用時(shí),假設(shè)給定key內(nèi)至少有一個(gè)非空列表,那么彈出遇到的第一個(gè)非空列表的頭元素,并和被彈出元素所屬的列表的名字一起,組成結(jié)果返回給調(diào)用者。
當(dāng)存在多個(gè)給定key時(shí),BLPOP按給定key參數(shù)排列的先后順序,依次檢查各個(gè)列表。
如果如今有job、 command和request三個(gè)列表,當(dāng)中job不存在,command和request都持有非空列表。考慮下面命令:
BLPOP job command request 0
BLPOP保證返回的元素來(lái)自command,由于它是按”查找job -> 查找command -> 查找request“這種順序,第一個(gè)找到的非空列表。
?
?
堵塞行為
假設(shè)全部給定key都不存在或包括空列表,那么BLPOP命令將堵塞連接,直到等待超時(shí),或有還有一個(gè)client對(duì)給定key的隨意一個(gè)運(yùn)行LPUSH或RPUSH命令為止。
超時(shí)參數(shù)timeout接受一個(gè)以秒為單位的數(shù)字作為值。超時(shí)參數(shù)設(shè)為0表示堵塞時(shí)間能夠無(wú)限期延長(zhǎng)(block indefinitely) 。
?
?
同樣的key被多個(gè)client同一時(shí)候堵塞
同樣的key能夠被多個(gè)client同一時(shí)候堵塞。
不同的client被放進(jìn)一個(gè)隊(duì)列中,按”先堵塞先服務(wù)”(first-BLPOP,first-served)的順序?yàn)閗ey運(yùn)行BLPOP命令。
在MULTI/EXEC事務(wù)中的BLPOP
BLPOP能夠用于流水線(pipline,批量地發(fā)送多個(gè)命令并讀入多個(gè)回復(fù)),但把它用在MULTI/EXEC塊其中沒(méi)有意義。由于這要求整個(gè)server被堵塞以保證塊運(yùn)行時(shí)的原子性,該行為阻止了其它c(diǎn)lient運(yùn)行LPUSH或RPUSH命令。
因此,一個(gè)被包裹在MULTI/EXEC塊內(nèi)的BLPOP命令,行為表現(xiàn)得就像LPOP一樣,對(duì)空列表返回nil,對(duì)非空列表彈出列表元素,不進(jìn)行不論什么堵塞操作。
?
?
時(shí)間復(fù)雜度:O(1)返回值:
假設(shè)列表為空,返回一個(gè)nil。
反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素所屬的key,第二個(gè)元素是被彈出元素的值。
?
?
BRPOP
BRPOP key [key ...] timeout
BRPOP是列表的堵塞式(blocking)彈出原語(yǔ)。
它是RPOP命令的堵塞版本號(hào),當(dāng)給定列表內(nèi)沒(méi)有不論什么元素可供彈出的時(shí)候,連接將被BRPOP命令堵塞,直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止。
當(dāng)給定多個(gè)key參數(shù)時(shí),按參數(shù)key的先后順序依次檢查各個(gè)列表,彈出第一個(gè)非空列表的尾部元素。
關(guān)于堵塞操作的很多其它信息,請(qǐng)查看BLPOP命令,BRPOP除了彈出元素的位置和BLPOP不同之外,其它表現(xiàn)一致。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假如在指定時(shí)間內(nèi)沒(méi)有不論什么元素被彈出,則返回一個(gè)nil和等待時(shí)長(zhǎng)。
? ? 反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素所屬的key,第二個(gè)元素是被彈出元素的值。
?
LLEN
LLEN key
返回列表key的長(zhǎng)度。
假設(shè)key不存在,則key被解釋為一個(gè)空列表,返回0.
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表key的長(zhǎng)度。
?
LRANGE
LRANGE key start stop
返回列表key中指定區(qū)間內(nèi)的元素,區(qū)間以偏移量start和stop指定。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
注意LRANGE命令和編程語(yǔ)言區(qū)間函數(shù)的差別
假如你有一個(gè)包括一百個(gè)元素的列表,對(duì)該列表運(yùn)行LRANGE list 0 10,結(jié)果是一個(gè)包括11個(gè)元素的列表,這表明stop下標(biāo)也在LRANGE命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語(yǔ)言的區(qū)間函數(shù)可能不一致,比方Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標(biāo)
超出范圍的下標(biāo)值不會(huì)引起錯(cuò)誤。
假設(shè)start下標(biāo)比列表的最大下標(biāo)end(LLEN list減去1)還要大,或者start > stop,LRANGE返回一個(gè)空列表。
假設(shè)stop下標(biāo)比end下標(biāo)還要大,Redis將stop的值設(shè)置為end。
時(shí)間復(fù)雜度:
? ? O(S+N),S為偏移量start,N為指定區(qū)間內(nèi)元素的數(shù)量。
返回值:
? ? 一個(gè)列表,包括指定區(qū)間內(nèi)的元素。
?
LREM
LREM key count value
依據(jù)參數(shù)count的值,移除列表中與參數(shù)value相等的元素。
count的值能夠是下面幾種:
? ? ? ? count > 0: 從表頭開(kāi)始向表尾搜索,移除與value相等的元素,數(shù)量為count。
? ? ? ? count < 0: 從表尾開(kāi)始向表頭搜索,移除與value相等的元素,數(shù)量為count的絕對(duì)值。
? ? ? ? count = 0: 移除表中全部與value相等的值。
時(shí)間復(fù)雜度:
? ? O(N),N為列表的長(zhǎng)度。
返回值:
? ? 被移除元素的數(shù)量。
? ? 由于不存在的key被視作空表(empty list),所以當(dāng)key不存在時(shí),LREM命令總是返回0。
?
LSET
LSET key index value
將列表key下標(biāo)為index的元素的值甚至為value。
很多其它信息請(qǐng)參考LINDEX操作。
當(dāng)index參數(shù)超出范圍,或?qū)σ粋€(gè)空列表(key不存在)進(jìn)行LSET時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? 對(duì)頭元素或尾元素進(jìn)行LSET操作,復(fù)雜度為O(1)。
? ? 其它情況下,為O(N),N為列表的長(zhǎng)度。
返回值:
? ? 操作成功返回ok,否則返回錯(cuò)誤信息
?
LTRIM
LTRIM key start stop
對(duì)一個(gè)列表進(jìn)行修剪(trim),就是說(shuō),讓列表僅僅保留指定區(qū)間內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除。
舉個(gè)樣例,運(yùn)行命令LTRIM list 0 2,表示僅僅保留列表list的前三個(gè)元素,其余元素所有刪除。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
當(dāng)key不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
LTRIM命令通常和LPUSH命令或RPUSH命令配合使用,舉個(gè)樣例:
?
?
這個(gè)樣例模擬了一個(gè)日志程序,每次將最新日志newest_log放到log列表中,而且僅僅保留最新的100項(xiàng)。注意當(dāng)這樣使用LTRIM命令時(shí),時(shí)間復(fù)雜度是O(1),由于平均情況下,每次僅僅有一個(gè)元素被移除。
注意LTRIM命令和編程語(yǔ)言區(qū)間函數(shù)的差別
假如你有一個(gè)包括一百個(gè)元素的列表list,對(duì)該列表運(yùn)行LTRIM list 0 10,結(jié)果是一個(gè)包括11個(gè)元素的列表,這表明stop下標(biāo)也在LTRIM命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語(yǔ)言的區(qū)間函數(shù)可能不一致,比方Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標(biāo)
超出范圍的下標(biāo)值不會(huì)引起錯(cuò)誤。
假設(shè)start下標(biāo)比列表的最大下標(biāo)end(LLEN list減去1)還要大,或者start > stop,LTRIM返回一個(gè)空列表(由于LTRIM已經(jīng)將整個(gè)列表清空)。
假設(shè)stop下標(biāo)比end下標(biāo)還要大,Redis將stop的值設(shè)置為end。
時(shí)間復(fù)雜度:
? ? O(N),N為被移除的元素的數(shù)量。
返回值:
? ? 命令運(yùn)行成功時(shí),返回ok。
?
?
LINDEX
LINDEX key index
返回列表key中,下標(biāo)為index的元素。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為到達(dá)下標(biāo)index過(guò)程中經(jīng)過(guò)的元素?cái)?shù)量。
? ? 因此,對(duì)列表的頭元素和尾元素運(yùn)行LINDEX命令,復(fù)雜度為O(1)。
返回值:
? ? 列表中下標(biāo)為index的元素。
? ? 假設(shè)index參數(shù)的值不在列表的區(qū)間范圍內(nèi)(out of range),返回nil。
?
LINSERT
LINSERT key BEFORE|AFTER pivot value
將值value插入到列表key其中,位于值pivot之前或之后。
當(dāng)pivot不存在于列表key時(shí),不運(yùn)行不論什么操作。
當(dāng)key不存在時(shí),key被視為空列表,不運(yùn)行不論什么操作。
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為尋找pivot過(guò)程中經(jīng)過(guò)的元素?cái)?shù)量。
返回值:
? ? 假設(shè)命令運(yùn)行成功,返回插入操作完畢之后,列表的長(zhǎng)度。
? ? 假設(shè)沒(méi)有找到pivot,返回-1。
? ? 假設(shè)key不存在或?yàn)榭樟斜恚祷?。
?
?
RPOPLPUSH
RPOPLPUSH source destination
命令RPOPLPUSH在一個(gè)原子時(shí)間內(nèi),運(yùn)行下面兩個(gè)動(dòng)作:
? ? ? ? 將列表source中的最后一個(gè)元素(尾元素)彈出,并返回給client。
? ? ? ? 將source彈出的元素插入到列表destination,作為destination列表的的頭元素。
舉個(gè)樣例,你有兩個(gè)列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,運(yùn)行RPOPLPUSH source destination之后,source列表包括元素a, b,destination列表包括元素c, x, y, z ,而且元素c被返回。
假設(shè)source不存在,值nil被返回,而且不運(yùn)行其它動(dòng)作。
假設(shè)source和destination同樣,則列表中的表尾元素被移動(dòng)到表頭,并返回該元素,能夠把這樣的特殊情況視作列表的旋轉(zhuǎn)(rotation)操作。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被彈出的元素。
?
設(shè)計(jì)模式: 一個(gè)安全的隊(duì)列
Redis的列表常常被用作隊(duì)列(queue),用于在不同程序之間有序地交換消息(message)。一個(gè)程序(稱之為生產(chǎn)者,producer)通過(guò)LPUSH命令將消息放入隊(duì)列中,而還有一個(gè)程序(稱之為消費(fèi)者,consumer)通過(guò)RPOP命令取出隊(duì)列中等待時(shí)間最長(zhǎng)的消息。
不幸的是,在這個(gè)過(guò)程中,一個(gè)消費(fèi)者可能在獲得一個(gè)消息之后崩潰,而未運(yùn)行完畢的消息也因此丟失。
使用RPOPLPUSH命令能夠解決問(wèn)題,由于它在返回一個(gè)消息之余,還將該消息加入到還有一個(gè)列表其中,另外的這個(gè)列表能夠用作消息的備份表:假如一切正常,當(dāng)消費(fèi)者完畢該消息的處理之后,能夠用LREM命令將該消息從備份表刪除。
還有一方面,助手(helper)程序能夠通過(guò)監(jiān)視備份表,將超過(guò)一定處理時(shí)限的消息又一次放入隊(duì)列中去(負(fù)責(zé)處理該消息的消費(fèi)者可能已經(jīng)崩潰),這樣就不會(huì)丟失不論什么消息了。
?
BRPOPLPUSH
BRPOPLPUSH source destination timeout
BRPOPLPUSH是RPOPLPUSH的堵塞版本號(hào),當(dāng)給定列表source不為空時(shí),BRPOPLPUSH的表現(xiàn)和RPOPLPUSH一樣。
當(dāng)列表source為空時(shí),BRPOPLPUSH命令將堵塞連接,直到等待超時(shí),或有還有一個(gè)client對(duì)source運(yùn)行LPUSH或RPUSH命令為止。
超時(shí)參數(shù)timeout接受一個(gè)以秒為單位的數(shù)字作為值。超時(shí)參數(shù)設(shè)為0表示堵塞時(shí)間能夠無(wú)限期延長(zhǎng)(block indefinitely) 。
很多其它相關(guān)信息,請(qǐng)參考RPOPLPUSH命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假如在指定時(shí)間內(nèi)沒(méi)有不論什么元素被彈出,則返回一個(gè)nil和等待時(shí)長(zhǎng)。
? ? 反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素的值,第二個(gè)元素是等待時(shí)長(zhǎng)。
?
?
集合(Set)
?附錄,經(jīng)常使用集合運(yùn)算:
? ? ? ?A = {'a', 'b', 'c'}
? ? B = {'a', 'e', 'i', 'o', 'u'}
? ? inter(x, y): 交集,在集合x和集合y中都存在的元素。
? ? inter(A, B) = {'a'}
? ? union(x, y): 并集,在集合x中或集合y中的元素,假設(shè)一個(gè)元素在x和y中都出現(xiàn),那僅僅記錄一次就可以。
? ? union(A,B) = {'a', 'b', 'c', 'e', 'i', 'o', 'u'}
? ? diff(x, y): 差集,在集合x中而不在集合y中的元素。
? ? diff(A,B) = {'b', 'c'}
? ? card(x): 基數(shù),一個(gè)集合中元素的數(shù)量。
? ? card(A) = 3
? ? 空集: 基數(shù)為0的集合。
?
SADD
SADD key member [member ...]
將一個(gè)或多個(gè)member元素增加到集合key其中,已經(jīng)存在于集合的member元素將被忽略。
假如key不存在,則創(chuàng)建一個(gè)僅僅包括member元素作成員的集合。
當(dāng)key不是集合類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N是被加入的元素的數(shù)量。
返回值:
? ? 被加入到集合中的新元素的數(shù)量,不包含被忽略的元素。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),SADD僅僅接受單個(gè)member值。
?
?
SREM
SREM key member [member ...]
移除集合key中的一個(gè)或多個(gè)member元素,不存在的member元素會(huì)被忽略。
當(dāng)key不是集合類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為給定member元素的數(shù)量。
返回值:
? ? 被成功移除的元素的數(shù)量,不包含被忽略的元素。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),SREM僅僅接受單個(gè)member值。
?
?
SMEMBERS
SMEMBERS key
返回集合key中的全部成員。
時(shí)間復(fù)雜度:
? ? O(N),N為集合的基數(shù)。
返回值:
? ? 集合中的全部成員。
?
?
SISMEMBER
SISMEMBER key member
推斷member元素是否是集合key的成員。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)member元素是集合的成員,返回1。
? ? 假設(shè)member元素不是集合的成員,或key不存在,返回0。
?
?
SCARD
SCARD key
返回集合key的基數(shù)(集合中元素的數(shù)量)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 集合的基數(shù)。
? ? 當(dāng)key不存在時(shí),返回0。
?
?
SMOVE
SMOVE source destination member
將member元素從source集合移動(dòng)到destination集合。
SMOVE是原子性操作。
假設(shè)source集合不存在或不包括指定的member元素,則SMOVE命令不運(yùn)行不論什么操作,僅返回0。否則,member元素從source集合中被移除,并加入到destination集合中去。
當(dāng)destination集合已經(jīng)包括member元素時(shí),SMOVE命令僅僅是簡(jiǎn)單地將source集合中的member元素刪除。
當(dāng)source或destination不是集合類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)member元素被成功移除,返回1。
? ? 假設(shè)member元素不是source集合的成員,而且沒(méi)有不論什么操作對(duì)destination集合運(yùn)行,那么返回0。
?
?
SPOP
SPOP key
移除并返回集合中的一個(gè)隨機(jī)元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被移除的隨機(jī)元素。
? ? 當(dāng)key不存在或key是空集時(shí),返回nil。
?
?
? ? 也能夠參考:假設(shè)僅僅想獲取一個(gè)隨機(jī)元素,但不想該元素從集合中被移除的話,能夠使用SRANDMEMBER命令。
?
SRANDMEMBER
SRANDMEMBER key
返回集合中的一個(gè)隨機(jī)元素。
該操作和SPOP相似,但SPOP將隨機(jī)元素從集合中移除并返回,而SRANDMEMBER則只返回隨機(jī)元素,而不正確集合進(jìn)行不論什么修改。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被選中的隨機(jī)元素。 當(dāng)key不存在或key是空集時(shí),返回nil。
?
?
SINTER
SINTER key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的交集。
不存在的key被視為空集。
當(dāng)給定集合其中有一個(gè)空集時(shí),結(jié)果也為空集(依據(jù)集合運(yùn)算定律)。
時(shí)間復(fù)雜度:
? ? O(N * M),N為給定集合其中基數(shù)最小的集合,M為給定集合的個(gè)數(shù)。
返回值:
? ? 交集成員的列表。
?
?
SINTERSTORE
SINTERSTORE destination key [key ...]
此命令等同于SINTER,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination集合已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N * M),N為給定集合其中基數(shù)最小的集合,M為給定集合的個(gè)數(shù)。
返回值:
? ? 結(jié)果集中的成員數(shù)量。
?
?
SUNION
SUNION key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的并集。
不存在的key被視為空集。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 并集成員的列表。
?
?
SUNIONSTORE
SUNIONSTORE destination key [key ...]
此命令等同于SUNION,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 結(jié)果集中的元素?cái)?shù)量。
?
?
SDIFF
SDIFF key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的差集 。
不存在的key被視為空集。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 交集成員的列表。
?
?
SDIFFSTORE
SDIFFSTORE destination key [key ...]
此命令等同于SDIFF,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination集合已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 結(jié)果集中的元素?cái)?shù)量。
?
?
有序集(Sorted Set)
ZADD
?
ZADD key score member [[score member] [score member] ...]
將一個(gè)或多個(gè)member元素及其score值增加到有序集key其中。
假設(shè)某個(gè)member已經(jīng)是有序集的成員,那么更新這個(gè)member的score值,并通過(guò)又一次插入這個(gè)member元素,來(lái)保證該member在正確的位置上。
score值能夠是整數(shù)值或雙精度浮點(diǎn)數(shù)。
假設(shè)key不存在,則創(chuàng)建一個(gè)空的有序集并運(yùn)行ZADD操作。
當(dāng)key存在但不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
對(duì)有序集的很多其它介紹請(qǐng)參見(jiàn)sorted set。
時(shí)間復(fù)雜度:
? ? O(M*log(N)),N是有序集的基數(shù),M為成功加入的新成員的數(shù)量。
返回值:
? ? 被成功加入的新成員的數(shù)量,不包含那些被更新的、已經(jīng)存在的成員。
?
? ? ?
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),ZADD每次僅僅能加入一個(gè)元素。
?
?
ZREM
ZREM key member [member ...]
移除有序集key中的一個(gè)或多個(gè)成員,不存在的成員將被忽略。
當(dāng)key存在但不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(M*log(N)),N為有序集的基數(shù),M為被成功移除的成員的數(shù)量。
返回值:
? ? 被成功移除的成員的數(shù)量,不包含被忽略的成員。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),ZREM每次僅僅能刪除一個(gè)元素。
?
?
ZCARD
ZCARD key
返回有序集key的基數(shù)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)key存在且是有序集類型時(shí),返回有序集的基數(shù)。
? ? 當(dāng)key不存在時(shí),返回0。
?
ZCOUNT
ZCOUNT key min max
返回有序集key中,score值在min和max之間(默認(rèn)包含score值等于min或max)的成員。
關(guān)于參數(shù)min和max的具體用法,請(qǐng)參考ZRANGEBYSCORE命令。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為值在min和max之間的元素的數(shù)量。
返回值:
? ? score值在min和max之間的成員的數(shù)量。
?
ZSCORE
ZSCORE key member
返回有序集key中,成員member的score值。
假設(shè)member元素不是有序集key的成員,或key不存在,返回nil。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? member成員的score值,以字符串形式表示。
?
ZINCRBY
ZINCRBY key increment member
為有序集key的成員member的score值加上增量increment。
你也能夠通過(guò)傳遞一個(gè)負(fù)數(shù)值increment,讓score減去對(duì)應(yīng)的值,比方ZINCRBY key -5 member,就是讓member的score值減去5。
當(dāng)key不存在,或member不是key的成員時(shí),ZINCRBY key increment member等同于ZADD key increment member。
當(dāng)key不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
score值能夠是整數(shù)值或雙精度浮點(diǎn)數(shù)。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? member成員的新score值,以字符串形式表示。
?
?
ZRANGE
ZRANGE key start stop [WITHSCORES]
返回有序集key中,指定區(qū)間內(nèi)的成員。
當(dāng)中成員的位置按score值遞增(從小到大)來(lái)排序。
具有同樣score值的成員按字典序(lexicographical order)來(lái)排列。
假設(shè)你須要成員按score值遞減(從大到小)來(lái)排列,請(qǐng)使用ZREVRANGE命令。
下標(biāo)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示有序集第一個(gè)成員,以1表示有序集第二個(gè)成員,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示最后一個(gè)成員,-2表示倒數(shù)第二個(gè)成員,以此類推。
超出范圍的下標(biāo)并不會(huì)引起錯(cuò)誤。
比方說(shuō),當(dāng)start的值比有序集的最大下標(biāo)還要大,或是start > stop時(shí),ZRANGE命令僅僅是簡(jiǎn)單地返回一個(gè)空列表。
還有一方面,假如stop參數(shù)的值比有序集的最大下標(biāo)還要大,那么Redis將stop當(dāng)作最大下標(biāo)來(lái)處理。
能夠通過(guò)使用WITHSCORES選項(xiàng),來(lái)讓成員和它的score值一并返回,返回列表以value1,score1, ..., valueN,scoreN的格式表示。
client庫(kù)可能會(huì)返回一些更復(fù)雜的數(shù)據(jù)類型,比方數(shù)組、元組等。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
ZREVRANGE
ZREVRANGE key start stop [WITHSCORES]
返回有序集key中,指定區(qū)間內(nèi)的成員。
當(dāng)中成員的位置按score值遞減(從大到小)來(lái)排列。
具有同樣score值的成員按字典序的反序(reverse lexicographical order)排列。
除了成員按score值遞減的次序排列這一點(diǎn)外,ZREVRANGE命令的其它方面和ZRANGE命令一樣。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZRANGEBYSCORE
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集key中,全部score值介于min和max之間(包含等于min或max)的成員。有序集成員按score值遞增(從小到大)次序排列。
具有同樣score值的成員按字典序(lexicographical order)來(lái)排列(該屬性是有序集提供的,不須要額外的計(jì)算)。
可選的LIMIT參數(shù)指定返回結(jié)果的數(shù)量及區(qū)間(就像SQL中的SELECT LIMIT offset, count),注意當(dāng)offset非常大時(shí),定位offset的操作可能須要遍歷整個(gè)有序集,此過(guò)程最壞復(fù)雜度為O(N)時(shí)間。
可選的WITHSCORES參數(shù)決定結(jié)果集是單單返回有序集的成員,還是將有序集成員及其score值一起返回。
該選項(xiàng)自Redis 2.0版本號(hào)起可用。
區(qū)間及無(wú)限
min和max能夠是-inf和+inf,這樣一來(lái),你就能夠在不知道有序集的最低和最高score值的情況下,使用ZRANGEBYSCORE這類命令。
默認(rèn)情況下,區(qū)間的取值使用閉區(qū)間(小于等于或大于等于),你也能夠通過(guò)給參數(shù)前添加(符號(hào)來(lái)使用可選的開(kāi)區(qū)間(小于或大于)。
舉個(gè)樣例:
?
返回全部符合條件1 < score <= 5的成員;
?
返回全部符合條件5 < score < 10的成員。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為被結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZREVRANGEBYSCORE
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
返回有序集key中,score值介于max和min之間(默認(rèn)包含等于max或min)的全部的成員。有序集成員按score值遞減(從大到小)的次序排列。
具有同樣score值的成員按字典序的反序(reverse lexicographical order)排列。
除了成員按score值遞減的次序排列這一點(diǎn)外,ZREVRANGEBYSCORE命令的其它方面和ZRANGEBYSCORE命令一樣。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZRANK
ZRANK key member
返回有序集key中成員member的排名。當(dāng)中有序集成員按score值遞增(從小到大)順序排列。
排名以0為底,也就是說(shuō),score值最小的成員排名為0。
使用ZREVRANK命令能夠獲得成員按score值遞減(從大到小)排列的排名。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? 假設(shè)member是有序集key的成員,返回member的排名。
? ? 假設(shè)member不是有序集key的成員,返回nil。
?
ZREVRANK
ZREVRANK key member
返回有序集key中成員member的排名。當(dāng)中有序集成員按score值遞減(從大到小)排序。
排名以0為底,也就是說(shuō),score值最大的成員排名為0。
使用ZRANK命令能夠獲得成員按score值遞增(從小到大)排列的排名。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? 假設(shè)member是有序集key的成員,返回member的排名。
? ? 假設(shè)member不是有序集key的成員,返回nil。
?
?
ZREMRANGEBYRANK
ZREMRANGEBYRANK key start stop
移除有序集key中,指定排名(rank)區(qū)間內(nèi)的全部成員。
區(qū)間分別下面標(biāo)參數(shù)start和stop指出,包括start和stop在內(nèi)。
下標(biāo)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示有序集第一個(gè)成員,以1表示有序集第二個(gè)成員,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示最后一個(gè)成員,-2表示倒數(shù)第二個(gè)成員,以此類推。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為被移除成員的數(shù)量。
返回值:
? ? 被移除成員的數(shù)量。
?
?
ZREMRANGEBYSCORE
ZREMRANGEBYSCORE key min max
移除有序集key中,全部score值介于min和max之間(包含等于min或max)的成員。
自版本號(hào)2.1.6開(kāi)始,score值等于min或max的成員也能夠不包含在內(nèi),詳情請(qǐng)參見(jiàn)ZRANGEBYSCORE命令。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為被移除成員的數(shù)量。
返回值:
? ? 被移除成員的數(shù)量。
?
?
ZINTERSTORE
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
計(jì)算給定的一個(gè)或多個(gè)有序集的交集,當(dāng)中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該交集(結(jié)果集)儲(chǔ)存到destination。
默認(rèn)情況下,結(jié)果集中某個(gè)成員的score值是全部給定集下該成員score值之和。
關(guān)于WEIGHTS和AGGREGATE選項(xiàng)的描寫敘述,參見(jiàn)ZUNIONSTORE命令。
時(shí)間復(fù)雜度:
? ? O(N*K)+O(M*log(M)),N為給定key中基數(shù)最小的有序集,K為給定有序集的數(shù)量,M為結(jié)果集的基數(shù)。
返回值:
? ? 保存到destination的結(jié)果集的基數(shù)。
?
?
ZUNIONSTORE
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
計(jì)算給定的一個(gè)或多個(gè)有序集的并集,當(dāng)中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該并集(結(jié)果集)儲(chǔ)存到destination。
默認(rèn)情況下,結(jié)果集中某個(gè)成員的score值是全部給定集下該成員score值之和。
WEIGHTS
使用WEIGHTS選項(xiàng),你能夠?yàn)槊恳粋€(gè)給定有序集分別指定一個(gè)乘法因子(multiplication factor),每一個(gè)給定有序集的全部成員的score值在傳遞給聚合函數(shù)(aggregation function)之前都要先乘以該有序集的因子。
假設(shè)沒(méi)有指定WEIGHTS選項(xiàng),乘法因子默認(rèn)設(shè)置為1。
AGGREGATE
使用AGGREGATE選項(xiàng),你能夠指定并集的結(jié)果集的聚合方式。
默認(rèn)使用的參數(shù)SUM,能夠?qū)⑷考现心硞€(gè)成員的score值之和作為結(jié)果集中該成員的score值;使用參數(shù)MIN,能夠?qū)⑷考现心硞€(gè)成員的最小score值作為結(jié)果集中該成員的score值;而參數(shù)MAX則是將全部集合中某個(gè)成員的最大score值作為結(jié)果集中該成員的score值。
時(shí)間復(fù)雜度:
? ? O(N)+O(M log(M)),N為給定有序集基數(shù)的總和,M為結(jié)果集的基數(shù)。
返回值:
? ? 保存到destination的結(jié)果集的基數(shù)。
?
?
公布/訂閱(Pub/Sub)
PUBLISH
PUBLISH channel message
將信息 message 發(fā)送到指定的頻道 channel 。
時(shí)間復(fù)雜度:
? ? O(N+M),當(dāng)中 N 是頻道 channel 的訂閱者數(shù)量,而 M 則是使用模式訂閱(subscribed patterns)的client的數(shù)量。
返回值:
? ? 接收到信息 message 的訂閱者數(shù)量。
?
?
SUBSCRIBE
SUBSCRIBE channel [channel ...]
訂閱給定頻道的信息。
時(shí)間復(fù)雜度:
? ? O(N),當(dāng)中 N 是訂閱的頻道的數(shù)量。
返回值:
? ? 接收到的信息(請(qǐng)參見(jiàn)以下的代碼說(shuō)明)。
?
?
PSUBSCRIBE
PSUBSCRIBE pattern [pattern ...]
訂閱符合給定模式的頻道。
每一個(gè)模式以 * 作為匹配符,比方 huangz* 匹配全部以 huangz 開(kāi)頭的頻道( huangzmsg 、 huangz-blog 、 huangz.tweets 等等), news.* 匹配全部以 news. 開(kāi)頭的頻道(news.it 、 news.global.today 等等),諸如此類。
時(shí)間復(fù)雜度:
? ? O(N), N 是訂閱的模式的數(shù)量。
返回值:
? ? 接收到的信息(請(qǐng)參見(jiàn)以下的代碼說(shuō)明)。
?
?
UNSUBSCRIBE
? ? 警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
PUNSUBSCRIBE
? ? 警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
?
事務(wù)(Transaction)
WATCH
ATCH key [key ...]
監(jiān)視一個(gè)(或多個(gè)) key ,假設(shè)在事務(wù)運(yùn)行之前這個(gè)(或這些) key 被其它命令所修改,那么事務(wù)將被打斷。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
UNWATCH
UNWATCH
取消 WATCH 命令對(duì)全部 key 的監(jiān)視。
假設(shè)在運(yùn)行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被運(yùn)行了的話,那么就不須要再運(yùn)行 UNWATCH 了。
由于 EXEC 命令會(huì)運(yùn)行事務(wù),因此 WATCH 命令的效果已經(jīng)產(chǎn)生了;而 DISCARD 命令在取消事務(wù)的同一時(shí)候也會(huì)取消全部對(duì) key 的監(jiān)視,因此這兩個(gè)命令運(yùn)行之后,就沒(méi)有必要運(yùn)行 UNWATCH 了。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是 OK 。
?
MULTI
MULTI
標(biāo)記一個(gè)事務(wù)塊的開(kāi)始。
事務(wù)塊內(nèi)的多條命令會(huì)依照先后順序被放進(jìn)一個(gè)隊(duì)列其中,最后由 EXEC 命令在一個(gè)原子時(shí)間內(nèi)運(yùn)行。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
?
EXEC
EXEC
運(yùn)行全部事務(wù)塊內(nèi)的命令。
假如某個(gè)(或某些) key 正處于 WATCH 命令的監(jiān)視之下,且事務(wù)塊中有和這個(gè)(或這些) key 相關(guān)的命令,那么 EXEC 命令僅僅在這個(gè)(或這些) key 沒(méi)有被其它命令所修改的情況下運(yùn)行并生效,否則該事務(wù)被打斷(abort)。
時(shí)間復(fù)雜度:
? ? 事務(wù)塊內(nèi)全部命令的時(shí)間復(fù)雜度的總和。
返回值:
? ? 事務(wù)塊內(nèi)全部命令的返回值,按命令運(yùn)行的先后順序排列。
? ? 當(dāng)操作被打斷時(shí),返回空值 nil 。
?
?
DISCARD
DISCARD
取消事務(wù),放棄運(yùn)行事務(wù)塊內(nèi)的全部命令。
假設(shè)正在使用 WATCH 命令監(jiān)視某個(gè)(或某些) key ,那么取消全部監(jiān)視,等同于運(yùn)行命令 UNWATCH 。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
?
連接(Connection)
AUTH
AUTH password
通過(guò)設(shè)置配置文件里 requirepass 項(xiàng)的值(使用命令 CONFIG SET requirepass password ),能夠使用密碼來(lái)保護(hù) Redis server。
假設(shè)開(kāi)啟了password保護(hù)的話,在每次連接 Redis server之后,就要使用 AUTH 命令解鎖,解鎖之后才干使用其它 Redis 命令。
假設(shè) AUTH 命令給定的password password 和配置文件里的password相符的話,server會(huì)返回 OK 并開(kāi)始接受命令輸入。
反之,假設(shè)password不匹配的話,server將返回一個(gè)錯(cuò)誤,并要求client需又一次輸入password。
?
? ? 警告:由于 Redis 高性能的特點(diǎn),在非常短時(shí)間內(nèi)嘗試推測(cè)非常多個(gè)password是有可能的,因此請(qǐng)確保使用的password足夠復(fù)雜和足夠長(zhǎng),以免遭受password推測(cè)攻擊。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? password匹配時(shí)返回 OK ,否則返回一個(gè)錯(cuò)誤。
?
PING
PING
client向server發(fā)送一個(gè) PING ,然后server返回client一個(gè) PONG 。
通經(jīng)常使用于測(cè)試與server的連接是否仍然生效,或者用于測(cè)量延遲值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? PONG
?
?
SELECT
SELECT index
切換到指定的數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)索引號(hào)用數(shù)字值指定,以 0 作為起始索引值。
新的鏈接總是使用 0 號(hào)數(shù)據(jù)庫(kù)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? OK
?
ECHO
ECHO message
打印一個(gè)特定的信息 message ,測(cè)試時(shí)使用。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? message 自身。
?
?
QUIT
QUIT
請(qǐng)求server關(guān)閉與當(dāng)前client的連接。
一旦全部等待中的回復(fù)(假設(shè)有的話)順利寫入到client,連接就會(huì)被關(guān)閉。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK (可是不會(huì)被打印顯示,由于當(dāng)時(shí) Redis-cli 已經(jīng)退出)。
?
?
server(Server)
BGREWRITEAOF
BGREWRITEAOF
異步(Asynchronously)重寫 AOF 文件以反應(yīng)當(dāng)前數(shù)據(jù)庫(kù)的狀態(tài)。
即使 BGREWRITEAOF 命令運(yùn)行失敗,舊 AOF 文件里的數(shù)據(jù)也不會(huì)因此丟失或改變。
時(shí)間復(fù)雜度:
? ? O(N), N 為要追加到 AOF 文件里的數(shù)據(jù)數(shù)量。
返回值:
? ? 反饋信息。
?
BGSAVE
在后臺(tái)異步保存當(dāng)前數(shù)據(jù)庫(kù)的數(shù)據(jù)到磁盤。
BGSAVE 命令運(yùn)行之后馬上返回 OK ,然后 Redis fork出一個(gè)新子進(jìn)程,原來(lái)的 Redis 進(jìn)程(父進(jìn)程)繼續(xù)處理client請(qǐng)求,而子進(jìn)程則負(fù)責(zé)將數(shù)據(jù)保存到磁盤,然后退出。
client能夠通過(guò) LASTSAVE 命令查看相關(guān)信息,推斷 BGSAVE 命令是否運(yùn)行成功。
時(shí)間復(fù)雜度:
? ? O(N), N 為要保存到數(shù)據(jù)庫(kù)中的 key 的數(shù)量。
返回值:
? ? 反饋信息。
?
SAVE
SAVE
同步保存當(dāng)前數(shù)據(jù)庫(kù)的數(shù)據(jù)到磁盤。
時(shí)間復(fù)雜度:
? ? O(N), N 為要保存到數(shù)據(jù)庫(kù)中的 key 的數(shù)量。
返回值:
? ? 總是返回 OK 。
?
?
LASTSAVE
LASTSAVE
返回近期一次 Redis 成功運(yùn)行保存操作的時(shí)間點(diǎn)( SAVE 、 BGSAVE 等),以 UNIX 時(shí)間戳格式表示。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 一個(gè) UNIX 時(shí)間戳。
?
?
DBSIZE
DBSIZE
返回當(dāng)前數(shù)據(jù)庫(kù)的 key 的數(shù)量。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)前數(shù)據(jù)庫(kù)的 key 的數(shù)量。
?
?
SLAVEOF
SLAVEOF host port
SLAVEOF 命令用于在 Redis 執(zhí)行時(shí)動(dòng)態(tài)地改動(dòng)復(fù)制(replication)功能的行為。
通過(guò)運(yùn)行 SLAVEOF host port 命令,能夠?qū)?dāng)前server轉(zhuǎn)變?yōu)橹付╯erver的從屬server(slave server)。
假設(shè)當(dāng)前server已經(jīng)是某個(gè)主server(master server)的從屬server,那么運(yùn)行 SLAVEOF host port 將使當(dāng)前server停止對(duì)舊主server的同步,丟棄舊數(shù)據(jù)集,轉(zhuǎn)而開(kāi)始對(duì)新主server進(jìn)行同步。
另外,對(duì)一個(gè)從屬server運(yùn)行命令 SLAVEOF NO ONE 將使得這個(gè)從屬server關(guān)閉復(fù)制功能,并從從屬server轉(zhuǎn)變回主server,原來(lái)同步所得的數(shù)據(jù)集不會(huì)被丟棄。
利用“ SLAVEOF NO ONE 不會(huì)丟棄同步所得數(shù)據(jù)集”這個(gè)特性,能夠在主server失敗的時(shí)候,將從屬server用作新的主server,從而實(shí)現(xiàn)無(wú)間斷執(zhí)行。
時(shí)間復(fù)雜度:
? ? SLAVEOF host port ,O(N), N 為要同步的數(shù)據(jù)數(shù)量。
? ? SLAVEOF NO ONE , O(1) 。
返回值:
? ? 總是返回 OK 。
?
?
FLUSHALL
FLUSHALL
清空整個(gè) Redis server的數(shù)據(jù)(刪除全部數(shù)據(jù)庫(kù)的全部 key)。
此命令從不失敗。
時(shí)間復(fù)雜度:
? ? 尚未明白
返回值:
? ? 總是返回 OK 。
?
?
FLUSHDB
FLUSHDB
清空當(dāng)前數(shù)據(jù)庫(kù)中的全部 key 。
此命令從不失敗。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK 。
?
?
SHUTDOWN
SHUTDOWN
SHUTDOWN 命令運(yùn)行下面操作:
? ? 停止全部client
? ? 假設(shè)有最少一個(gè)保存點(diǎn)在等待,運(yùn)行 SAVE 命令
? ? 假設(shè) AOF 選項(xiàng)被打開(kāi),更新 AOF 文件
? ? server關(guān)閉
假設(shè)持久化被打開(kāi)的話, SHUTDOWN 命令會(huì)保證server正常關(guān)閉而不丟失不論什么數(shù)據(jù)。
假如僅僅是單純地運(yùn)行 SAVE 命令,然后再運(yùn)行 QUIT 命令,則沒(méi)有這一保證 —— 由于在運(yùn)行 SAVE 之后、運(yùn)行 QUIT 之前的這段時(shí)間中間,其它c(diǎn)lient可能正在和server進(jìn)行通訊,這時(shí)假設(shè)運(yùn)行 QUIT 就會(huì)造成數(shù)據(jù)丟失。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 運(yùn)行失敗時(shí)返回錯(cuò)誤。
? ? 運(yùn)行成功時(shí)不返回不論什么信息,server和client的連接斷開(kāi),client自己主動(dòng)退出。
?
?
SLOWLOG
SLOWLOG subcommand [argument]
什么是 SLOWLOG
Slow log 是 Redis 用來(lái)記錄查詢運(yùn)行時(shí)間的日志系統(tǒng)。
查詢運(yùn)行時(shí)間指的是不包含像client響應(yīng)(talking)、發(fā)送回復(fù)等 IO 操作,而單單是運(yùn)行一個(gè)查詢命令所耗費(fèi)的時(shí)間。
另外,slow log 保存在內(nèi)存里面,讀寫速度很快,因此你能夠放心地使用它,不必操心由于開(kāi)啟 slow log 而損害 Redis 的速度。
設(shè)置 SLOWLOG
Slow log 的行為由兩個(gè)配置參數(shù)(configuration parameter)指定,能夠通過(guò)改寫 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令對(duì)它們動(dòng)態(tài)地進(jìn)行改動(dòng)。
第一個(gè)選項(xiàng)是 slowlog-log-slower-then ,它決定要對(duì)運(yùn)行時(shí)間大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的查詢進(jìn)行記錄。
比方運(yùn)行下面命令將讓 slow log 記錄全部查詢時(shí)間大于等于 100 微秒的查詢:
CONFIG SET slowlog-log-slower-then 100 ,
而下面命令記錄全部查詢時(shí)間大于 1000 微秒的查詢:
CONFIG SET slowlog-log-slower-then 1000 。
還有一個(gè)選項(xiàng)是 slowlog-max-len ,它決定 slow log 最多能保存多少條日志, slow log 本身是一個(gè) LIFO 隊(duì)列,當(dāng)隊(duì)列大小超過(guò) slowlog-max-len 時(shí),最舊的一條日志將被刪除,而最新的一條日志增加到 slow log ,以此類推。
下面命令讓 slow log 最多保存 1000 條日志:
CONFIG SET slowlog-max-len 1000 。
使用 CONFIG GET 命令能夠查詢兩個(gè)選項(xiàng)的當(dāng)前值:
?
?
查看 slow log
要查看 slow log ,能夠使用 SLOWLOG GET 或者 SLOWLOG GET number 命令,前者打印全部 slow log ,最大長(zhǎng)度取決于 slowlog-max-len 選項(xiàng)的值,而 SLOWLOG GET number 則僅僅打印指定數(shù)量的日志。
最新的日志會(huì)最先被打印:
?
?
日志的唯一 id 僅僅有在 Redis server重新啟動(dòng)的時(shí)候才會(huì)重置,這樣能夠避免對(duì)日志的反復(fù)處理(比方你可能會(huì)想在每次發(fā)現(xiàn)新的慢查詢時(shí)發(fā)郵件通知你)。
查看當(dāng)前日志的數(shù)量
使用命令 SLOWLOG LEN 能夠查看當(dāng)前日志的數(shù)量。
請(qǐng)注意這個(gè)值和 slower-max-len 的差別,它們一個(gè)是當(dāng)前日志的數(shù)量,一個(gè)是同意記錄的最大日志的數(shù)量。
?
清空日志
使用命令 SLOWLOG RESET 能夠清空 slow log 。
?
?
時(shí)間復(fù)雜度:O(1)
返回值:取決于不同命令,返回不同的值。
?
INFO
INFO
返回關(guān)于 Redis server的各種信息和統(tǒng)計(jì)值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 詳細(xì)請(qǐng)參見(jiàn)以下的測(cè)試代碼。
?
?
CONFIG GET
CONFIG GET parameter
CONFIG GET 命令用于取得執(zhí)行中的 Redis server的配置參數(shù)(configuration parameters),只是并不是全部配置參數(shù)都被 CONFIG GET 命令所支持。
CONFIG GET 接受單個(gè)參數(shù) parameter 作為搜索keyword,查找全部匹配的配置參數(shù),當(dāng)中參數(shù)和值以“鍵-值對(duì)”(key-value pairs)的方式排列。
比方運(yùn)行 CONFIG GET s* 命令,server就會(huì)返回全部以 s 開(kāi)頭的配置參數(shù)及參數(shù)的值:
?
?
假設(shè)你僅僅是尋找特定的某個(gè)參數(shù)的話,你當(dāng)然也能夠直接指定參數(shù)的名字:
?
使用命令 CONFIG GET * ,能夠列出 CONFIG GET 命令支持的全部參數(shù):
?
全部被 CONFIG SET 所支持的配置參數(shù)都能夠在配置文件 redis.conf 中找到,只是 CONFIG GET 和 CONFIG SET 使用的格式和 redis.conf 文件所使用的格式有下面兩點(diǎn)不同:
? ? 10kb 、 2gb 這些在配置文件里所使用的儲(chǔ)存單位縮寫,不能夠用在 CONFIG 命令中, CONFIG SET 的值僅僅能通過(guò)數(shù)字值顯式地設(shè)定。
? ? ?
? ? 像 CONFIG SET xxx 1k 這種命令是錯(cuò)誤的,正確的格式是 CONFIG SET xxx 1000 。
? ? save 選項(xiàng)在 redis.conf 中是用多行文字儲(chǔ)存的,但在 CONFIG GET 命令中,它僅僅打印一行文字。
? ? ?
? ? 下面是 save 選項(xiàng)在 redis.conf 文件里的表示:
? ? ?
? ? save 900 1
? ? save 300 10
? ? save 60 10000
? ? ?
? ? 可是 CONFIG GET 命令的輸出僅僅有一行:
? ? ?
? ? redis> CONFIG GET save
? ? 1) "save"
? ? 2) "900 1 300 10 60 10000"
? ? ?
? ? 上面 save 參數(shù)的三個(gè)值表示:在 900 秒內(nèi)最少有 1 個(gè) key 被修改,或者 300 秒內(nèi)最少有 10 個(gè) key 被修改,又或者 60 秒內(nèi)最少有 1000 個(gè) key 被修改,以上三個(gè)條件隨便滿足一個(gè),就觸發(fā)一次保存操作。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 給定配置參數(shù)的值。
?
CONFIG SET
CONFIG SET parameter value
CONFIG SET 命令能夠動(dòng)態(tài)地調(diào)整 Redis server的配置(configuration)而無(wú)須重新啟動(dòng)。
你能夠使用它改動(dòng)配置參數(shù),或者改變 Redis 的持久化(Persistence)方式。
CONFIG SET 能夠改動(dòng)的配置參數(shù)能夠使用命令 CONFIG GET * 來(lái)列出,全部被 CONFIG SET 改動(dòng)的配置參數(shù)都會(huì)馬上生效。
關(guān)于 CONFIG SET 命令的很多其它消息,請(qǐng)參見(jiàn)命令 CONFIG GET 的說(shuō)明。
關(guān)于怎樣使用 CONFIG SET 命令改動(dòng) Redis 持久化方式,請(qǐng)參見(jiàn) Redis Persistence 。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 當(dāng)設(shè)置成功時(shí)返回 OK ,否則返回一個(gè)錯(cuò)誤。
?
CONFIG RESETSTAT
CONFIG RESETSTAT
重置 INFO 命令中的某些統(tǒng)計(jì)數(shù)據(jù),包含:
? ? Keyspace hits (鍵空間命中次數(shù))
? ? Keyspace misses (鍵空間不命中次數(shù))
? ? Number of commands processed (運(yùn)行命令的次數(shù))
? ? Number of connections received (連接server的次數(shù))
? ? Number of expired keys (過(guò)期key的數(shù)量)
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK 。
?
DEBUG OBJECT
DEBUG OBJECT key
返回給定 key 的調(diào)試信息。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng) key 存在時(shí),返回有關(guān)信息。
? ? 當(dāng) key 不存在時(shí),返回一個(gè)錯(cuò)誤。
?
DEBUG SEGFAULT
DEBUG SEGFAULT
令 Redis server崩潰,調(diào)試用。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 無(wú)
?
MONITOR
MONITOR
實(shí)時(shí)打印出 Redis server接收到的命令,調(diào)試用。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 總是返回 OK 。
?
SYNC
YNC
用于復(fù)制功能(replication)的內(nèi)部命令。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 不明白
非常實(shí)用;下面是redis官方提供的命令使用技巧:
下載地址例如以下:
https://github.com/owlient/phpredis(支持redis 2.0.4)
Redis::__construct構(gòu)造函數(shù)
$redis = new Redis();
connect, open 鏈接redis服務(wù)
參數(shù)
host: string,服務(wù)地址
port: int,端口號(hào)
timeout: float,鏈接時(shí)長(zhǎng) (可選, 默覺(jué)得 0 ,不限鏈接時(shí)間)
注: 在redis.conf中也有時(shí)間,默覺(jué)得300
pconnect, popen 不會(huì)主動(dòng)關(guān)閉的鏈接
參考上面
setOption 設(shè)置redis模式
getOption 查看redis設(shè)置的模式
ping 查看連接狀態(tài)
?
KEY相關(guān)操作
DEL
移除給定的一個(gè)或多個(gè)key。
假設(shè)key不存在,則忽略該命令。
時(shí)間復(fù)雜度:
? ? O(N),N為要移除的key的數(shù)量。
? ? 移除單個(gè)字符串類型的key,時(shí)間復(fù)雜度為O(1)。
? ? 移除單個(gè)列表、集合、有序集合或哈希表類型的key,時(shí)間復(fù)雜度為O(M),M為以上數(shù)據(jù)結(jié)構(gòu)內(nèi)的元素?cái)?shù)量。
返回值:
? ? 被移除key的數(shù)量。
?
//DEL
# 情況1: 刪除單個(gè)key
$redis->set('myname','ikodota');
echo $redis->get('myname').'<br>'; # 返回:ikodota
$redis->del('myname');# 返回 TRUE(1)
var_dump($redis->get('myname')); # 返回 bool(false)
# 情況2: 刪除一個(gè)不存在的key
if(!$redis->exists('fake_key')) # 不存在
var_dump($redis->del('fake_key')); # 返回 int(0)
# 情況3: 同一時(shí)候刪除多個(gè)key
$array_mset=array('first_key'=>'first_val',
? ? ? ? ? 'second_key'=>'second_val',
? ? ? ? ? 'third_key'=>'third_val');
$redis->mset($array_mset); #用MSET一次儲(chǔ)存多個(gè)值
$array_mget=array('first_key','second_key','third_key');
var_dump($redis->mget($array_mget)); #一次返回多個(gè)值 //array(3) { [0]=> string(9) "first_val" [1]=> string(10) "second_val" [2]=> string(9) "third_val" }
$redis->del($array_mget); #同一時(shí)候刪除多個(gè)key
var_dump($redis->mget($array_mget)); #返回 array(3) { [0]=> bool(false) [1]=> bool(false) [2]=> bool(false) }
?
KEYS
KEYS pattern?
查找符合給定模式的key。
KEYS *命中數(shù)據(jù)庫(kù)中全部key。
KEYS h?llo命中hello, hallo and hxllo等。
KEYS h*llo命中hllo和heeeeello等。
KEYS h[ae]llo命中hello和hallo,但不命中hillo。
特殊符號(hào)用"\"隔開(kāi)
時(shí)間復(fù)雜度:
? ? O(N),N為數(shù)據(jù)庫(kù)中key的數(shù)量。
返回值:
? ? 符合給定模式的key列表。
警告 :KEYS的速度很快,但在一個(gè)大的數(shù)據(jù)庫(kù)中使用它仍然可能造成性能問(wèn)題,假設(shè)你須要從一個(gè)數(shù)據(jù)集中查找特定的key,你不妨用集合(Set)。
?
//KEYS
#$redis->FLUSHALL();
$array_mset_keys=array('one'=>'1',
? ? ? ? ? 'two'=>'2',
? ? ? ? ? 'three '=>'3',
? ? ? ? ? 'four'=>'4');
$redis->mset($array_mset_keys); #用MSET一次儲(chǔ)存多個(gè)值
var_dump($redis->keys('*o*')); //array(3) { [0]=> string(4) "four" [1]=> string(3) "two" [2]=> string(3) "one" }
var_dump($redis->keys('t??')); //array(1) { [0]=> string(3) "two" }
var_dump($redis->keys('t[w]*')); //array(1) { [0]=> string(3) "two" }
print_r($redis->keys('*')); //Array ( [0] => four [1] => three [2] => two [3] => one )
?
RANDOMKEY
從當(dāng)前數(shù)據(jù)庫(kù)中隨機(jī)返回(不刪除)一個(gè)key。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)數(shù)據(jù)庫(kù)不為空時(shí),返回一個(gè)key。
? ? 當(dāng)數(shù)據(jù)庫(kù)為空時(shí),返回nil。
?
//RANDOMKEY
$redis->FLUSHALL();
# 情況1:數(shù)據(jù)庫(kù)不為空
$array_mset_randomkey=array('fruit'=>'apple',
? ? ? ? ? ? ? ? 'drink'=>'beer',
? ? ? ? ? ? ? ? 'food'=>'cookis');
$redis->mset($array_mset_randomkey);
echo $redis->randomkey();?
print_r($redis->keys('*')); # 查看數(shù)據(jù)庫(kù)內(nèi)全部key,證明RANDOMKEY并不刪除key//Array ( [0] => food [1] => drink [2] => fruit )
# 情況2:數(shù)據(jù)庫(kù)為空
$redis->flushdb(); ?# 刪除當(dāng)前數(shù)據(jù)庫(kù)全部key
var_dump($redis-> randomkey()); //bool(false)
?
TTL
TTL key
返回給定key的剩余生存時(shí)間(time to live)(以秒為單位)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? key的剩余生存時(shí)間(以秒為單位)。
? ? 當(dāng)key不存在或沒(méi)有設(shè)置生存時(shí)間時(shí),返回-1 。
//TTL
# 情況1:帶TTL的key
$redis->flushdb();
//$redis->set('name','ikodota'); # 設(shè)置一個(gè)key
$redis->expire('name',30); ?# 設(shè)置生存時(shí)間為30秒 //return (integer) 1
echo $redis->get('name'); //return ikodota
echo $redis->ttl('name'); //(integer) 25
//echo $redis->ttl('name'); ?# 30秒過(guò)去,name過(guò)期 //(integer) -1
var_dump($redis->get('name')); # 過(guò)期的key將被刪除 //return bool(false);
# 情況2:不帶TTL的key
$redis->set('site','wikipedia.org');//OK
var_dump($redis->ttl('site'));//int(-1)
# 情況3:不存在的key
$redis->EXISTS('not_exists_key');//int(0)
var_dump($redis->TTL('not_exists_key'));//int(-1)
EXISTS
EXISTS key
檢查給定key是否存在。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 若key存在,返回1,否則返回0。
//EXISTS
echo '<br>EXISTS<br>';
$redis->set('db',"redis"); //bool(true)?
var_dump($redis->exists('db')); ?# key存在 //bool(true)?
$redis->del('db'); ? # 刪除key //int(1)
var_dump($redis->exists('db')) ?# key不存在 //bool(false)
?
MOVE
MOVE key db
將當(dāng)前數(shù)據(jù)庫(kù)(默覺(jué)得0)的key移動(dòng)到給定的數(shù)據(jù)庫(kù)db其中。
假設(shè)當(dāng)前數(shù)據(jù)庫(kù)(源數(shù)據(jù)庫(kù))和給定數(shù)據(jù)庫(kù)(目標(biāo)數(shù)據(jù)庫(kù))有同樣名字的給定key,或者key不存在于當(dāng)前數(shù)據(jù)庫(kù),那么MOVE沒(méi)有不論什么效果。
因此,也能夠利用這一特性,將MOVE當(dāng)作鎖(locking)原語(yǔ)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 移動(dòng)成功返回1,失敗則返回0。
//MOVE
echo '<br><br>MOVE<br>';
# 情況1: key存在于當(dāng)前數(shù)據(jù)庫(kù)
$redis->SELECT(0); ?# redis默認(rèn)使用數(shù)據(jù)庫(kù)0,為了清晰起見(jiàn),這里再顯式指定一次。//OK
$redis->SET('song',"secret base - Zone"); //OK
var_dump ($redis->MOVE('song',1)); ?# 將song移動(dòng)到數(shù)據(jù)庫(kù)1 //bool(true)
# 情況2:當(dāng)key不存在的時(shí)候
$redis->SELECT(1);
var_dump ($redis->EXISTS('fake_key'));//bool(false);
var_dump($redis->MOVE('fake_key', 0)); ?# 試圖從數(shù)據(jù)庫(kù)1移動(dòng)一個(gè)不存在的key到數(shù)據(jù)庫(kù)0,失敗) //bool(false)
$redis->SELECT(0); # 使用數(shù)據(jù)庫(kù)0
var_dump($redis->EXISTS('fake_key')); ?# 證實(shí)fake_key不存在 //bool(false)
# 情況3:當(dāng)源數(shù)據(jù)庫(kù)和目標(biāo)數(shù)據(jù)庫(kù)有同樣的key時(shí)
$redis->SELECT(0); ?# 使用數(shù)據(jù)庫(kù)0
$redis->SET('favorite_fruit',"banana");
$redis->SELECT(1); ?# 使用數(shù)據(jù)庫(kù)1
$redis->SET('favorite_fruit',"apple");
$redis->SELECT(0); ?# 使用數(shù)據(jù)庫(kù)0,并試圖將favorite_fruit移動(dòng)到數(shù)據(jù)庫(kù)1
var_dump($redis->MOVE('favorite_fruit',1)); ?# 由于兩個(gè)數(shù)據(jù)庫(kù)有同樣的key,MOVE失敗 //return bool(false)
echo $redis->GET('favorite_fruit'); ?# 數(shù)據(jù)庫(kù)0的favorite_fruit沒(méi)變 //return banana
$redis->SELECT(1);
echo $redis->GET('favorite_fruit'); ? # 數(shù)據(jù)庫(kù)1的favorite_fruit也是 //return apple
?
RENAME?
RENAME key newkey
將key改名為newkey。
當(dāng)key和newkey同樣或者key不存在時(shí),返回一個(gè)錯(cuò)誤。
當(dāng)newkey已經(jīng)存在時(shí),RENAME命令將覆蓋舊值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 改名成功時(shí)提示OK,失敗時(shí)候返回一個(gè)錯(cuò)誤。
//RENAME
echo '<br><br>RENAME<br>';
# 情況1:key存在且newkey不存在
$redis->SET('message',"hello world");
var_dump($redis->RENAME('message','greeting')); ?//bool(true)
var_dump($redis->EXISTS('message')); ?# message不復(fù)存在 //bool(false)
var_dump($redis->EXISTS('greeting')); ? # greeting取而代之 //bool(true)
# 情況2:當(dāng)key不存在時(shí),返回錯(cuò)誤 ,php返回false;
var_dump($redis->RENAME('fake_key','never_exists')); ?//bool(false)
# 情況3:newkey已存在時(shí),RENAME會(huì)覆蓋舊newkey
$redis->SET('pc',"lenovo");
$redis->SET('personal_computer',"dell");?
var_dump($redis->RENAME('pc','personal_computer')); //bool(true)
var_dump($redis->GET('pc')); //(nil) ? bool(false)
var_dump($redis->GET('personal_computer')); ?# dell“沒(méi)有”了 //string(6) "lenovo"
?
RENAMENX?
RENAMENX key newkey
當(dāng)且僅當(dāng)newkey不存在時(shí),將key改為newkey。
出錯(cuò)的情況和RENAME一樣(key不存在時(shí)報(bào)錯(cuò))。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 改動(dòng)成功時(shí),返回1。
? ? 假設(shè)newkey已經(jīng)存在,返回0。
//RENAMENX
echo '<br><br>RENAMENX<br>';
# 情況1:newkey不存在,成功
$redis->SET('player',"MPlyaer");
$redis->EXISTS('best_player'); //int(0)
var_dump($redis->RENAMENX('player','best_player')); // bool(true)?
# 情況2:newkey存在時(shí),失敗
$redis->SET('animal',"bear");
$redis->SET('favorite_animal', "butterfly");
var_dump($redis->RENAMENX('animal', 'favorite_animal'));// bool(false)
var_dump($redis->get('animal')); //string(4) "bear"
var_dump($redis->get('favorite_animal')); //string(9) "butterfly"
TYPE
TYPE key
返回key所儲(chǔ)存的值的類型。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? none(key不存在) int(0)
? ? string(字符串) int(1)
? ? list(列表) int(3)
? ? set(集合) int(2)
? ? zset(有序集) int(4)
? ? hash(哈希表) int(5)
?
//TYPE
$redis->flushALL();
echo '<br><br>TYPE<br>';
var_dump($redis->TYPE('fake_key')); //none /int(0)
$redis->SET('weather',"sunny"); ?# 構(gòu)建一個(gè)字符串
var_dump($redis->TYPE('weather'));//string / int(1)
$redis->SADD('pat',"dog"); ?# 構(gòu)建一個(gè)集合
var_dump($redis->TYPE('pat')); //set /int(2)
$redis->LPUSH('book_list',"programming in scala"); ?# 構(gòu)建一個(gè)列表
var_dump($redis->TYPE('book_list'));//list / int(3)?
$redis->ZADD('pats',1,'cat'); ?# 構(gòu)建一個(gè)zset (sorted set) // int(1)
$redis->ZADD('pats',2,'dog');
$redis->ZADD('pats',3,'pig');
var_dump($redis->zRange('pats',0,-1)); // array(3) { [0]=> string(3) "cat" [1]=> string(3) "dog" [2]=> string(3) "pig" }
var_dump($redis->TYPE('pats')); //zset / int(4)
$redis->HSET('website','google','www.g.cn'); ? # 一個(gè)新域
var_dump($redis->HGET('website','google')); //string(8) "www.g.cn"
var_dump($redis->TYPE('website')); //hash /int(5)
EXPIRE
EXPIRE key seconds
為給定key設(shè)置生存時(shí)間。
當(dāng)key過(guò)期時(shí),它會(huì)被自己主動(dòng)刪除。
在Redis中,帶有生存時(shí)間的key被稱作“易失的”(volatile)。
?
在低于2.1.3版本號(hào)的Redis中,已存在的生存時(shí)間不可覆蓋。
從2.1.3版本號(hào)開(kāi)始,key的生存時(shí)間能夠被更新,也能夠被PERSIST命令移除。(詳情參見(jiàn) http://redis.io/topics/expire)。
?
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功返回1。
? ? 當(dāng)key不存在或者不能為key設(shè)置生存時(shí)間時(shí)(比方在低于2.1.3中你嘗試更新key的生存時(shí)間),返回0。
//EXPIRE
$redis->select(7);
//$redis->flushdb();
echo '<br><br>EXPIRE<br>';
$redis->SET('cache_page',"www.cnblogs.com/ikodota");
$redis->EXPIRE('cache_page', 30); ?# 設(shè)置30秒后過(guò)期
sleep(6);
echo $redis->TTL('cache_page').'<br>'; ? # 查看給定key的剩余生存時(shí)間 //(integer) 24
$redis->EXPIRE('cache_page', 3000); ?# 更新生存時(shí)間,3000秒
sleep(4);
echo $redis->TTL('cache_page').'<br>'; ? //(integer) 2996
?
?
EXPIREAT?
EXPIREAT key timestamp
EXPIREAT的作用和EXPIRE一樣,都用于為key設(shè)置生存時(shí)間。
不同在于EXPIREAT命令接受的時(shí)間參數(shù)是UNIX時(shí)間戳(unix timestamp)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)生存時(shí)間設(shè)置成功,返回1。
? ? 當(dāng)key不存在或沒(méi)辦法設(shè)置生存時(shí)間,返回0。
?
//EXPIREAT
echo '<br><br>EXPIREAT<br>';
$redis->SET('cache','www.google.com');
echo $redis->EXPIREAT('cache','1355292000'); # 這個(gè)key將在2012.12.12過(guò)期
echo ($redis->TTL('cache')); //return 124345085
?
OBJECT?
OBJECT subcommand [arguments [arguments]]
OBJECT命令同意從內(nèi)部察看給定key的Redis對(duì)象。
它通經(jīng)常使用在除錯(cuò)(debugging)或者了解為了節(jié)省空間而對(duì)key使用特殊編碼的情況。
當(dāng)將Redis用作緩存程序時(shí),你也能夠通過(guò)OBJECT命令中的信息,決定key的驅(qū)趕策略(eviction policies)。
OBJECT命令有多個(gè)子命令:
? ? OBJECT REFCOUNT <key>返回給定key引用所儲(chǔ)存的值的次數(shù)。此命令主要用于除錯(cuò)。
? ? OBJECT ENCODING <key>返回給定key鎖儲(chǔ)存的值所使用的內(nèi)部表示(representation)。
? ? OBJECT IDLETIME <key>返回給定key自儲(chǔ)存以來(lái)的空轉(zhuǎn)時(shí)間(idle, 沒(méi)有被讀取也沒(méi)有被寫入),以秒為單位。
對(duì)象能夠以多種方式編碼:
? ? 字符串能夠被編碼為raw(一般字符串)或int(用字符串表示64位數(shù)字是為了節(jié)約空間)。
? ? 列表能夠被編碼為ziplist或linkedlist。ziplist是為節(jié)約大小較小的列表空間而作的特殊表示。
? ? 集合能夠被編碼為intset或者h(yuǎn)ashtable。intset是僅僅儲(chǔ)存數(shù)字的小集合的特殊表示。
? ? 哈希表能夠編碼為zipmap或者h(yuǎn)ashtable。zipmap是小哈希表的特殊表示。
? ? 有序集合能夠被編碼為ziplist或者skiplist格式。ziplist用于表示小的有序集合,而skiplist則用于表示不論什么大小的有序集合。
假如你做了什么讓Redis沒(méi)辦法再使用節(jié)省空間的編碼時(shí)(比方將一個(gè)僅僅有1個(gè)元素的集合擴(kuò)展為一個(gè)有100萬(wàn)個(gè)元素的集合),特殊編碼類型(specially encoded types)會(huì)自己主動(dòng)轉(zhuǎn)換成通用類型(general type)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? REFCOUNT和IDLETIME返回?cái)?shù)字。
? ? ENCODING返回對(duì)應(yīng)的編碼類型。
//OBJECT
$redis->select(8);
echo '<br><br>OBJECT<br>';
$redis->SET('game',"WOW"); ?# 設(shè)置一個(gè)字符串
$redis->OBJECT('REFCOUNT','game'); ?# 僅僅有一個(gè)引用
//sleep(5);
echo $redis->OBJECT('IDLETIME','game'); ?# 等待一陣。。。然后查看空轉(zhuǎn)時(shí)間 //(integer) 10
//echo $redis->GET('game'); ?# 提取game, 讓它處于活躍(active)狀態(tài) ?//return WOW
//echo $redis->OBJECT('IDLETIME','game'); ?# 不再處于空轉(zhuǎn) //(integer) 0
var_dump($redis->OBJECT('ENCODING','game')); ?# 字符串的編碼方式 //string(3) "raw"
$redis->SET('phone',15820123123); ?# 大的數(shù)字也被編碼為字符串
var_dump($redis->OBJECT('ENCODING','phone')); //string(3) "raw"
$redis->SET('age',20); ?# 短數(shù)字被編碼為int
var_dump($redis->OBJECT('ENCODING','age')); //string(3) "int"
?
PERSIST?
PERSIST key
?
移除給定key的生存時(shí)間。
?
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)生存時(shí)間移除成功時(shí),返回1.
? ? 假設(shè)key不存在或key沒(méi)有設(shè)置生存時(shí)間,返回0。
?
//PERSIST
echo '<br><br>PERSIST<br>';
$redis->SET('time_to_say_goodbye',"886...");
$redis->EXPIRE('time_to_say_goodbye', 300);
sleep(3);
echo $redis->TTL('time_to_say_goodbye'); # (int) 297
echo '<br>';
$redis->PERSIST('time_to_say_goodbye'); ?# 移除生存時(shí)間
echo $redis->TTL('time_to_say_goodbye'); ?# 移除成功 ?//int(-1)
SORT
?
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]
排序,分頁(yè)等
參數(shù)
array(
‘by’ => ‘some_pattern_*’,
‘limit’ => array(0, 1),
‘get’ => ‘some_other_pattern_*’ or an array of patterns,
‘sort’ => ‘a(chǎn)sc’ or ‘desc’,
‘a(chǎn)lpha’ => TRUE,
‘store’ => ‘external-key’
)
返回或保存給定列表、集合、有序集合key中經(jīng)過(guò)排序的元素。
排序默認(rèn)以數(shù)字作為對(duì)象,值被解釋為雙精度浮點(diǎn)數(shù),然后進(jìn)行比較。
?
一般SORT使用方法
最簡(jiǎn)單的SORT用法是SORT key。
如果today_cost是一個(gè)保存數(shù)字的列表,SORT命令默認(rèn)會(huì)返回該列表值的遞增(從小到大)排序結(jié)果。
?
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('today_cost', 30);
$redis->LPUSH('today_cost', 1.5);
$redis->LPUSH('today_cost', 10);
$redis->LPUSH('today_cost', 8);
# 排序
var_dump($redis->SORT('today_cost')); //array(4) { [0]=> string(3) "1.5" [1]=> string(1) "8" [2]=> string(2) "10" [3]=> string(2) "30" }
當(dāng)數(shù)據(jù)集中保存的是字符串值時(shí),你能夠用ALPHA修飾符(modifier)進(jìn)行排序。
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('website', "www.reddit.com");
$redis->LPUSH('website', "www.slashdot.com");
$redis->LPUSH('website', "www.infoq.com");
# 默認(rèn)排序
var_dump($redis->SORT('website'));//array(3) { [0]=> string(13) "www.infoq.com" [1]=> string(16) "www.slashdot.com" [2]=> string(14) "www.reddit.com" }
# 按字符排序 ALPHA=true
var_dump($redis->SORT('website', array('ALPHA'=>TRUE))); //array(3) { [0]=> string(13) "www.infoq.com" [1]=> string(14) "www.reddit.com" [2]=> string(16) "www.slashdot.com" }
假設(shè)你正確設(shè)置了!LC_COLLATE環(huán)境變量的話,Redis能識(shí)別UTF-8編碼。
排序之后返回的元素?cái)?shù)量能夠通過(guò)LIMIT修飾符進(jìn)行限制。
LIMIT修飾符接受兩個(gè)參數(shù):offset和count。
offset指定要跳過(guò)的元素?cái)?shù)量,count指定跳過(guò)offset個(gè)指定的元素之后,要返回多少個(gè)對(duì)象。
下面樣例返回排序結(jié)果的前5個(gè)對(duì)象(offset為0表示沒(méi)有元素被跳過(guò))。
# 將數(shù)據(jù)一一增加到列表中
$redis->LPUSH('rank', 30); //(integer) 1
$redis->LPUSH('rank', 56); //(integer) 2
$redis->LPUSH('rank', 42); //(integer) 3
$redis->LPUSH('rank', 22); //(integer) 4
$redis->LPUSH('rank', 0); ?//(integer) 5
$redis->LPUSH('rank', 11); //(integer) 6
$redis->LPUSH('rank', 32); //(integer) 7
$redis->LPUSH('rank', 67); //(integer) 8
$redis->LPUSH('rank', 50); //(integer) 9
$redis->LPUSH('rank', 44); //(integer) 10
$redis->LPUSH('rank', 55); //(integer) 11
# 排序
$redis_sort_option=array('LIMIT'=>array(0,5));
var_dump($redis->SORT('rank',$redis_sort_option)); ? # 返回排名前五的元素 // array(5) { [0]=> string(1) "0" [1]=> string(2) "11" [2]=> string(2) "22" [3]=> string(2) "30" [4]=> string(2) "32" }
修飾符能夠組合使用。下面樣例返回降序(從大到小)的前5個(gè)對(duì)象。
$redis_sort_option=array(
? ? ? ? ? ? 'LIMIT'=>array(0,5),
? ? ? ? ? ? 'SORT'=>'DESC'
? ? ? ? ? ? );
var_dump($redis->SORT('rank',$redis_sort_option)); //array(5) { [0]=> string(2) "67" [1]=> string(2) "56" [2]=> string(2) "55" [3]=> string(2) "50" [4]=> string(2) "44" }
?
使用外部key進(jìn)行排序
有時(shí)候你會(huì)希望使用外部的key作為權(quán)重來(lái)比較元素,取代默認(rèn)的對(duì)例如法。
如果如今實(shí)用戶(user)數(shù)據(jù)例如以下:
id ?name level
-------------------------------
1 admin ?9999
2 huangz 10
59230 jack ? ?3
222 hacker ? 9999
id數(shù)據(jù)保存在key名為user_id的列表中。
name數(shù)據(jù)保存在key名為user_name_{id}的列表中
level數(shù)據(jù)保存在user_level_{id}的key中。
# 先將要使用的數(shù)據(jù)增加到數(shù)據(jù)庫(kù)中
# admin
$redis->LPUSH('user_id', 1);//(integer) 1
$redis->SET('user_name_1', 'admin');
$redis->SET('user_level_1',9999);
# huangz
$redis->LPUSH('user_id', 2);//(integer) 2
$redis->SET('user_name_2', 'huangz');
$redis->SET('user_level_2', 10);
# jack
$redis->LPUSH('user_id', 59230);//(integer) 3
$redis->SET('user_name_59230','jack');
$redis->SET('user_level_59230', 3);
# hacker
$redis->LPUSH('user_id', 222); ?//(integer) 4
$redis->SET('user_name_222', 'hacker');
$redis->SET('user_level_222', 9999);
?
假設(shè)希望按level從大到小排序user_id,能夠使用下面命令:
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option)); //array(4) { [0]=> string(3) "222" [1]=> string(1) "1" [2]=> string(1) "2" [3]=> string(5) "59230" }
#---------------------------
#1) "222" ? ?# hacker
#2) "1" ? ? ?# admin
#3) "2" ? ? ?# huangz
#4) "59230" ?# jack
可是有時(shí)候僅僅是返回相應(yīng)的id沒(méi)有什么用,你可能更希望排序后返回id相應(yīng)的username,這樣更友好一點(diǎn),使用GET選項(xiàng)能夠做到這一點(diǎn):
?
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>'user_name_*'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id', $redis_sort_option)); //array(4) { [0]=> string(6) "hacker" [1]=> string(5) "admin" [2]=> string(6) "huangz" [3]=> string(4) "jack" }
#1) "hacker"
#2) "admin"
#3) "huangz"
#4) "jack"
能夠多次地、有序地使用GET操作來(lái)獲取很多其它外部key。
比方你不但希望獲取username,還希望連用戶的password也一并列出,能夠使用下面命令:
?
# 先加入一些測(cè)試數(shù)據(jù)
$redis->SET('user_password_222', "hey,im in");
$redis->SET('user_password_1', "a_long_long_password");
$redis->SET('user_password_2', "nobodyknows");
$redis->SET('user_password_59230', "jack201022");
# 獲取name和password
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('user_name_*','user_password_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(8) { [0]=> string(6) "hacker" [1]=> string(9) "hey,im in" [2]=> string(5) "admin" [3]=> string(20) "a_long_long_password" [4]=> string(6) "huangz" [5]=> string(11) "nobodyknows" [6]=> string(4) "jack" [7]=> string(10) "jack201022" }
#------------------------------------
#1) "hacker" ? ? ? # username
#2) "hey,im in" ? ?# password
#3) "jack"
#4) "jack201022"
#5) "huangz"
#6) "nobodyknows"
#7) "admin"
#8) "a_long_long_password"
# 注意GET操作是有序的,GET user_name_* GET user_password_* 和 GET user_password_* GET user_name_*返回的結(jié)果位置不同
?
# 獲取name和password 注意GET操作是有序的
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('user_password_*','user_name_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));// array(8) { [0]=> string(9) "hey,im in" [1]=> string(6) "hacker" [2]=> string(20) "a_long_long_password" [3]=> string(5) "admin" [4]=> string(11) "nobodyknows" [5]=> string(6) "huangz" [6]=> string(10) "jack201022" [7]=> string(4) "jack" }
GET另一個(gè)特殊的規(guī)則——"GET #",用于獲取被排序?qū)ο?我們這里的樣例是user_id)的當(dāng)前元素。
比方你希望user_id按level排序,還要列出id、name和password,能夠使用下面命令:
?
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('#','user_password_*','user_name_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(12) { [0]=> string(3) "222" [1]=> string(9) "hey,im in" [2]=> string(6) "hacker" [3]=> string(1) "1" [4]=> string(20) "a_long_long_password" [5]=> string(5) "admin" [6]=> string(1) "2" [7]=> string(11) "nobodyknows" [8]=> string(6) "huangz" [9]=> string(5) "59230" [10]=> string(10) "jack201022" [11]=> string(4) "jack" }
#--------------------------------------------------------------
#1) "222" ? ? ? ? ?# id
#2) "hacker" ? ? ? # name
#3) "hey,im in" ? ?# password
#4) "1"
#5) "admin"
#6) "a_long_long_password"
#7) "2"
#8) "huangz"
#9) "nobodyknows"
#10) "59230"
#11) "jack"
#12) "jack201022"
僅僅獲取對(duì)象而不排序
BY修飾符能夠?qū)⒁粋€(gè)不存在的key當(dāng)作權(quán)重,讓SORT跳過(guò)排序操作。
該方法用于你希望獲取外部對(duì)象而又不希望引起排序開(kāi)銷時(shí)使用。
?
# 確保fake_key不存在
$redis->EXISTS('fake_key');//(integer) 0
# 以fake_key作BY參數(shù),不排序,僅僅GET name 和 GET password
$redis_sort_option=array('BY'=>'fake_key',
? ? ? ? ? ? 'SORT'=>'DESC',
? ? ? ? ? ? 'GET'=>array('#','user_name_*','user_password_*')
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option));//array(12) { [0]=> string(3) "222" [1]=> string(6) "hacker" [2]=> string(9) "hey,im in" [3]=> string(5) "59230" [4]=> string(4) "jack" [5]=> string(10) "jack201022" [6]=> string(1) "2" [7]=> string(6) "huangz" [8]=> string(11) "nobodyknows" [9]=> string(1) "1" [10]=> string(5) "admin" [11]=> string(20) "a_long_long_password" }
#----------------------------------------------
#1) "222" ? ? ? ?# id
#2) "hacker" ? ? # user_name
#3) "hey,im in" ?# password
#4) "59230"
#5) "jack"
#6) "jack201022"
#7) "2"
#8) "huangz"
#9) "nobodyknows"
#10) "1"
#11) "admin"
#12) "a_long_long_password"
保存排序結(jié)果
默認(rèn)情況下,SORT操作僅僅是簡(jiǎn)單地返回排序結(jié)果,假設(shè)你希望保存排序結(jié)果,能夠給STORE選項(xiàng)指定一個(gè)key作為參數(shù),排序結(jié)果將以列表的形式被保存到這個(gè)key上。(若指定key已存在,則覆蓋。)
$redis->EXISTS('user_info_sorted_by_level'); ?# 確保指定key不存在 ? //(integer) 0
$redis_sort_option=array('BY'=>'user_level_*',
? ? ? ? ? ? 'GET'=>array('#','user_name_*','user_password_*'),
? ? ? ? ? ? 'STORE'=>'user_info_sorted_by_level'
? ? ? ? ? ? );
var_dump($redis->SORT('user_id',$redis_sort_option)); //int(12)
var_dump($redis->LRANGE('user_info_sorted_by_level', 0 ,11)); ?# 查看排序結(jié)果 ?//array(12) { [0]=> string(5) "59230" [1]=> string(4) "jack" [2]=> string(10) "jack201022" [3]=> string(1) "2" [4]=> string(6) "huangz" [5]=> string(11) "nobodyknows" [6]=> string(3) "222" [7]=> string(6) "hacker" [8]=> string(9) "hey,im in" [9]=> string(1) "1" [10]=> string(5) "admin" [11]=> string(20) "a_long_long_password" }
#-----------------------------------------------------------------
#1) "59230"
#2) "jack"
#3) "jack201022"
#4) "2"
#5) "huangz"
#6) "nobodyknows"
#7) "222"
#8) "hacker"
#9) "hey,im in"
#10) "1"
#11) "admin"
#12) "a_long_long_password"
一個(gè)有趣的使用方法是將SORT結(jié)果保存,用EXPIRE為結(jié)果集設(shè)置生存時(shí)間,這樣結(jié)果集就成了SORT操作的一個(gè)緩存。
這樣就不必頻繁地調(diào)用SORT操作了,僅僅有當(dāng)結(jié)果集過(guò)期時(shí),才須要再調(diào)用一次SORT操作。
有時(shí)候?yàn)榱苏_實(shí)現(xiàn)這一使用方法,你可能須要加鎖以避免多個(gè)client同一時(shí)候進(jìn)行緩存重建(也就是多個(gè)client,同一時(shí)間進(jìn)行SORT操作,并保存為結(jié)果集),詳細(xì)參見(jiàn)SETNX命令。
在GET和BY中使用哈希表
能夠使用哈希表特有的語(yǔ)法,在SORT命令中進(jìn)行GET和BY操作。
# 如果如今我們的用戶表新增了一個(gè)serial項(xiàng)來(lái)為作為每一個(gè)用戶的序列號(hào)
# 序列號(hào)以哈希表的形式保存在serial哈希域內(nèi)。
$redis_hash_testdata_array=array(1=>'23131283',
? ? ? ? ? ? ? ? 2=>'23810573',
? ? ? ? ? ? ? ? 222=>'502342349',
? ? ? ? ? ? ? ? 59230=>'2435829758'
? ? ? ? ? ? ? ? );
$redis->HMSET('serial',$redis_hash_testdata_array);
# 我們希望以比較serial中的大小來(lái)作為排序user_id的方式
$redis_sort_option=array('BY'=>'*->serial');
var_dump($redis->SORT('user_id', $redis_sort_option)); //array(4) { [0]=> string(3) "222" [1]=> string(5) "59230" [2]=> string(1) "2" [3]=> string(1) "1" }
#----------------------------------------
#1) "222"
#2) "59230"
#3) "2"
#4) "1"
?
符號(hào)"->"用于切割哈希表的keyword(key name)和索引域(hash field),格式為"key->field"。
除此之外,哈希表的BY和GET操作和上面介紹的其它數(shù)據(jù)結(jié)構(gòu)(列表、集合、有序集合)沒(méi)有什么不同。
時(shí)間復(fù)雜度:
? ? O(N+M*log(M)),N為要排序的列表或集合內(nèi)的元素?cái)?shù)量,M為要返回的元素?cái)?shù)量。
? ? 假設(shè)僅僅是使用SORT命令的GET選項(xiàng)獲取數(shù)據(jù)而沒(méi)有進(jìn)行排序,時(shí)間復(fù)雜度O(N)。
返回值:
? ? 沒(méi)有使用STORE參數(shù),返回列表形式的排序結(jié)果。
? ? 使用STORE參數(shù),返回排序結(jié)果的元素?cái)?shù)量。
?
字符串(String)
SET
SET key value
將字符串值value關(guān)聯(lián)到key。
假設(shè)key已經(jīng)持有其它值,SET就覆寫舊值,無(wú)視類型。
時(shí)間復(fù)雜度:O(1)返回值:總是返回OK(TRUE),由于SET不可能失敗。
# 情況1:對(duì)字符串類型的key進(jìn)行SET
$redis->SET('apple', 'www.apple.com');#OK ?//bool(true)
$redis->GET('apple');//"www.apple.com"
# 情況2:對(duì)非字符串類型的key進(jìn)行SET
$redis->LPUSH('greet_list', "hello"); ?# 建立一個(gè)列表 #(integer) 1 //int(1)
$redis->TYPE('greet_list');#list //int(3)
$redis->SET('greet_list', "yooooooooooooooooo"); ? # 覆蓋列表類型 #OK //bool(true)
$redis->TYPE('greet_list');#string //int(1)
?
SETNX
SETNX key value
將key的值設(shè)為value,當(dāng)且僅當(dāng)key不存在。
若給定的key已經(jīng)存在,則SETNX不做不論什么動(dòng)作。
SETNX是”SET if Not eXists”(假設(shè)不存在,則SET)的簡(jiǎn)寫。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功,返回1。
? ? 設(shè)置失敗,返回0。
//SETNX
echo '<br><br>SETNX<br>';
$redis->EXISTS('job'); ?# job不存在 //bool(false);
$redis->SETNX('job', "programmer"); ?# job設(shè)置成功 //bool(true)
$redis->SETNX('job', "code-farmer"); ?# job設(shè)置失敗 //bool(false)
echo $redis->GET('job'); ?# 沒(méi)有被覆蓋 //"programmer"
設(shè)計(jì)模式(Design pattern): 將SETNX用于加鎖(locking)
SETNX能夠用作加鎖原語(yǔ)(locking primitive)。比方說(shuō),要對(duì)keyword(key)foo加鎖,client能夠嘗試下面方式:
SETNX lock.foo <current Unix time + lock timeout + 1>
假設(shè)SETNX返回1,說(shuō)明client已經(jīng)獲得了鎖,key設(shè)置的unix時(shí)間則指定了鎖失效的時(shí)間。之后client能夠通過(guò)DEL lock.foo來(lái)釋放鎖。
假設(shè)SETNX返回0,說(shuō)明key已經(jīng)被其它c(diǎn)lient上鎖了。假設(shè)鎖是非堵塞(non blocking lock)的,我們能夠選擇返回調(diào)用,或者進(jìn)入一個(gè)重試循環(huán),直到成功獲得鎖或重試超時(shí)(timeout)。
處理死鎖(deadlock)
上面的鎖算法有一個(gè)問(wèn)題:假設(shè)由于client失敗、崩潰或其它原因?qū)е聸](méi)有辦法釋放鎖的話,怎么辦?
這樣的狀況能夠通過(guò)檢測(cè)發(fā)現(xiàn)——由于上鎖的key保存的是unix時(shí)間戳,假如key值的時(shí)間戳小于當(dāng)前的時(shí)間戳,表示鎖已經(jīng)不再有效。
可是,當(dāng)有多個(gè)client同一時(shí)候檢測(cè)一個(gè)鎖是否過(guò)期并嘗試釋放它的時(shí)候,我們不能簡(jiǎn)單粗暴地刪除死鎖的key,再用SETNX上鎖,由于這時(shí)競(jìng)爭(zhēng)條件(race condition)已經(jīng)形成了:
? ? C1和C2讀取lock.foo并檢查時(shí)間戳,SETNX都返回0,由于它已經(jīng)被C3鎖上了,但C3在上鎖之后就崩潰(crashed)了。
? ? C1向lock.foo發(fā)送DEL命令。
? ? C1向lock.foo發(fā)送SETNX并成功。
? ? C2向lock.foo發(fā)送DEL命令。
? ? C2向lock.foo發(fā)送SETNX并成功。
? ? 出錯(cuò):由于競(jìng)爭(zhēng)條件的關(guān)系,C1和C2兩個(gè)都獲得了鎖。
幸好,下面算法能夠避免以上問(wèn)題。來(lái)看看我們聰明的C4client怎么辦:
? ? C4向lock.foo發(fā)送SETNX命令。
? ? 由于崩潰掉的C3還鎖著lock.foo,所以Redis向C4返回0。
? ? C4向lock.foo發(fā)送GET命令,查看lock.foo的鎖是否過(guò)期。假設(shè)不,則休眠(sleep)一段時(shí)間,并在之后重試。
? ? 還有一方面,假設(shè)lock.foo內(nèi)的unix時(shí)間戳比當(dāng)前時(shí)間戳老,C4運(yùn)行下面命令:
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
? ? 由于GETSET的作用,C4能夠檢查看GETSET的返回值,確定lock.foo之前儲(chǔ)存的舊值仍是那個(gè)過(guò)期時(shí)間戳,假設(shè)是的話,那么C4獲得鎖。
? ? 假設(shè)其它c(diǎn)lient,比方C5,比C4更快地運(yùn)行了GETSET操作并獲得鎖,那么C4的GETSET操作返回的就是一個(gè)未過(guò)期的時(shí)間戳(C5設(shè)置的時(shí)間戳)。C4僅僅好從第一步開(kāi)始重試。
注意,即便C4的GETSET操作對(duì)key進(jìn)行了改動(dòng),這對(duì)未來(lái)也沒(méi)什么影響。
(這里是不是有點(diǎn)問(wèn)題?C4的確是能夠重試,但C5怎么辦?它的鎖的過(guò)期被C4改動(dòng)了。——譯注)
? ? ?警告
? ? 為了讓這個(gè)加鎖算法更健壯,獲得鎖的client應(yīng)該經(jīng)常檢查過(guò)期時(shí)間以免鎖因諸如DEL等命令的運(yùn)行而被意外解開(kāi),由于client失敗的情況很復(fù)雜,不不過(guò)崩潰這么簡(jiǎn)單,還可能是client由于某些操作被堵塞了相當(dāng)長(zhǎng)時(shí)間,緊接著DEL命令被嘗試運(yùn)行(但這時(shí)鎖卻在另外的client手上)。
?
SETEX
SETEX key seconds value
將值value關(guān)聯(lián)到key,并將key的生存時(shí)間設(shè)為seconds(以秒為單位)。
假設(shè)key 已經(jīng)存在,SETEX命令將覆寫舊值。
這個(gè)命令類似于下面兩個(gè)命令:
$redis->SET('key', 'value');
$redis->EXPIRE('key','seconds'); ?# 設(shè)置生存時(shí)間?
不同之處是,SETEX是一個(gè)原子性(atomic)操作,關(guān)聯(lián)值和設(shè)置生存時(shí)間兩個(gè)動(dòng)作會(huì)在同一時(shí)間內(nèi)完畢,該命令在Redis用作緩存時(shí),很有用。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功時(shí)返回OK。
? ? 當(dāng)seconds參數(shù)不合法時(shí),返回一個(gè)錯(cuò)誤。
# 情況1:key不存在
$redis->SETEX('cache_user_id', 60,10086);//bool(true)
echo $redis->GET('cache_user_id'); ?# 值 //"10086"
sleep(4);
echo $redis->TTL('cache_user_id'); ?# 剩余生存時(shí)間 //int(56)
# 情況2:key已經(jīng)存在,key被覆寫
$redis->SET('cd', "timeless"); //bool(true);
$redis->SETEX('cd', 3000,"goodbye my love"); //bool(true);
echo $redis->GET('cd');//"goodbye my love"
?
SETRANGE
SETRANGE key offset value
用value參數(shù)覆寫(Overwrite)給定key所儲(chǔ)存的字符串值,從偏移量offset開(kāi)始。
不存在的key當(dāng)作空白字符串處理。
SETRANGE命令會(huì)確保字符串足夠長(zhǎng)以便將value設(shè)置在指定的偏移量上,假設(shè)給定key原來(lái)儲(chǔ)存的字符串長(zhǎng)度比偏移量小(比方字符串僅僅有5個(gè)字符長(zhǎng),但你設(shè)置的offset是10),那么原字符和偏移量之間的空白將用零比特(zerobytes,"\x00")來(lái)填充。
注意你能使用的最大偏移量是2^29-1(536870911),由于Redis的字符串被限制在512兆(megabytes)內(nèi)。假設(shè)你須要使用比這更大的空間,你得使用多個(gè)key。
時(shí)間復(fù)雜度:
? ? 對(duì)小(small)的字符串,平攤復(fù)雜度O(1)。(關(guān)于什么字符串是”小”的,請(qǐng)參考APPEND命令)
? ? 否則為O(M),M為value參數(shù)的長(zhǎng)度。
返回值:
? ? 被SETRANGE改動(dòng)之后,字符串的長(zhǎng)度。
? ? ?警告
? ? ?當(dāng)生成一個(gè)非常長(zhǎng)的字符串時(shí),Redis須要分配內(nèi)存空 間,該操作有時(shí)候可能會(huì)造成server堵塞(block)。在2010年的Macbook Pro上,設(shè)置偏移量為536870911(512MB內(nèi)存分配),耗費(fèi)約300毫秒, 設(shè)置偏移量為134217728(128MB內(nèi)存分配),耗費(fèi)約80毫秒,設(shè)置偏移量33554432(32MB內(nèi)存分配),耗費(fèi)約30毫秒,設(shè)置偏移量 為8388608(8MB內(nèi)存分配),耗費(fèi)約8毫秒。 注意若首次內(nèi)存分配成功之后,再對(duì)同一個(gè)key調(diào)用SETRANGE操作,無(wú)須再又一次內(nèi)存。
模式
由于有了SETRANGE和GETRANGE命令,你能夠?qū)edis字符串用作具有O(1)隨機(jī)訪問(wèn)時(shí)間的線性數(shù)組。這在非常多真有用例中都是非常高速且高效的儲(chǔ)存方式。
# 情況1:對(duì)非空字符串進(jìn)行SETRANGE
$redis->SET('greeting', "hello world");
$redis->SETRANGE('greeting', 6, "Redis"); //int(11)
$redis->GET('greeting');//"hello Redis"
# 情況2:對(duì)空字符串/不存在的key進(jìn)行SETRANGE
$redis->EXISTS('empty_string');//bool(false)
$redis->SETRANGE('empty_string', 5 ,"Redis!"); ?# 對(duì)不存在的key使用SETRANGE //int(11)
var_dump($redis->GET('empty_string')); ?# 空白處被"\x00"填充 ?#"\x00\x00\x00\x00\x00Redis!" ? //return string(11) "Redis!"
MSET?
MSET key value [key value ...]
同一時(shí)候設(shè)置一個(gè)或多個(gè)key-value對(duì)。
當(dāng)發(fā)現(xiàn)同名的key存在時(shí),MSET會(huì)用新值覆蓋舊值,假設(shè)你不希望覆蓋同名key,請(qǐng)使用MSETNX命令。
MSET是一個(gè)原子性(atomic)操作,全部給定key都在同一時(shí)間內(nèi)被設(shè)置,某些給定key被更新而還有一些給定key沒(méi)有改變的情況,不可能發(fā)生。
時(shí)間復(fù)雜度:
? ? O(N),N為要設(shè)置的key數(shù)量。
返回值:
? ? 總是返回OK(由于MSET不可能失敗)
#MSET
echo '<br><br>MSET<br>';
$redis->select(0);
$redis->flushdb();
$array_mset=array('date'=>'2012.3.5',
? ? ? ? 'time'=>'9.09a.m.',
? ? ? ? 'weather'=>'sunny'
? ? ? ? );
$redis->MSET($array_mset); //bool(true)
var_dump($redis->KEYS('*')); ? # 確保指定的三個(gè)key-value對(duì)被插入 //array(3) { [0]=> string(4) "time" [1]=> string(7) "weather" [2]=> string(4) "date" }
# MSET覆蓋舊值的樣例 可是經(jīng)過(guò)測(cè)試覆蓋不了
var_dump($redis->SET('google', "google.cn")); ? //bool(true)
var_dump($redis->MSET('google',"google.hk")); //bool(false)
echo $redis->GET('google'); //google.cn ?與redis手冊(cè)的演示樣例結(jié)果不符
?
MSETNX
MSETNX key value [key value ...]
同一時(shí)候設(shè)置一個(gè)或多個(gè)key-value對(duì),當(dāng)且僅當(dāng)key不存在。
即使僅僅有一個(gè)key已存在,MSETNX也會(huì)拒絕全部傳入key的設(shè)置操作
MSETNX是原子性的,因此它能夠用作設(shè)置多個(gè)不同key表示不同字段(field)的唯一性邏輯對(duì)象(unique logic object),全部字段要么全被設(shè)置,要么全不被設(shè)置。
時(shí)間復(fù)雜度:
? ? O(N),N為要設(shè)置的key的數(shù)量。
返回值:
? ? 當(dāng)全部key都成功設(shè)置,返回1。
? ? 假設(shè)全部key都設(shè)置失敗(最少有一個(gè)key已經(jīng)存在),那么返回0。
# 情況1:對(duì)不存在的key進(jìn)行MSETNX
$array_mset=array('rmdbs'=>'MySQL',
? ? ? ? 'nosql'=>'MongoDB',
? ? ? ? 'key-value-store'=>'redis'
? ? ? ? );
$redis->MSETNX($array_mset);//bool(true)
# 情況2:對(duì)已存在的key進(jìn)行MSETNX
$array_mset=array('rmdbs'=>'Sqlite',
? ? ? ? 'language'=>'python'
? ? ? ? );
var_dump($redis->MSETNX($array_mset)); ?# rmdbs鍵已經(jīng)存在,操作失敗 //bool(false)
var_dump($redis->EXISTS('language')); ?# 由于操作是原子性的,language沒(méi)有被設(shè)置 ?bool(false)
echo $redis->GET('rmdbs'); ?# rmdbs沒(méi)有被改動(dòng) //"MySQL"
$array_mset_keys=array( 'rmdbs', 'nosql', 'key-value-store');
print_r($redis->MGET($array_mset_keys)); //Array ( [0] => MySQL [1] => MongoDB [2] => redis )
?
APPEND
APPEND key value
假設(shè)key已經(jīng)存在而且是一個(gè)字符串,APPEND命令將value追加到key原來(lái)的值之后。
假設(shè)key不存在,APPEND就簡(jiǎn)單地將給定key設(shè)為value,就像運(yùn)行SET key value一樣。
時(shí)間復(fù)雜度:
? ? 平攤復(fù)雜度O(1)
返回值:
? ? 追加value之后,key中字符串的長(zhǎng)度。
# 情況1:對(duì)不存在的key運(yùn)行APPEND
$redis->EXISTS('myphone'); ?# 確保myphone不存在 //bool(false)
$redis->APPEND('myphone',"nokia"); ?# 對(duì)不存在的key進(jìn)行APPEND,等同于SET myphone "nokia" //int(5) # 字符長(zhǎng)度
# 情況2:對(duì)字符串進(jìn)行APPEND
$redis->APPEND('myphone', " - 1110");# 長(zhǎng)度從5個(gè)字符添加到12個(gè)字符 //int(12)
echo $redis->GET('myphone'); ?# 查看整個(gè)字符串 //"nokia - 1110"
GET
GET key
返回key所關(guān)聯(lián)的字符串值。
假設(shè)key不存在則返回特殊值nil。
假如key儲(chǔ)存的值不是字符串類型,返回一個(gè)錯(cuò)誤,由于GET僅僅能用于處理字符串值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? key的值。
? ? 假設(shè)key不存在,返回nil。
?
//GET
var_dump($redis->GET('fake_key')); #(nil) //return bool(false)
$redis->SET('animate', "anohana"); //return bool(true)
var_dump($redis->GET('animate')); //return string(7) "anohana"
?
MGET
MGET key [key ...]
返回全部(一個(gè)或多個(gè))給定key的值。
假設(shè)某個(gè)指定key不存在,那么返回特殊值nil。因此,該命令永不失敗。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 一個(gè)包括全部給定key的值的列表。
//MGET
echo '<br><br>MGET<br>';
$redis_mget_data_array=array('name'=>'ikodota','blog'=>'cnblogs.com/ikodota');
$redis->MSET($redis_mget_data_array);#用MSET一次儲(chǔ)存多個(gè)值?
$redis_mget_key_array=array('name','blog');
var_dump($redis->MGET($redis_mget_key_array)); //array(2) { [0]=> string(7) "ikodota" [1]=> string(19) "cnblogs.com/ikodota" }
$redis->EXISTS('fake_key'); //bool(false)
$redis_mget_key_array=array('name','fake_key');
var_dump($redis->MGET($redis_mget_key_array)); ?# 當(dāng)MGET中有不存在key的情況 ? //array(2) { [0]=> string(7) "ikodota" [1]=> bool(false) }
GETRANGE
GETRANGE key start end
返回key中字符串值的子字符串,字符串的截取范圍由start和end兩個(gè)偏移量決定(包含start和end在內(nèi))。
負(fù)數(shù)偏移量表示從字符串最后開(kāi)始計(jì)數(shù),-1表示最后一個(gè)字符,-2表示倒數(shù)第二個(gè),以此類推。
GETRANGE通過(guò)保證子字符串的值域(range)不超過(guò)實(shí)際字符串的值域來(lái)處理超出范圍的值域請(qǐng)求。
時(shí)間復(fù)雜度:
? ? O(N),N為要返回的字符串的長(zhǎng)度。
? ? 復(fù)雜度終于由返回值長(zhǎng)度決定,但由于從已有字符串中建立子字符串的操作很便宜(cheap),所以對(duì)于長(zhǎng)度不大的字符串,該操作的復(fù)雜度也可看作O(1)。
返回值:
? ? 截取得出的子字符串。
? ? 注解:在<=2.0的版本號(hào)里,GETRANGE被叫作SUBSTR。
//GETRANGE
echo '<br><br>GETRANGE<br>';
$redis->SET('greeting', "hello, my friend");
echo $redis->GETRANGE('greeting', 0, 4).'<br>'; ?# 返回索引0-4的字符,包含4。 //"hello"
echo $redis->GETRANGE('greeting', -1 ,-5).'<br>'; ?# 不支持回繞操作 ?//""
echo $redis->GETRANGE('greeting', -3 ,-1).'<br>'; ?# 負(fù)數(shù)索引 //"end"
echo $redis->GETRANGE('greeting', 0, -1).'<br>'; ?# 從第一個(gè)到最后一個(gè) //"hello, my friend"
echo $redis->GETRANGE('greeting', 0, 1008611).'<br>'; ?# 值域范圍不超過(guò)實(shí)際字符串,超過(guò)部分自己主動(dòng)被符略 //"hello, my friend"
?
GETSET
GETSET key value
將給定key的值設(shè)為value,并返回key的舊值。
當(dāng)key存在但不是字符串類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 返回給定key的舊值(old value)。
? ? 當(dāng)key沒(méi)有舊值時(shí),返回nil。
//GETSET
echo '<br><br>GETSET<br>';
var_dump($redis->EXISTS('mail'));//return bool(false);
var_dump($redis->GETSET('mail','xxx@google.com')); ?# 由于mail之前不存在,沒(méi)有舊值,返回nil ,#(nil) ? //bool(false)
var_dump($redis->GETSET('mail','xxx@yahoo.com')); ?# mail被更新,舊值被返回 //string(14) "xxx@google.com"
設(shè)計(jì)模式
GETSET能夠和INCR組合使用,實(shí)現(xiàn)一個(gè)有原子性(atomic)復(fù)位操作的計(jì)數(shù)器(counter)。
舉例來(lái)說(shuō),每次當(dāng)某個(gè)事件發(fā)生時(shí),進(jìn)程可能對(duì)一個(gè)名為mycount的key調(diào)用INCR操作,通常我們還要在一個(gè)原子時(shí)間內(nèi)同一時(shí)候完畢獲得計(jì)數(shù)器的值和將計(jì)數(shù)器值復(fù)位為0兩個(gè)操作。
能夠用命令GETSET mycounter 0來(lái)實(shí)現(xiàn)這一目標(biāo)。
$redis->SELECT(2);
echo $redis->INCR('mycount').'<br>'; #(integer) 11
if($redis->GET('mycount')>19){
? ? echo $redis->GETSET('mycount', 0).'<br>'; ?# 一個(gè)原子內(nèi)完畢GET mycount和SET mycount 0操作 #"11"?
}
echo $redis->GET('mycount'); #"0"
?
STRLEN
STRLEN key
返回key所儲(chǔ)存的字符串值的長(zhǎng)度。
當(dāng)key儲(chǔ)存的不是字符串值時(shí),返回一個(gè)錯(cuò)誤。
復(fù)雜度:
? ? O(1)
返回值:
? ? 字符串值的長(zhǎng)度。
? ? 當(dāng) key不存在時(shí),返回0。
$redis->SET('mykey', "Hello world");
echo $redis->STRLEN('mykey'); //int(11)
echo $redis->STRLEN('nonexisting'); # 不存在的key長(zhǎng)度視為0 ?//int(0)
INCR
INCR key
將key中儲(chǔ)存的數(shù)字值增一。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行INCR操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行INCR命令之后key的值。
? ? 注解:這是一個(gè)針對(duì)字符串的操作,由于Redis沒(méi)有專用的整數(shù)類型,所以key內(nèi)儲(chǔ)存的字符串被解釋為十進(jìn)制64位有符號(hào)整數(shù)來(lái)運(yùn)行INCR操作。
$redis->SET('page_view', 20);
var_dump($redis->INCR('page_view')); //int(21)?
var_dump($redis->GET('page_view')); ? ?# 數(shù)字值在Redis中以字符串的形式保存 //string(2) "21
INCRBY
INCRBY key increment
將key所儲(chǔ)存的值加上增量increment。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行INCRBY命令。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 加上increment之后,key的值。
//INCRBY
echo '<br><br>INCRBY<br>';
# 情況1:key存在且是數(shù)字值
$redis->SET('rank', 50); ?# 設(shè)置rank為50
$redis->INCRBY('rank', 20); ?# 給rank加上20
var_dump($redis->GET('rank')); #"70" ? //string(2) "70"
# 情況2:key不存在
$redis->EXISTS('counter'); //bool(false)
$redis->INCRBY('counter'); #int 30 ?//bool(false)
var_dump($redis->GET('counter')); #30 //經(jīng)測(cè)試 與手冊(cè)上結(jié)果不一樣,不能直接從bool型轉(zhuǎn)為int型。 return bool(false)?
# 情況3:key不是數(shù)字值
$redis->SET('book', "long long ago...");
var_dump($redis->INCRBY('book', 200)); #(error) ERR value is not an integer or out of range ? // bool(false)
?
DECR
DECR key
將key中儲(chǔ)存的數(shù)字值減一。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行DECR操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行DECR命令之后key的值。
//DECR
$redis->SELECT(3);
$redis->flushdb();
echo '<br><br>DECR<br>';
# 情況1:對(duì)存在的數(shù)字值key進(jìn)行DECR
$redis->SET('failure_times', 10);
$redis->DECR('failure_times'); //int(9)
echo $redis->GET('failure_times').'<br>'; ?//string(1) "9"
# 情況2:對(duì)不存在的key值進(jìn)行DECR
$redis->EXISTS('count'); #(integer) 0 //bool(false)
$redis->DECR('count'); ?//int(-1)?
echo $redis->GET('count').'<br>'; //string(2) "-1"
# 情況3:對(duì)存在但不是數(shù)值的key進(jìn)行DECR
$redis->SET('company', 'YOUR_CODE_SUCKS.LLC');
var_dump($redis->DECR('company')); #(error) ERR value is not an integer or out of range ? //bool(false)
echo $redis->GET('company').'<br>'; //YOUR_CODE_SUCKS.LLC
?
DECRBY
DECRBY key decrement
將key所儲(chǔ)存的值減去減量decrement。
假設(shè)key不存在,以0為key的初始值,然后運(yùn)行DECRBY操作。
假設(shè)值包括錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
關(guān)于很多其它遞增(increment)/遞減(decrement)操作信息,參見(jiàn)INCR命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 減去decrement之后,key的值。
# 情況1:對(duì)存在的數(shù)值key進(jìn)行DECRBY
$redis->SET('count', 100);
var_dump($redis->DECRBY('count', 20)); //int(80)
var_dump($redis->GET('count')); ?//string(2) "80"
# 情況2:對(duì)不存在的key進(jìn)行DECRBY
$redis->EXISTS('pages');#(integer) 0 ?//bool(false)
var_dump($redis->DECRBY('pages', 10)); ?//int(-10)
var_dump($redis->GET('pages')); //string(3) "-10"
?
SETBIT
SETBIT key offset value
對(duì)key所儲(chǔ)存的字符串值,設(shè)置或清除指定偏移量上的位(bit)。
位的設(shè)置或清除取決于value參數(shù),能夠是0也能夠是1。
當(dāng)key不存在時(shí),自己主動(dòng)生成一個(gè)新的字符串值。
字符串會(huì)增長(zhǎng)(grown)以確保它能夠?qū)alue保存在指定的偏移量上。當(dāng)字符串值增長(zhǎng)時(shí),空白位置以0填充。
offset參數(shù)必須大于或等于0,小于2^32(bit映射被限制在512MB內(nèi))。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 指定偏移量原來(lái)儲(chǔ)存的位("0"或"1").
? ? 警告:對(duì)使用大的offset的SETBIT操作來(lái)說(shuō),內(nèi)存分配可能造成Redisserver被堵塞。詳細(xì)參考SETRANGE命令,warning(警告)部分。
//SETBIT
echo '<br><br>SETBIT<br>';
$bit_val=67;
echo decbin($bit_val).'<br>'; //1000011
var_dump($redis->SETBIT('bit',1,1));//int(0) ?空位上都是0
var_dump($redis->SETBIT('bit',2,0));//int(0)
var_dump($redis->SETBIT('bit',3,0));//int(0)
var_dump($redis->SETBIT('bit',4,0));//int(0)
var_dump($redis->SETBIT('bit',5,0));//int(0)
var_dump($redis->SETBIT('bit',6,1));//int(0)
var_dump($redis->SETBIT('bit',7,1));//int(0)
var_dump($redis->GET('bit')); //string(1) "C" ,二進(jìn)制為:1000011 ,ASCII:67
var_dump($redis->GETBIT('bit', 6 )); //int(1) ?取出第6位(從左到右)為“1”
var_dump($redis->SETBIT('bit',5,1));//int(0) ?把第5位的0改為1
var_dump($redis->SETBIT('bit',6,0));//int(1) ?把第6位的1改為0
var_dump($redis->GET('bit')); //string(1) "E ,二進(jìn)制為:1000101,ASCII:69l
GETBIT
GETBIT key offset
對(duì)key所儲(chǔ)存的字符串值,獲取指定偏移量上的位(bit)。
當(dāng)offset比字符串值的長(zhǎng)度大,或者key不存在時(shí),返回0。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 字符串值指定偏移量上的位(bit)。
#參見(jiàn)SETBIT的演示樣例
?
哈希表(Hash)
HSET
HSET key field value
將哈希表key中的域field的值設(shè)為value。
假設(shè)key不存在,一個(gè)新的哈希表被創(chuàng)建并進(jìn)行HSET操作。
假設(shè)域field已經(jīng)存在于哈希表中,舊值將被覆蓋。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)field是哈希表中的一個(gè)新建域,而且值設(shè)置成功,返回1。
? ? 假設(shè)哈希表中域field已經(jīng)存在且舊值已被新值覆蓋,返回0。
?
HSETNX
HSETNX key field value
將哈希表key中的域field的值設(shè)置為value,當(dāng)且僅當(dāng)域field不存在。
若域field已經(jīng)存在,該操作無(wú)效。
假設(shè)key不存在,一個(gè)新哈希表被創(chuàng)建并運(yùn)行HSETNX命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 設(shè)置成功,返回1。
? ? 假設(shè)給定域已經(jīng)存在且沒(méi)有操作被運(yùn)行,返回0。
?
HMSET
HMSET key field value [field value ...]
同一時(shí)候?qū)⒍鄠€(gè)field - value(域-值)對(duì)設(shè)置到哈希表key中。
此命令會(huì)覆蓋哈希表中已存在的域。
假設(shè)key不存在,一個(gè)空哈希表被創(chuàng)建并運(yùn)行HMSET操作。
時(shí)間復(fù)雜度:
? ? O(N),N為field - value對(duì)的數(shù)量。
返回值:
? ? 假設(shè)命令運(yùn)行成功,返回OK。
? ? 當(dāng)key不是哈希表(hash)類型時(shí),返回一個(gè)錯(cuò)誤。
?
?
HGET
HGET key field
返回哈希表key中給定域field的值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 給定域的值。
? ? 當(dāng)給定域不存在或是給定key不存在時(shí),返回nil。
?
HMGET
HMGET key field [field ...]
返回哈希表key中,一個(gè)或多個(gè)給定域的值。
假設(shè)給定的域不存在于哈希表,那么返回一個(gè)nil值。
由于不存在的key被當(dāng)作一個(gè)空哈希表來(lái)處理,所以對(duì)一個(gè)不存在的key進(jìn)行HMGET操作將返回一個(gè)僅僅帶有nil值的表。
時(shí)間復(fù)雜度:
? ? O(N),N為給定域的數(shù)量。
返回值:
? ? 一個(gè)包括多個(gè)給定域的關(guān)聯(lián)值的表,表值的排列順序和給定域參數(shù)的請(qǐng)求順序一樣。
?
?
HGETALL
HGETALL key
返回哈希表key中,全部的域和值。
在返回值里,緊跟每一個(gè)域名(field name)之后是域的值(value),所以返回值的長(zhǎng)度是哈希表大小的兩倍。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 以列表形式返回哈希表的域和域的值。 若key不存在,返回空列表。
?
?
HDEL
HDEL key field [field ...]
刪除哈希表key中的一個(gè)或多個(gè)指定域,不存在的域?qū)⒈缓雎浴?
時(shí)間復(fù)雜度:
? ? O(N),N為要?jiǎng)h除的域的數(shù)量。
返回值:
? ? 被成功移除的域的數(shù)量,不包含被忽略的域。
? ? 注解:在Redis2.4下面的版本號(hào)里,HDEL每次僅僅能刪除單個(gè)域,假設(shè)你須要在一個(gè)原子時(shí)間內(nèi)刪除多個(gè)域,請(qǐng)將命令包括在MULTI/ EXEC塊內(nèi)。
?
HLEN
HLEN key
返回哈希表key中域的數(shù)量。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 哈希表中域的數(shù)量。
? ? 當(dāng)key不存在時(shí),返回0。
?
HEXISTS
HEXISTS key field
查看哈希表key中,給定域field是否存在。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)哈希表含有給定域,返回1。
? ? 假設(shè)哈希表不含有給定域,或key不存在,返回0。
?
HINCRBY
HINCRBY key field increment
為哈希表key中的域field的值加上增量increment。
增量也能夠?yàn)樨?fù)數(shù),相當(dāng)于對(duì)給定域進(jìn)行減法操作。
假設(shè)key不存在,一個(gè)新的哈希表被創(chuàng)建并運(yùn)行HINCRBY命令。
假設(shè)域field不存在,那么在運(yùn)行命令前,域的值被初始化為0。
對(duì)一個(gè)儲(chǔ)存字符串值的域field運(yùn)行HINCRBY命令將造成一個(gè)錯(cuò)誤。
本操作的值限制在64位(bit)有符號(hào)數(shù)字表示之內(nèi)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行HINCRBY命令之后,哈希表key中域field的值。
?
HKEYS
HKEYS key
返回哈希表key中的全部域。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 一個(gè)包括哈希表中全部域的表。
? ? 當(dāng)key不存在時(shí),返回一個(gè)空表。
?
HVALS
HVALS key
返回哈希表key中的全部值。
時(shí)間復(fù)雜度:
? ? O(N),N為哈希表的大小。
返回值:
? ? 一個(gè)包括哈希表中全部值的表。
? ? 當(dāng)key不存在時(shí),返回一個(gè)空表。
?
表(List)
頭元素和尾元素
頭元素指的是列表左端/前端第一個(gè)元素,尾元素指的是列表右端/后端第一個(gè)元素。
舉個(gè)樣例,列表list包括三個(gè)元素:x, y, z,當(dāng)中x是頭元素,而z則是尾元素。
空列表
指不包括不論什么元素的列表,Redis將不存在的key也視為空列表。
?
LPUSH
LPUSH key value [value ...]
將一個(gè)或多個(gè)值value插入到列表key的表頭。
假設(shè)有多個(gè)value值,那么各個(gè)value值按從左到右的順序依次插入到表頭:比方對(duì)一個(gè)空列表(mylist)運(yùn)行LPUSH mylist a b c,則結(jié)果列表為c b a,等同于運(yùn)行運(yùn)行命令LPUSH mylist a、LPUSH mylist b、LPUSH mylist c。
假設(shè)key不存在,一個(gè)空列表會(huì)被創(chuàng)建并運(yùn)行LPUSH操作。
當(dāng)key存在但不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行LPUSH命令后,列表的長(zhǎng)度。
?
? ? 注解:在Redis 2.4版本號(hào)曾經(jīng)的LPUSH命令,都僅僅接受單個(gè)value值。
?
LPUSHX
LPUSHX key value
將值value插入到列表key的表頭,當(dāng)且僅當(dāng)key存在而且是一個(gè)列表。
和LPUSH命令相反,當(dāng)key不存在時(shí),LPUSHX命令什么也不做。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? LPUSHX命令運(yùn)行之后,表的長(zhǎng)度。
?
RPUSH
RPUSH key value [value ...]
將一個(gè)或多個(gè)值value插入到列表key的表尾。
假設(shè)有多個(gè)value值,那么各個(gè)value值按從左到右的順序依次插入到表尾:比方對(duì)一個(gè)空列表(mylist)運(yùn)行RPUSH mylist a b c,則結(jié)果列表為a b c,等同于運(yùn)行命令RPUSHmylist a、RPUSH mylist b、RPUSH mylist c。
假設(shè)key不存在,一個(gè)空列表會(huì)被創(chuàng)建并運(yùn)行RPUSH操作。
當(dāng)key存在但不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 運(yùn)行RPUSH操作后,表的長(zhǎng)度。
? ? 注解:在Redis 2.4版本號(hào)曾經(jīng)的RPUSH命令,都僅僅接受單個(gè)value值。
?
RPUSHX
RPUSHX key value
將值value插入到列表key的表尾,當(dāng)且僅當(dāng)key存在而且是一個(gè)列表。
和RPUSH命令相反,當(dāng)key不存在時(shí),RPUSHX命令什么也不做。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? RPUSHX命令運(yùn)行之后,表的長(zhǎng)度。
?
LPOP
LPOP key
移除并返回列表key的頭元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表的頭元素。
? ? 當(dāng)key不存在時(shí),返回nil。
?
RPOP
RPOP key
移除并返回列表key的尾元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表的尾元素。
? ? 當(dāng)key不存在時(shí),返回nil。
?
BLPOP
BLPOP key [key ...] timeout
BLPOP是列表的堵塞式(blocking)彈出原語(yǔ)。
它是LPOP命令的堵塞版本號(hào),當(dāng)給定列表內(nèi)沒(méi)有不論什么元素可供彈出的時(shí)候,連接將被BLPOP命令堵塞,直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止。
當(dāng)給定多個(gè)key參數(shù)時(shí),按參數(shù)key的先后順序依次檢查各個(gè)列表,彈出第一個(gè)非空列表的頭元素。
非堵塞行為
當(dāng)BLPOP被調(diào)用時(shí),假設(shè)給定key內(nèi)至少有一個(gè)非空列表,那么彈出遇到的第一個(gè)非空列表的頭元素,并和被彈出元素所屬的列表的名字一起,組成結(jié)果返回給調(diào)用者。
當(dāng)存在多個(gè)給定key時(shí),BLPOP按給定key參數(shù)排列的先后順序,依次檢查各個(gè)列表。
如果如今有job、 command和request三個(gè)列表,當(dāng)中job不存在,command和request都持有非空列表。考慮下面命令:
BLPOP job command request 0
BLPOP保證返回的元素來(lái)自command,由于它是按”查找job -> 查找command -> 查找request“這種順序,第一個(gè)找到的非空列表。
?
?
堵塞行為
假設(shè)全部給定key都不存在或包括空列表,那么BLPOP命令將堵塞連接,直到等待超時(shí),或有還有一個(gè)client對(duì)給定key的隨意一個(gè)運(yùn)行LPUSH或RPUSH命令為止。
超時(shí)參數(shù)timeout接受一個(gè)以秒為單位的數(shù)字作為值。超時(shí)參數(shù)設(shè)為0表示堵塞時(shí)間能夠無(wú)限期延長(zhǎng)(block indefinitely) 。
?
?
同樣的key被多個(gè)client同一時(shí)候堵塞
同樣的key能夠被多個(gè)client同一時(shí)候堵塞。
不同的client被放進(jìn)一個(gè)隊(duì)列中,按”先堵塞先服務(wù)”(first-BLPOP,first-served)的順序?yàn)閗ey運(yùn)行BLPOP命令。
在MULTI/EXEC事務(wù)中的BLPOP
BLPOP能夠用于流水線(pipline,批量地發(fā)送多個(gè)命令并讀入多個(gè)回復(fù)),但把它用在MULTI/EXEC塊其中沒(méi)有意義。由于這要求整個(gè)server被堵塞以保證塊運(yùn)行時(shí)的原子性,該行為阻止了其它c(diǎn)lient運(yùn)行LPUSH或RPUSH命令。
因此,一個(gè)被包裹在MULTI/EXEC塊內(nèi)的BLPOP命令,行為表現(xiàn)得就像LPOP一樣,對(duì)空列表返回nil,對(duì)非空列表彈出列表元素,不進(jìn)行不論什么堵塞操作。
?
?
時(shí)間復(fù)雜度:O(1)返回值:
假設(shè)列表為空,返回一個(gè)nil。
反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素所屬的key,第二個(gè)元素是被彈出元素的值。
?
?
BRPOP
BRPOP key [key ...] timeout
BRPOP是列表的堵塞式(blocking)彈出原語(yǔ)。
它是RPOP命令的堵塞版本號(hào),當(dāng)給定列表內(nèi)沒(méi)有不論什么元素可供彈出的時(shí)候,連接將被BRPOP命令堵塞,直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止。
當(dāng)給定多個(gè)key參數(shù)時(shí),按參數(shù)key的先后順序依次檢查各個(gè)列表,彈出第一個(gè)非空列表的尾部元素。
關(guān)于堵塞操作的很多其它信息,請(qǐng)查看BLPOP命令,BRPOP除了彈出元素的位置和BLPOP不同之外,其它表現(xiàn)一致。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假如在指定時(shí)間內(nèi)沒(méi)有不論什么元素被彈出,則返回一個(gè)nil和等待時(shí)長(zhǎng)。
? ? 反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素所屬的key,第二個(gè)元素是被彈出元素的值。
?
LLEN
LLEN key
返回列表key的長(zhǎng)度。
假設(shè)key不存在,則key被解釋為一個(gè)空列表,返回0.
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 列表key的長(zhǎng)度。
?
LRANGE
LRANGE key start stop
返回列表key中指定區(qū)間內(nèi)的元素,區(qū)間以偏移量start和stop指定。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
注意LRANGE命令和編程語(yǔ)言區(qū)間函數(shù)的差別
假如你有一個(gè)包括一百個(gè)元素的列表,對(duì)該列表運(yùn)行LRANGE list 0 10,結(jié)果是一個(gè)包括11個(gè)元素的列表,這表明stop下標(biāo)也在LRANGE命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語(yǔ)言的區(qū)間函數(shù)可能不一致,比方Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標(biāo)
超出范圍的下標(biāo)值不會(huì)引起錯(cuò)誤。
假設(shè)start下標(biāo)比列表的最大下標(biāo)end(LLEN list減去1)還要大,或者start > stop,LRANGE返回一個(gè)空列表。
假設(shè)stop下標(biāo)比end下標(biāo)還要大,Redis將stop的值設(shè)置為end。
時(shí)間復(fù)雜度:
? ? O(S+N),S為偏移量start,N為指定區(qū)間內(nèi)元素的數(shù)量。
返回值:
? ? 一個(gè)列表,包括指定區(qū)間內(nèi)的元素。
?
LREM
LREM key count value
依據(jù)參數(shù)count的值,移除列表中與參數(shù)value相等的元素。
count的值能夠是下面幾種:
? ? ? ? count > 0: 從表頭開(kāi)始向表尾搜索,移除與value相等的元素,數(shù)量為count。
? ? ? ? count < 0: 從表尾開(kāi)始向表頭搜索,移除與value相等的元素,數(shù)量為count的絕對(duì)值。
? ? ? ? count = 0: 移除表中全部與value相等的值。
時(shí)間復(fù)雜度:
? ? O(N),N為列表的長(zhǎng)度。
返回值:
? ? 被移除元素的數(shù)量。
? ? 由于不存在的key被視作空表(empty list),所以當(dāng)key不存在時(shí),LREM命令總是返回0。
?
LSET
LSET key index value
將列表key下標(biāo)為index的元素的值甚至為value。
很多其它信息請(qǐng)參考LINDEX操作。
當(dāng)index參數(shù)超出范圍,或?qū)σ粋€(gè)空列表(key不存在)進(jìn)行LSET時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? 對(duì)頭元素或尾元素進(jìn)行LSET操作,復(fù)雜度為O(1)。
? ? 其它情況下,為O(N),N為列表的長(zhǎng)度。
返回值:
? ? 操作成功返回ok,否則返回錯(cuò)誤信息
?
LTRIM
LTRIM key start stop
對(duì)一個(gè)列表進(jìn)行修剪(trim),就是說(shuō),讓列表僅僅保留指定區(qū)間內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除。
舉個(gè)樣例,運(yùn)行命令LTRIM list 0 2,表示僅僅保留列表list的前三個(gè)元素,其余元素所有刪除。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
當(dāng)key不是列表類型時(shí),返回一個(gè)錯(cuò)誤。
LTRIM命令通常和LPUSH命令或RPUSH命令配合使用,舉個(gè)樣例:
?
?
這個(gè)樣例模擬了一個(gè)日志程序,每次將最新日志newest_log放到log列表中,而且僅僅保留最新的100項(xiàng)。注意當(dāng)這樣使用LTRIM命令時(shí),時(shí)間復(fù)雜度是O(1),由于平均情況下,每次僅僅有一個(gè)元素被移除。
注意LTRIM命令和編程語(yǔ)言區(qū)間函數(shù)的差別
假如你有一個(gè)包括一百個(gè)元素的列表list,對(duì)該列表運(yùn)行LTRIM list 0 10,結(jié)果是一個(gè)包括11個(gè)元素的列表,這表明stop下標(biāo)也在LTRIM命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語(yǔ)言的區(qū)間函數(shù)可能不一致,比方Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標(biāo)
超出范圍的下標(biāo)值不會(huì)引起錯(cuò)誤。
假設(shè)start下標(biāo)比列表的最大下標(biāo)end(LLEN list減去1)還要大,或者start > stop,LTRIM返回一個(gè)空列表(由于LTRIM已經(jīng)將整個(gè)列表清空)。
假設(shè)stop下標(biāo)比end下標(biāo)還要大,Redis將stop的值設(shè)置為end。
時(shí)間復(fù)雜度:
? ? O(N),N為被移除的元素的數(shù)量。
返回值:
? ? 命令運(yùn)行成功時(shí),返回ok。
?
?
LINDEX
LINDEX key index
返回列表key中,下標(biāo)為index的元素。
下標(biāo)(index)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示列表的第一個(gè)元素,以1表示列表的第二個(gè)元素,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示列表的最后一個(gè)元素,-2表示列表的倒數(shù)第二個(gè)元素,以此類推。
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為到達(dá)下標(biāo)index過(guò)程中經(jīng)過(guò)的元素?cái)?shù)量。
? ? 因此,對(duì)列表的頭元素和尾元素運(yùn)行LINDEX命令,復(fù)雜度為O(1)。
返回值:
? ? 列表中下標(biāo)為index的元素。
? ? 假設(shè)index參數(shù)的值不在列表的區(qū)間范圍內(nèi)(out of range),返回nil。
?
LINSERT
LINSERT key BEFORE|AFTER pivot value
將值value插入到列表key其中,位于值pivot之前或之后。
當(dāng)pivot不存在于列表key時(shí),不運(yùn)行不論什么操作。
當(dāng)key不存在時(shí),key被視為空列表,不運(yùn)行不論什么操作。
假設(shè)key不是列表類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為尋找pivot過(guò)程中經(jīng)過(guò)的元素?cái)?shù)量。
返回值:
? ? 假設(shè)命令運(yùn)行成功,返回插入操作完畢之后,列表的長(zhǎng)度。
? ? 假設(shè)沒(méi)有找到pivot,返回-1。
? ? 假設(shè)key不存在或?yàn)榭樟斜恚祷?。
?
?
RPOPLPUSH
RPOPLPUSH source destination
命令RPOPLPUSH在一個(gè)原子時(shí)間內(nèi),運(yùn)行下面兩個(gè)動(dòng)作:
? ? ? ? 將列表source中的最后一個(gè)元素(尾元素)彈出,并返回給client。
? ? ? ? 將source彈出的元素插入到列表destination,作為destination列表的的頭元素。
舉個(gè)樣例,你有兩個(gè)列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,運(yùn)行RPOPLPUSH source destination之后,source列表包括元素a, b,destination列表包括元素c, x, y, z ,而且元素c被返回。
假設(shè)source不存在,值nil被返回,而且不運(yùn)行其它動(dòng)作。
假設(shè)source和destination同樣,則列表中的表尾元素被移動(dòng)到表頭,并返回該元素,能夠把這樣的特殊情況視作列表的旋轉(zhuǎn)(rotation)操作。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被彈出的元素。
?
設(shè)計(jì)模式: 一個(gè)安全的隊(duì)列
Redis的列表常常被用作隊(duì)列(queue),用于在不同程序之間有序地交換消息(message)。一個(gè)程序(稱之為生產(chǎn)者,producer)通過(guò)LPUSH命令將消息放入隊(duì)列中,而還有一個(gè)程序(稱之為消費(fèi)者,consumer)通過(guò)RPOP命令取出隊(duì)列中等待時(shí)間最長(zhǎng)的消息。
不幸的是,在這個(gè)過(guò)程中,一個(gè)消費(fèi)者可能在獲得一個(gè)消息之后崩潰,而未運(yùn)行完畢的消息也因此丟失。
使用RPOPLPUSH命令能夠解決問(wèn)題,由于它在返回一個(gè)消息之余,還將該消息加入到還有一個(gè)列表其中,另外的這個(gè)列表能夠用作消息的備份表:假如一切正常,當(dāng)消費(fèi)者完畢該消息的處理之后,能夠用LREM命令將該消息從備份表刪除。
還有一方面,助手(helper)程序能夠通過(guò)監(jiān)視備份表,將超過(guò)一定處理時(shí)限的消息又一次放入隊(duì)列中去(負(fù)責(zé)處理該消息的消費(fèi)者可能已經(jīng)崩潰),這樣就不會(huì)丟失不論什么消息了。
?
BRPOPLPUSH
BRPOPLPUSH source destination timeout
BRPOPLPUSH是RPOPLPUSH的堵塞版本號(hào),當(dāng)給定列表source不為空時(shí),BRPOPLPUSH的表現(xiàn)和RPOPLPUSH一樣。
當(dāng)列表source為空時(shí),BRPOPLPUSH命令將堵塞連接,直到等待超時(shí),或有還有一個(gè)client對(duì)source運(yùn)行LPUSH或RPUSH命令為止。
超時(shí)參數(shù)timeout接受一個(gè)以秒為單位的數(shù)字作為值。超時(shí)參數(shù)設(shè)為0表示堵塞時(shí)間能夠無(wú)限期延長(zhǎng)(block indefinitely) 。
很多其它相關(guān)信息,請(qǐng)參考RPOPLPUSH命令。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假如在指定時(shí)間內(nèi)沒(méi)有不論什么元素被彈出,則返回一個(gè)nil和等待時(shí)長(zhǎng)。
? ? 反之,返回一個(gè)含有兩個(gè)元素的列表,第一個(gè)元素是被彈出元素的值,第二個(gè)元素是等待時(shí)長(zhǎng)。
?
?
集合(Set)
?附錄,經(jīng)常使用集合運(yùn)算:
? ? ? ?A = {'a', 'b', 'c'}
? ? B = {'a', 'e', 'i', 'o', 'u'}
? ? inter(x, y): 交集,在集合x和集合y中都存在的元素。
? ? inter(A, B) = {'a'}
? ? union(x, y): 并集,在集合x中或集合y中的元素,假設(shè)一個(gè)元素在x和y中都出現(xiàn),那僅僅記錄一次就可以。
? ? union(A,B) = {'a', 'b', 'c', 'e', 'i', 'o', 'u'}
? ? diff(x, y): 差集,在集合x中而不在集合y中的元素。
? ? diff(A,B) = {'b', 'c'}
? ? card(x): 基數(shù),一個(gè)集合中元素的數(shù)量。
? ? card(A) = 3
? ? 空集: 基數(shù)為0的集合。
?
SADD
SADD key member [member ...]
將一個(gè)或多個(gè)member元素增加到集合key其中,已經(jīng)存在于集合的member元素將被忽略。
假如key不存在,則創(chuàng)建一個(gè)僅僅包括member元素作成員的集合。
當(dāng)key不是集合類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N是被加入的元素的數(shù)量。
返回值:
? ? 被加入到集合中的新元素的數(shù)量,不包含被忽略的元素。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),SADD僅僅接受單個(gè)member值。
?
?
SREM
SREM key member [member ...]
移除集合key中的一個(gè)或多個(gè)member元素,不存在的member元素會(huì)被忽略。
當(dāng)key不是集合類型,返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(N),N為給定member元素的數(shù)量。
返回值:
? ? 被成功移除的元素的數(shù)量,不包含被忽略的元素。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),SREM僅僅接受單個(gè)member值。
?
?
SMEMBERS
SMEMBERS key
返回集合key中的全部成員。
時(shí)間復(fù)雜度:
? ? O(N),N為集合的基數(shù)。
返回值:
? ? 集合中的全部成員。
?
?
SISMEMBER
SISMEMBER key member
推斷member元素是否是集合key的成員。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)member元素是集合的成員,返回1。
? ? 假設(shè)member元素不是集合的成員,或key不存在,返回0。
?
?
SCARD
SCARD key
返回集合key的基數(shù)(集合中元素的數(shù)量)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 集合的基數(shù)。
? ? 當(dāng)key不存在時(shí),返回0。
?
?
SMOVE
SMOVE source destination member
將member元素從source集合移動(dòng)到destination集合。
SMOVE是原子性操作。
假設(shè)source集合不存在或不包括指定的member元素,則SMOVE命令不運(yùn)行不論什么操作,僅返回0。否則,member元素從source集合中被移除,并加入到destination集合中去。
當(dāng)destination集合已經(jīng)包括member元素時(shí),SMOVE命令僅僅是簡(jiǎn)單地將source集合中的member元素刪除。
當(dāng)source或destination不是集合類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 假設(shè)member元素被成功移除,返回1。
? ? 假設(shè)member元素不是source集合的成員,而且沒(méi)有不論什么操作對(duì)destination集合運(yùn)行,那么返回0。
?
?
SPOP
SPOP key
移除并返回集合中的一個(gè)隨機(jī)元素。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被移除的隨機(jī)元素。
? ? 當(dāng)key不存在或key是空集時(shí),返回nil。
?
?
? ? 也能夠參考:假設(shè)僅僅想獲取一個(gè)隨機(jī)元素,但不想該元素從集合中被移除的話,能夠使用SRANDMEMBER命令。
?
SRANDMEMBER
SRANDMEMBER key
返回集合中的一個(gè)隨機(jī)元素。
該操作和SPOP相似,但SPOP將隨機(jī)元素從集合中移除并返回,而SRANDMEMBER則只返回隨機(jī)元素,而不正確集合進(jìn)行不論什么修改。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 被選中的隨機(jī)元素。 當(dāng)key不存在或key是空集時(shí),返回nil。
?
?
SINTER
SINTER key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的交集。
不存在的key被視為空集。
當(dāng)給定集合其中有一個(gè)空集時(shí),結(jié)果也為空集(依據(jù)集合運(yùn)算定律)。
時(shí)間復(fù)雜度:
? ? O(N * M),N為給定集合其中基數(shù)最小的集合,M為給定集合的個(gè)數(shù)。
返回值:
? ? 交集成員的列表。
?
?
SINTERSTORE
SINTERSTORE destination key [key ...]
此命令等同于SINTER,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination集合已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N * M),N為給定集合其中基數(shù)最小的集合,M為給定集合的個(gè)數(shù)。
返回值:
? ? 結(jié)果集中的成員數(shù)量。
?
?
SUNION
SUNION key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的并集。
不存在的key被視為空集。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 并集成員的列表。
?
?
SUNIONSTORE
SUNIONSTORE destination key [key ...]
此命令等同于SUNION,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 結(jié)果集中的元素?cái)?shù)量。
?
?
SDIFF
SDIFF key [key ...]
返回一個(gè)集合的所有成員,該集合是所有給定集合的差集 。
不存在的key被視為空集。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 交集成員的列表。
?
?
SDIFFSTORE
SDIFFSTORE destination key [key ...]
此命令等同于SDIFF,但它將結(jié)果保存到destination集合,而不是簡(jiǎn)單地返回結(jié)果集。
假設(shè)destination集合已經(jīng)存在,則將其覆蓋。
destination能夠是key本身。
時(shí)間復(fù)雜度:
? ? O(N),N是全部給定集合的成員數(shù)量之和。
返回值:
? ? 結(jié)果集中的元素?cái)?shù)量。
?
?
有序集(Sorted Set)
ZADD
?
ZADD key score member [[score member] [score member] ...]
將一個(gè)或多個(gè)member元素及其score值增加到有序集key其中。
假設(shè)某個(gè)member已經(jīng)是有序集的成員,那么更新這個(gè)member的score值,并通過(guò)又一次插入這個(gè)member元素,來(lái)保證該member在正確的位置上。
score值能夠是整數(shù)值或雙精度浮點(diǎn)數(shù)。
假設(shè)key不存在,則創(chuàng)建一個(gè)空的有序集并運(yùn)行ZADD操作。
當(dāng)key存在但不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
對(duì)有序集的很多其它介紹請(qǐng)參見(jiàn)sorted set。
時(shí)間復(fù)雜度:
? ? O(M*log(N)),N是有序集的基數(shù),M為成功加入的新成員的數(shù)量。
返回值:
? ? 被成功加入的新成員的數(shù)量,不包含那些被更新的、已經(jīng)存在的成員。
?
? ? ?
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),ZADD每次僅僅能加入一個(gè)元素。
?
?
ZREM
ZREM key member [member ...]
移除有序集key中的一個(gè)或多個(gè)成員,不存在的成員將被忽略。
當(dāng)key存在但不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
時(shí)間復(fù)雜度:
? ? O(M*log(N)),N為有序集的基數(shù),M為被成功移除的成員的數(shù)量。
返回值:
? ? 被成功移除的成員的數(shù)量,不包含被忽略的成員。
? ? 注解:在Redis2.4版本號(hào)曾經(jīng),ZREM每次僅僅能刪除一個(gè)元素。
?
?
ZCARD
ZCARD key
返回有序集key的基數(shù)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)key存在且是有序集類型時(shí),返回有序集的基數(shù)。
? ? 當(dāng)key不存在時(shí),返回0。
?
ZCOUNT
ZCOUNT key min max
返回有序集key中,score值在min和max之間(默認(rèn)包含score值等于min或max)的成員。
關(guān)于參數(shù)min和max的具體用法,請(qǐng)參考ZRANGEBYSCORE命令。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為值在min和max之間的元素的數(shù)量。
返回值:
? ? score值在min和max之間的成員的數(shù)量。
?
ZSCORE
ZSCORE key member
返回有序集key中,成員member的score值。
假設(shè)member元素不是有序集key的成員,或key不存在,返回nil。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? member成員的score值,以字符串形式表示。
?
ZINCRBY
ZINCRBY key increment member
為有序集key的成員member的score值加上增量increment。
你也能夠通過(guò)傳遞一個(gè)負(fù)數(shù)值increment,讓score減去對(duì)應(yīng)的值,比方ZINCRBY key -5 member,就是讓member的score值減去5。
當(dāng)key不存在,或member不是key的成員時(shí),ZINCRBY key increment member等同于ZADD key increment member。
當(dāng)key不是有序集類型時(shí),返回一個(gè)錯(cuò)誤。
score值能夠是整數(shù)值或雙精度浮點(diǎn)數(shù)。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? member成員的新score值,以字符串形式表示。
?
?
ZRANGE
ZRANGE key start stop [WITHSCORES]
返回有序集key中,指定區(qū)間內(nèi)的成員。
當(dāng)中成員的位置按score值遞增(從小到大)來(lái)排序。
具有同樣score值的成員按字典序(lexicographical order)來(lái)排列。
假設(shè)你須要成員按score值遞減(從大到小)來(lái)排列,請(qǐng)使用ZREVRANGE命令。
下標(biāo)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示有序集第一個(gè)成員,以1表示有序集第二個(gè)成員,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示最后一個(gè)成員,-2表示倒數(shù)第二個(gè)成員,以此類推。
超出范圍的下標(biāo)并不會(huì)引起錯(cuò)誤。
比方說(shuō),當(dāng)start的值比有序集的最大下標(biāo)還要大,或是start > stop時(shí),ZRANGE命令僅僅是簡(jiǎn)單地返回一個(gè)空列表。
還有一方面,假如stop參數(shù)的值比有序集的最大下標(biāo)還要大,那么Redis將stop當(dāng)作最大下標(biāo)來(lái)處理。
能夠通過(guò)使用WITHSCORES選項(xiàng),來(lái)讓成員和它的score值一并返回,返回列表以value1,score1, ..., valueN,scoreN的格式表示。
client庫(kù)可能會(huì)返回一些更復(fù)雜的數(shù)據(jù)類型,比方數(shù)組、元組等。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
ZREVRANGE
ZREVRANGE key start stop [WITHSCORES]
返回有序集key中,指定區(qū)間內(nèi)的成員。
當(dāng)中成員的位置按score值遞減(從大到小)來(lái)排列。
具有同樣score值的成員按字典序的反序(reverse lexicographical order)排列。
除了成員按score值遞減的次序排列這一點(diǎn)外,ZREVRANGE命令的其它方面和ZRANGE命令一樣。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZRANGEBYSCORE
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集key中,全部score值介于min和max之間(包含等于min或max)的成員。有序集成員按score值遞增(從小到大)次序排列。
具有同樣score值的成員按字典序(lexicographical order)來(lái)排列(該屬性是有序集提供的,不須要額外的計(jì)算)。
可選的LIMIT參數(shù)指定返回結(jié)果的數(shù)量及區(qū)間(就像SQL中的SELECT LIMIT offset, count),注意當(dāng)offset非常大時(shí),定位offset的操作可能須要遍歷整個(gè)有序集,此過(guò)程最壞復(fù)雜度為O(N)時(shí)間。
可選的WITHSCORES參數(shù)決定結(jié)果集是單單返回有序集的成員,還是將有序集成員及其score值一起返回。
該選項(xiàng)自Redis 2.0版本號(hào)起可用。
區(qū)間及無(wú)限
min和max能夠是-inf和+inf,這樣一來(lái),你就能夠在不知道有序集的最低和最高score值的情況下,使用ZRANGEBYSCORE這類命令。
默認(rèn)情況下,區(qū)間的取值使用閉區(qū)間(小于等于或大于等于),你也能夠通過(guò)給參數(shù)前添加(符號(hào)來(lái)使用可選的開(kāi)區(qū)間(小于或大于)。
舉個(gè)樣例:
?
返回全部符合條件1 < score <= 5的成員;
?
返回全部符合條件5 < score < 10的成員。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為被結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZREVRANGEBYSCORE
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
返回有序集key中,score值介于max和min之間(默認(rèn)包含等于max或min)的全部的成員。有序集成員按score值遞減(從大到小)的次序排列。
具有同樣score值的成員按字典序的反序(reverse lexicographical order)排列。
除了成員按score值遞減的次序排列這一點(diǎn)外,ZREVRANGEBYSCORE命令的其它方面和ZRANGEBYSCORE命令一樣。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),M為結(jié)果集的基數(shù)。
返回值:
? ? 指定區(qū)間內(nèi),帶有score值(可選)的有序集成員的列表。
?
?
ZRANK
ZRANK key member
返回有序集key中成員member的排名。當(dāng)中有序集成員按score值遞增(從小到大)順序排列。
排名以0為底,也就是說(shuō),score值最小的成員排名為0。
使用ZREVRANK命令能夠獲得成員按score值遞減(從大到小)排列的排名。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? 假設(shè)member是有序集key的成員,返回member的排名。
? ? 假設(shè)member不是有序集key的成員,返回nil。
?
ZREVRANK
ZREVRANK key member
返回有序集key中成員member的排名。當(dāng)中有序集成員按score值遞減(從大到小)排序。
排名以0為底,也就是說(shuō),score值最大的成員排名為0。
使用ZRANK命令能夠獲得成員按score值遞增(從小到大)排列的排名。
時(shí)間復(fù)雜度:
? ? O(log(N))
返回值:
? ? 假設(shè)member是有序集key的成員,返回member的排名。
? ? 假設(shè)member不是有序集key的成員,返回nil。
?
?
ZREMRANGEBYRANK
ZREMRANGEBYRANK key start stop
移除有序集key中,指定排名(rank)區(qū)間內(nèi)的全部成員。
區(qū)間分別下面標(biāo)參數(shù)start和stop指出,包括start和stop在內(nèi)。
下標(biāo)參數(shù)start和stop都以0為底,也就是說(shuō),以0表示有序集第一個(gè)成員,以1表示有序集第二個(gè)成員,以此類推。
你也能夠使用負(fù)數(shù)下標(biāo),以-1表示最后一個(gè)成員,-2表示倒數(shù)第二個(gè)成員,以此類推。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為被移除成員的數(shù)量。
返回值:
? ? 被移除成員的數(shù)量。
?
?
ZREMRANGEBYSCORE
ZREMRANGEBYSCORE key min max
移除有序集key中,全部score值介于min和max之間(包含等于min或max)的成員。
自版本號(hào)2.1.6開(kāi)始,score值等于min或max的成員也能夠不包含在內(nèi),詳情請(qǐng)參見(jiàn)ZRANGEBYSCORE命令。
時(shí)間復(fù)雜度:
? ? O(log(N)+M),N為有序集的基數(shù),而M為被移除成員的數(shù)量。
返回值:
? ? 被移除成員的數(shù)量。
?
?
ZINTERSTORE
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
計(jì)算給定的一個(gè)或多個(gè)有序集的交集,當(dāng)中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該交集(結(jié)果集)儲(chǔ)存到destination。
默認(rèn)情況下,結(jié)果集中某個(gè)成員的score值是全部給定集下該成員score值之和。
關(guān)于WEIGHTS和AGGREGATE選項(xiàng)的描寫敘述,參見(jiàn)ZUNIONSTORE命令。
時(shí)間復(fù)雜度:
? ? O(N*K)+O(M*log(M)),N為給定key中基數(shù)最小的有序集,K為給定有序集的數(shù)量,M為結(jié)果集的基數(shù)。
返回值:
? ? 保存到destination的結(jié)果集的基數(shù)。
?
?
ZUNIONSTORE
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
計(jì)算給定的一個(gè)或多個(gè)有序集的并集,當(dāng)中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該并集(結(jié)果集)儲(chǔ)存到destination。
默認(rèn)情況下,結(jié)果集中某個(gè)成員的score值是全部給定集下該成員score值之和。
WEIGHTS
使用WEIGHTS選項(xiàng),你能夠?yàn)槊恳粋€(gè)給定有序集分別指定一個(gè)乘法因子(multiplication factor),每一個(gè)給定有序集的全部成員的score值在傳遞給聚合函數(shù)(aggregation function)之前都要先乘以該有序集的因子。
假設(shè)沒(méi)有指定WEIGHTS選項(xiàng),乘法因子默認(rèn)設(shè)置為1。
AGGREGATE
使用AGGREGATE選項(xiàng),你能夠指定并集的結(jié)果集的聚合方式。
默認(rèn)使用的參數(shù)SUM,能夠?qū)⑷考现心硞€(gè)成員的score值之和作為結(jié)果集中該成員的score值;使用參數(shù)MIN,能夠?qū)⑷考现心硞€(gè)成員的最小score值作為結(jié)果集中該成員的score值;而參數(shù)MAX則是將全部集合中某個(gè)成員的最大score值作為結(jié)果集中該成員的score值。
時(shí)間復(fù)雜度:
? ? O(N)+O(M log(M)),N為給定有序集基數(shù)的總和,M為結(jié)果集的基數(shù)。
返回值:
? ? 保存到destination的結(jié)果集的基數(shù)。
?
?
公布/訂閱(Pub/Sub)
PUBLISH
PUBLISH channel message
將信息 message 發(fā)送到指定的頻道 channel 。
時(shí)間復(fù)雜度:
? ? O(N+M),當(dāng)中 N 是頻道 channel 的訂閱者數(shù)量,而 M 則是使用模式訂閱(subscribed patterns)的client的數(shù)量。
返回值:
? ? 接收到信息 message 的訂閱者數(shù)量。
?
?
SUBSCRIBE
SUBSCRIBE channel [channel ...]
訂閱給定頻道的信息。
時(shí)間復(fù)雜度:
? ? O(N),當(dāng)中 N 是訂閱的頻道的數(shù)量。
返回值:
? ? 接收到的信息(請(qǐng)參見(jiàn)以下的代碼說(shuō)明)。
?
?
PSUBSCRIBE
PSUBSCRIBE pattern [pattern ...]
訂閱符合給定模式的頻道。
每一個(gè)模式以 * 作為匹配符,比方 huangz* 匹配全部以 huangz 開(kāi)頭的頻道( huangzmsg 、 huangz-blog 、 huangz.tweets 等等), news.* 匹配全部以 news. 開(kāi)頭的頻道(news.it 、 news.global.today 等等),諸如此類。
時(shí)間復(fù)雜度:
? ? O(N), N 是訂閱的模式的數(shù)量。
返回值:
? ? 接收到的信息(請(qǐng)參見(jiàn)以下的代碼說(shuō)明)。
?
?
UNSUBSCRIBE
? ? 警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
PUNSUBSCRIBE
? ? 警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
?
事務(wù)(Transaction)
WATCH
ATCH key [key ...]
監(jiān)視一個(gè)(或多個(gè)) key ,假設(shè)在事務(wù)運(yùn)行之前這個(gè)(或這些) key 被其它命令所修改,那么事務(wù)將被打斷。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
UNWATCH
UNWATCH
取消 WATCH 命令對(duì)全部 key 的監(jiān)視。
假設(shè)在運(yùn)行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被運(yùn)行了的話,那么就不須要再運(yùn)行 UNWATCH 了。
由于 EXEC 命令會(huì)運(yùn)行事務(wù),因此 WATCH 命令的效果已經(jīng)產(chǎn)生了;而 DISCARD 命令在取消事務(wù)的同一時(shí)候也會(huì)取消全部對(duì) key 的監(jiān)視,因此這兩個(gè)命令運(yùn)行之后,就沒(méi)有必要運(yùn)行 UNWATCH 了。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是 OK 。
?
MULTI
MULTI
標(biāo)記一個(gè)事務(wù)塊的開(kāi)始。
事務(wù)塊內(nèi)的多條命令會(huì)依照先后順序被放進(jìn)一個(gè)隊(duì)列其中,最后由 EXEC 命令在一個(gè)原子時(shí)間內(nèi)運(yùn)行。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
?
EXEC
EXEC
運(yùn)行全部事務(wù)塊內(nèi)的命令。
假如某個(gè)(或某些) key 正處于 WATCH 命令的監(jiān)視之下,且事務(wù)塊中有和這個(gè)(或這些) key 相關(guān)的命令,那么 EXEC 命令僅僅在這個(gè)(或這些) key 沒(méi)有被其它命令所修改的情況下運(yùn)行并生效,否則該事務(wù)被打斷(abort)。
時(shí)間復(fù)雜度:
? ? 事務(wù)塊內(nèi)全部命令的時(shí)間復(fù)雜度的總和。
返回值:
? ? 事務(wù)塊內(nèi)全部命令的返回值,按命令運(yùn)行的先后順序排列。
? ? 當(dāng)操作被打斷時(shí),返回空值 nil 。
?
?
DISCARD
DISCARD
取消事務(wù),放棄運(yùn)行事務(wù)塊內(nèi)的全部命令。
假設(shè)正在使用 WATCH 命令監(jiān)視某個(gè)(或某些) key ,那么取消全部監(jiān)視,等同于運(yùn)行命令 UNWATCH 。
時(shí)間復(fù)雜度:
? ? O(1)。
返回值:
? ? 總是返回 OK 。
?
?
連接(Connection)
AUTH
AUTH password
通過(guò)設(shè)置配置文件里 requirepass 項(xiàng)的值(使用命令 CONFIG SET requirepass password ),能夠使用密碼來(lái)保護(hù) Redis server。
假設(shè)開(kāi)啟了password保護(hù)的話,在每次連接 Redis server之后,就要使用 AUTH 命令解鎖,解鎖之后才干使用其它 Redis 命令。
假設(shè) AUTH 命令給定的password password 和配置文件里的password相符的話,server會(huì)返回 OK 并開(kāi)始接受命令輸入。
反之,假設(shè)password不匹配的話,server將返回一個(gè)錯(cuò)誤,并要求client需又一次輸入password。
?
? ? 警告:由于 Redis 高性能的特點(diǎn),在非常短時(shí)間內(nèi)嘗試推測(cè)非常多個(gè)password是有可能的,因此請(qǐng)確保使用的password足夠復(fù)雜和足夠長(zhǎng),以免遭受password推測(cè)攻擊。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? password匹配時(shí)返回 OK ,否則返回一個(gè)錯(cuò)誤。
?
PING
PING
client向server發(fā)送一個(gè) PING ,然后server返回client一個(gè) PONG 。
通經(jīng)常使用于測(cè)試與server的連接是否仍然生效,或者用于測(cè)量延遲值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? PONG
?
?
SELECT
SELECT index
切換到指定的數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)索引號(hào)用數(shù)字值指定,以 0 作為起始索引值。
新的鏈接總是使用 0 號(hào)數(shù)據(jù)庫(kù)。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? OK
?
ECHO
ECHO message
打印一個(gè)特定的信息 message ,測(cè)試時(shí)使用。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? message 自身。
?
?
QUIT
QUIT
請(qǐng)求server關(guān)閉與當(dāng)前client的連接。
一旦全部等待中的回復(fù)(假設(shè)有的話)順利寫入到client,連接就會(huì)被關(guān)閉。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK (可是不會(huì)被打印顯示,由于當(dāng)時(shí) Redis-cli 已經(jīng)退出)。
?
?
server(Server)
BGREWRITEAOF
BGREWRITEAOF
異步(Asynchronously)重寫 AOF 文件以反應(yīng)當(dāng)前數(shù)據(jù)庫(kù)的狀態(tài)。
即使 BGREWRITEAOF 命令運(yùn)行失敗,舊 AOF 文件里的數(shù)據(jù)也不會(huì)因此丟失或改變。
時(shí)間復(fù)雜度:
? ? O(N), N 為要追加到 AOF 文件里的數(shù)據(jù)數(shù)量。
返回值:
? ? 反饋信息。
?
BGSAVE
在后臺(tái)異步保存當(dāng)前數(shù)據(jù)庫(kù)的數(shù)據(jù)到磁盤。
BGSAVE 命令運(yùn)行之后馬上返回 OK ,然后 Redis fork出一個(gè)新子進(jìn)程,原來(lái)的 Redis 進(jìn)程(父進(jìn)程)繼續(xù)處理client請(qǐng)求,而子進(jìn)程則負(fù)責(zé)將數(shù)據(jù)保存到磁盤,然后退出。
client能夠通過(guò) LASTSAVE 命令查看相關(guān)信息,推斷 BGSAVE 命令是否運(yùn)行成功。
時(shí)間復(fù)雜度:
? ? O(N), N 為要保存到數(shù)據(jù)庫(kù)中的 key 的數(shù)量。
返回值:
? ? 反饋信息。
?
SAVE
SAVE
同步保存當(dāng)前數(shù)據(jù)庫(kù)的數(shù)據(jù)到磁盤。
時(shí)間復(fù)雜度:
? ? O(N), N 為要保存到數(shù)據(jù)庫(kù)中的 key 的數(shù)量。
返回值:
? ? 總是返回 OK 。
?
?
LASTSAVE
LASTSAVE
返回近期一次 Redis 成功運(yùn)行保存操作的時(shí)間點(diǎn)( SAVE 、 BGSAVE 等),以 UNIX 時(shí)間戳格式表示。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 一個(gè) UNIX 時(shí)間戳。
?
?
DBSIZE
DBSIZE
返回當(dāng)前數(shù)據(jù)庫(kù)的 key 的數(shù)量。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng)前數(shù)據(jù)庫(kù)的 key 的數(shù)量。
?
?
SLAVEOF
SLAVEOF host port
SLAVEOF 命令用于在 Redis 執(zhí)行時(shí)動(dòng)態(tài)地改動(dòng)復(fù)制(replication)功能的行為。
通過(guò)運(yùn)行 SLAVEOF host port 命令,能夠?qū)?dāng)前server轉(zhuǎn)變?yōu)橹付╯erver的從屬server(slave server)。
假設(shè)當(dāng)前server已經(jīng)是某個(gè)主server(master server)的從屬server,那么運(yùn)行 SLAVEOF host port 將使當(dāng)前server停止對(duì)舊主server的同步,丟棄舊數(shù)據(jù)集,轉(zhuǎn)而開(kāi)始對(duì)新主server進(jìn)行同步。
另外,對(duì)一個(gè)從屬server運(yùn)行命令 SLAVEOF NO ONE 將使得這個(gè)從屬server關(guān)閉復(fù)制功能,并從從屬server轉(zhuǎn)變回主server,原來(lái)同步所得的數(shù)據(jù)集不會(huì)被丟棄。
利用“ SLAVEOF NO ONE 不會(huì)丟棄同步所得數(shù)據(jù)集”這個(gè)特性,能夠在主server失敗的時(shí)候,將從屬server用作新的主server,從而實(shí)現(xiàn)無(wú)間斷執(zhí)行。
時(shí)間復(fù)雜度:
? ? SLAVEOF host port ,O(N), N 為要同步的數(shù)據(jù)數(shù)量。
? ? SLAVEOF NO ONE , O(1) 。
返回值:
? ? 總是返回 OK 。
?
?
FLUSHALL
FLUSHALL
清空整個(gè) Redis server的數(shù)據(jù)(刪除全部數(shù)據(jù)庫(kù)的全部 key)。
此命令從不失敗。
時(shí)間復(fù)雜度:
? ? 尚未明白
返回值:
? ? 總是返回 OK 。
?
?
FLUSHDB
FLUSHDB
清空當(dāng)前數(shù)據(jù)庫(kù)中的全部 key 。
此命令從不失敗。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK 。
?
?
SHUTDOWN
SHUTDOWN
SHUTDOWN 命令運(yùn)行下面操作:
? ? 停止全部client
? ? 假設(shè)有最少一個(gè)保存點(diǎn)在等待,運(yùn)行 SAVE 命令
? ? 假設(shè) AOF 選項(xiàng)被打開(kāi),更新 AOF 文件
? ? server關(guān)閉
假設(shè)持久化被打開(kāi)的話, SHUTDOWN 命令會(huì)保證server正常關(guān)閉而不丟失不論什么數(shù)據(jù)。
假如僅僅是單純地運(yùn)行 SAVE 命令,然后再運(yùn)行 QUIT 命令,則沒(méi)有這一保證 —— 由于在運(yùn)行 SAVE 之后、運(yùn)行 QUIT 之前的這段時(shí)間中間,其它c(diǎn)lient可能正在和server進(jìn)行通訊,這時(shí)假設(shè)運(yùn)行 QUIT 就會(huì)造成數(shù)據(jù)丟失。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 運(yùn)行失敗時(shí)返回錯(cuò)誤。
? ? 運(yùn)行成功時(shí)不返回不論什么信息,server和client的連接斷開(kāi),client自己主動(dòng)退出。
?
?
SLOWLOG
SLOWLOG subcommand [argument]
什么是 SLOWLOG
Slow log 是 Redis 用來(lái)記錄查詢運(yùn)行時(shí)間的日志系統(tǒng)。
查詢運(yùn)行時(shí)間指的是不包含像client響應(yīng)(talking)、發(fā)送回復(fù)等 IO 操作,而單單是運(yùn)行一個(gè)查詢命令所耗費(fèi)的時(shí)間。
另外,slow log 保存在內(nèi)存里面,讀寫速度很快,因此你能夠放心地使用它,不必操心由于開(kāi)啟 slow log 而損害 Redis 的速度。
設(shè)置 SLOWLOG
Slow log 的行為由兩個(gè)配置參數(shù)(configuration parameter)指定,能夠通過(guò)改寫 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令對(duì)它們動(dòng)態(tài)地進(jìn)行改動(dòng)。
第一個(gè)選項(xiàng)是 slowlog-log-slower-then ,它決定要對(duì)運(yùn)行時(shí)間大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的查詢進(jìn)行記錄。
比方運(yùn)行下面命令將讓 slow log 記錄全部查詢時(shí)間大于等于 100 微秒的查詢:
CONFIG SET slowlog-log-slower-then 100 ,
而下面命令記錄全部查詢時(shí)間大于 1000 微秒的查詢:
CONFIG SET slowlog-log-slower-then 1000 。
還有一個(gè)選項(xiàng)是 slowlog-max-len ,它決定 slow log 最多能保存多少條日志, slow log 本身是一個(gè) LIFO 隊(duì)列,當(dāng)隊(duì)列大小超過(guò) slowlog-max-len 時(shí),最舊的一條日志將被刪除,而最新的一條日志增加到 slow log ,以此類推。
下面命令讓 slow log 最多保存 1000 條日志:
CONFIG SET slowlog-max-len 1000 。
使用 CONFIG GET 命令能夠查詢兩個(gè)選項(xiàng)的當(dāng)前值:
?
?
查看 slow log
要查看 slow log ,能夠使用 SLOWLOG GET 或者 SLOWLOG GET number 命令,前者打印全部 slow log ,最大長(zhǎng)度取決于 slowlog-max-len 選項(xiàng)的值,而 SLOWLOG GET number 則僅僅打印指定數(shù)量的日志。
最新的日志會(huì)最先被打印:
?
?
日志的唯一 id 僅僅有在 Redis server重新啟動(dòng)的時(shí)候才會(huì)重置,這樣能夠避免對(duì)日志的反復(fù)處理(比方你可能會(huì)想在每次發(fā)現(xiàn)新的慢查詢時(shí)發(fā)郵件通知你)。
查看當(dāng)前日志的數(shù)量
使用命令 SLOWLOG LEN 能夠查看當(dāng)前日志的數(shù)量。
請(qǐng)注意這個(gè)值和 slower-max-len 的差別,它們一個(gè)是當(dāng)前日志的數(shù)量,一個(gè)是同意記錄的最大日志的數(shù)量。
?
清空日志
使用命令 SLOWLOG RESET 能夠清空 slow log 。
?
?
時(shí)間復(fù)雜度:O(1)
返回值:取決于不同命令,返回不同的值。
?
INFO
INFO
返回關(guān)于 Redis server的各種信息和統(tǒng)計(jì)值。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 詳細(xì)請(qǐng)參見(jiàn)以下的測(cè)試代碼。
?
?
CONFIG GET
CONFIG GET parameter
CONFIG GET 命令用于取得執(zhí)行中的 Redis server的配置參數(shù)(configuration parameters),只是并不是全部配置參數(shù)都被 CONFIG GET 命令所支持。
CONFIG GET 接受單個(gè)參數(shù) parameter 作為搜索keyword,查找全部匹配的配置參數(shù),當(dāng)中參數(shù)和值以“鍵-值對(duì)”(key-value pairs)的方式排列。
比方運(yùn)行 CONFIG GET s* 命令,server就會(huì)返回全部以 s 開(kāi)頭的配置參數(shù)及參數(shù)的值:
?
?
假設(shè)你僅僅是尋找特定的某個(gè)參數(shù)的話,你當(dāng)然也能夠直接指定參數(shù)的名字:
?
使用命令 CONFIG GET * ,能夠列出 CONFIG GET 命令支持的全部參數(shù):
?
全部被 CONFIG SET 所支持的配置參數(shù)都能夠在配置文件 redis.conf 中找到,只是 CONFIG GET 和 CONFIG SET 使用的格式和 redis.conf 文件所使用的格式有下面兩點(diǎn)不同:
? ? 10kb 、 2gb 這些在配置文件里所使用的儲(chǔ)存單位縮寫,不能夠用在 CONFIG 命令中, CONFIG SET 的值僅僅能通過(guò)數(shù)字值顯式地設(shè)定。
? ? ?
? ? 像 CONFIG SET xxx 1k 這種命令是錯(cuò)誤的,正確的格式是 CONFIG SET xxx 1000 。
? ? save 選項(xiàng)在 redis.conf 中是用多行文字儲(chǔ)存的,但在 CONFIG GET 命令中,它僅僅打印一行文字。
? ? ?
? ? 下面是 save 選項(xiàng)在 redis.conf 文件里的表示:
? ? ?
? ? save 900 1
? ? save 300 10
? ? save 60 10000
? ? ?
? ? 可是 CONFIG GET 命令的輸出僅僅有一行:
? ? ?
? ? redis> CONFIG GET save
? ? 1) "save"
? ? 2) "900 1 300 10 60 10000"
? ? ?
? ? 上面 save 參數(shù)的三個(gè)值表示:在 900 秒內(nèi)最少有 1 個(gè) key 被修改,或者 300 秒內(nèi)最少有 10 個(gè) key 被修改,又或者 60 秒內(nèi)最少有 1000 個(gè) key 被修改,以上三個(gè)條件隨便滿足一個(gè),就觸發(fā)一次保存操作。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 給定配置參數(shù)的值。
?
CONFIG SET
CONFIG SET parameter value
CONFIG SET 命令能夠動(dòng)態(tài)地調(diào)整 Redis server的配置(configuration)而無(wú)須重新啟動(dòng)。
你能夠使用它改動(dòng)配置參數(shù),或者改變 Redis 的持久化(Persistence)方式。
CONFIG SET 能夠改動(dòng)的配置參數(shù)能夠使用命令 CONFIG GET * 來(lái)列出,全部被 CONFIG SET 改動(dòng)的配置參數(shù)都會(huì)馬上生效。
關(guān)于 CONFIG SET 命令的很多其它消息,請(qǐng)參見(jiàn)命令 CONFIG GET 的說(shuō)明。
關(guān)于怎樣使用 CONFIG SET 命令改動(dòng) Redis 持久化方式,請(qǐng)參見(jiàn) Redis Persistence 。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 當(dāng)設(shè)置成功時(shí)返回 OK ,否則返回一個(gè)錯(cuò)誤。
?
CONFIG RESETSTAT
CONFIG RESETSTAT
重置 INFO 命令中的某些統(tǒng)計(jì)數(shù)據(jù),包含:
? ? Keyspace hits (鍵空間命中次數(shù))
? ? Keyspace misses (鍵空間不命中次數(shù))
? ? Number of commands processed (運(yùn)行命令的次數(shù))
? ? Number of connections received (連接server的次數(shù))
? ? Number of expired keys (過(guò)期key的數(shù)量)
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 總是返回 OK 。
?
DEBUG OBJECT
DEBUG OBJECT key
返回給定 key 的調(diào)試信息。
時(shí)間復(fù)雜度:
? ? O(1)
返回值:
? ? 當(dāng) key 存在時(shí),返回有關(guān)信息。
? ? 當(dāng) key 不存在時(shí),返回一個(gè)錯(cuò)誤。
?
DEBUG SEGFAULT
DEBUG SEGFAULT
令 Redis server崩潰,調(diào)試用。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 無(wú)
?
MONITOR
MONITOR
實(shí)時(shí)打印出 Redis server接收到的命令,調(diào)試用。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 總是返回 OK 。
?
SYNC
YNC
用于復(fù)制功能(replication)的內(nèi)部命令。
時(shí)間復(fù)雜度:
? ? 不明白
返回值:
? ? 不明白
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
