本文是參考《redis中文手冊》,將示例代碼用php來實現(xiàn),注意php-redis與redis_cli的區(qū)別(主要是返回值類型和參數(shù)用法)。
目錄(使用CTRL+F快速查找命令):
Key | String | Hash | List | Set |
---|---|---|---|---|
Sorted Set | Pub/Sub | Transaction | Connection | Server |
---|---|---|---|---|
phpredis是redis的php的一個擴展,效率是相當高有鏈表排序功能,對創(chuàng)建內(nèi)存級的模塊業(yè)務關系
很有用;以下是redis官方提供的命令使用技巧:
下載地址如下:
https://github.com/owlient/phpredis(支持redis 2.0.4)
Redis::__construct構造函數(shù)
$redis = new Redis();
connect, open 鏈接redis服務
參數(shù)
host: string,服務地址
port: int,端口號
timeout: float,鏈接時長 (可選, 默認為 0 ,不限鏈接時間)
注: 在redis.conf中也有時間,默認為300
pconnect, popen 不會主動關閉的鏈接
參考上面
setOption 設置redis模式
getOption 查看redis設置的模式
ping 查看連接狀態(tài)
KEY相關操作
移除給定的一個或多個key。
如果key不存在,則忽略該命令。
//DEL
# 情況1: 刪除單個key
$redis->set('myname','ikodota');
echo $redis->get('myname').'<br>'; # 返回:ikodota
$redis->del('myname');# 返回 TRUE(1)
var_dump($redis->get('myname')); # 返回 bool(false)
# 情況2: 刪除一個不存在的key
if(!$redis->exists('fake_key')) # 不存在
var_dump($redis->del('fake_key')); # 返回 int(0)
# 情況3: 同時刪除多個key
$array_mset=array('first_key'=>'first_val',
'second_key'=>'second_val',
'third_key'=>'third_val');
$redis->mset($array_mset); #用MSET一次儲存多個值
$array_mget=array('first_key','second_key','third_key');
var_dump($redis->mget($array_mget)); #一次返回多個值 //array(3) { [0]=> string(9) "first_val" [1]=> string(10) "second_val" [2]=> string(9) "third_val" }
$redis->del($array_mget); #同時刪除多個key
var_dump($redis->mget($array_mget)); #返回 array(3) { [0]=> bool(false) [1]=> bool(false) [2]=> bool(false) }
特殊符號用"\"隔開
//KEYS
#$redis->FLUSHALL();
$array_mset_keys=array('one'=>'1',
'two'=>'2',
'three '=>'3',
'four'=>'4');
$redis->mset($array_mset_keys); #用MSET一次儲存多個值
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 )
從當前數(shù)據(jù)庫中隨機返回(不刪除)一個key。
//RANDOMKEY
$redis->FLUSHALL();
# 情況1:數(shù)據(jù)庫不為空
$array_mset_randomkey=array('fruit'=>'apple',
'drink'=>'beer',
'food'=>'cookis');
$redis->mset($array_mset_randomkey);
echo $redis->randomkey();
print_r($redis->keys('*')); # 查看數(shù)據(jù)庫內(nèi)所有key,證明RANDOMKEY并不刪除key//Array ( [0] => food [1] => drink [2] => fruit )
# 情況2:數(shù)據(jù)庫為空
$redis->flushdb(); # 刪除當前數(shù)據(jù)庫所有key
var_dump($redis-> randomkey()); //bool(false)
返回給定key的剩余生存時間(time to live)(以秒為單位)。
//TTL
# 情況1:帶TTL的key
$redis->flushdb();
//$redis->set('name','ikodota'); # 設置一個key
$redis->expire('name',30); # 設置生存時間為30秒 //return (integer) 1
echo $redis->get('name'); //return ikodota
echo $redis->ttl('name'); //(integer) 25
//echo $redis->ttl('name'); # 30秒過去,name過期 //(integer) -1
var_dump($redis->get('name')); # 過期的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)
檢查給定key是否存在。
//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)
將當前數(shù)據(jù)庫(默認為0)的key移動到給定的數(shù)據(jù)庫db當中。
如果當前數(shù)據(jù)庫(源數(shù)據(jù)庫)和給定數(shù)據(jù)庫(目標數(shù)據(jù)庫)有相同名字的給定key,或者key不存在于當前數(shù)據(jù)庫,那么MOVE沒有任何效果。
因此,也可以利用這一特性,將MOVE當作鎖(locking)原語。
//MOVE
echo '<br><br>MOVE<br>';
# 情況1: key存在于當前數(shù)據(jù)庫
$redis->SELECT(0); # redis默認使用數(shù)據(jù)庫0,為了清晰起見,這里再顯式指定一次。//OK
$redis->SET('song',"secret base - Zone"); //OK
var_dump ($redis->MOVE('song',1)); # 將song移動到數(shù)據(jù)庫1 //bool(true)
# 情況2:當key不存在的時候
$redis->SELECT(1);
var_dump ($redis->EXISTS('fake_key'));//bool(false);
var_dump($redis->MOVE('fake_key', 0)); # 試圖從數(shù)據(jù)庫1移動一個不存在的key到數(shù)據(jù)庫0,失敗) //bool(false)
$redis->SELECT(0); # 使用數(shù)據(jù)庫0
var_dump($redis->EXISTS('fake_key')); # 證實fake_key不存在 //bool(false)
# 情況3:當源數(shù)據(jù)庫和目標數(shù)據(jù)庫有相同的key時
$redis->SELECT(0); # 使用數(shù)據(jù)庫0
$redis->SET('favorite_fruit',"banana");
$redis->SELECT(1); # 使用數(shù)據(jù)庫1
$redis->SET('favorite_fruit',"apple");
$redis->SELECT(0); # 使用數(shù)據(jù)庫0,并試圖將favorite_fruit移動到數(shù)據(jù)庫1
var_dump($redis->MOVE('favorite_fruit',1)); # 因為兩個數(shù)據(jù)庫有相同的key,MOVE失敗 //return bool(false)
echo $redis->GET('favorite_fruit'); # 數(shù)據(jù)庫0的favorite_fruit沒變 //return banana
$redis->SELECT(1);
echo $redis->GET('favorite_fruit'); # 數(shù)據(jù)庫1的favorite_fruit也是 //return apple
將key改名為newkey。
當key和newkey相同或者key不存在時,返回一個錯誤。
當newkey已經(jīng)存在時,RENAME命令將覆蓋舊值。
//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不復存在 //bool(false)
var_dump($redis->EXISTS('greeting')); # greeting取而代之 //bool(true)
# 情況2:當key不存在時,返回錯誤 ,php返回false;
var_dump($redis->RENAME('fake_key','never_exists')); //bool(false)
# 情況3:newkey已存在時,RENAME會覆蓋舊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“沒有”了 //string(6) "lenovo"
當且僅當newkey不存在時,將key改為newkey。
出錯的情況和RENAME一樣(key不存在時報錯)。
//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存在時,失敗
$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"
返回key所儲存的值的類型。
//TYPE
$redis->flushALL();
echo '<br><br>TYPE<br>';
var_dump($redis->TYPE('fake_key')); //none /int(0)
$redis->SET('weather',"sunny"); # 構建一個字符串
var_dump($redis->TYPE('weather'));//string / int(1)
$redis->SADD('pat',"dog"); # 構建一個集合
var_dump($redis->TYPE('pat')); //set /int(2)
$redis->LPUSH('book_list',"programming in scala"); # 構建一個列表
var_dump($redis->TYPE('book_list'));//list / int(3)
$redis->ZADD('pats',1,'cat'); # 構建一個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'); # 一個新域
var_dump($redis->HGET('website','google')); //string(8) "www.g.cn"
var_dump($redis->TYPE('website')); //hash /int(5)
EXPIRE key seconds
為給定key設置生存時間。
當key過期時,它會被自動刪除。
在Redis中,帶有生存時間的key被稱作“易失的”(volatile)。
//EXPIRE
$redis->select(7);
//$redis->flushdb();
echo '<br><br>EXPIRE<br>';
$redis->SET('cache_page',"www.cnblogs.com/ikodota");
$redis->EXPIRE('cache_page', 30); # 設置30秒后過期
sleep(6);
echo $redis->TTL('cache_page').'<br>'; # 查看給定key的剩余生存時間 //(integer) 24
$redis->EXPIRE('cache_page', 3000); # 更新生存時間,3000秒
sleep(4);
echo $redis->TTL('cache_page').'<br>'; //(integer) 2996
EXPIREAT的作用和EXPIRE一樣,都用于為key設置生存時間。
不同在于EXPIREAT命令接受的時間參數(shù)是UNIX時間戳(unix timestamp)。
//EXPIREAT
echo '<br><br>EXPIREAT<br>';
$redis->SET('cache','www.google.com');
echo $redis->EXPIREAT('cache','1355292000'); # 這個key將在2012.12.12過期
echo ($redis->TTL('cache')); //return 124345085
OBJECT命令允許從內(nèi)部察看給定key的Redis對象。
OBJECT命令有多個子命令:
//OBJECT
$redis->select(8);
echo '<br><br>OBJECT<br>';
$redis->SET('game',"WOW"); # 設置一個字符串
$redis->OBJECT('REFCOUNT','game'); # 只有一個引用
//sleep(5);
echo $redis->OBJECT('IDLETIME','game'); # 等待一陣。。。然后查看空轉時間 //(integer) 10
//echo $redis->GET('game'); # 提取game, 讓它處于活躍(active)狀態(tài) //return WOW
//echo $redis->OBJECT('IDLETIME','game'); # 不再處于空轉 //(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"
移除給定key的生存時間。
//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'); # 移除生存時間
echo $redis->TTL('time_to_say_goodbye'); # 移除成功 //int(-1)
排序,分頁等
參數(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)過排序的元素。
排序默認以數(shù)字作為對象,值被解釋為雙精度浮點數(shù),然后進行比較。
一般SORT用法
最簡單的SORT使用方法是SORT key。
假設today_cost是一個保存數(shù)字的列表,SORT命令默認會返回該列表值的遞增(從小到大)排序結果。
# 將數(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" }
當數(shù)據(jù)集中保存的是字符串值時,你可以用ALPHA修飾符(modifier)進行排序。
# 將數(shù)據(jù)一一加入到列表中
$redis->LPUSH('website', "www.reddit.com");
$redis->LPUSH('website', "www.slashdot.com");
$redis->LPUSH('website', "www.infoq.com");
# 默認排序
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" }
如果你正確設置了!LC_COLLATE環(huán)境變量的話,Redis能識別UTF-8編碼。
以下例子返回排序結果的前5個對象(offset為0表示沒有元素被跳過)。
# 將數(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個對象。
$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進行排序
有時候你會希望使用外部的key作為權重來比較元素,代替默認的對比方法。
假設現(xiàn)在有用戶(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ù)庫中
# 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);
如果希望按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
但是有時候只是返回相應的id沒有什么用,你可能更希望排序后返回id對應的用戶名,這樣更友好一點,使用GET選項可以做到這一點:
$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操作來獲取更多外部key。
比如你不但希望獲取用戶名,還希望連用戶的密碼也一并列出,可以使用以下命令:
# 先添加一些測試數(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" # 用戶名
#2) "hey,im in" # 密碼
#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_*返回的結果位置不同
# 獲取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還有一個特殊的規(guī)則——"GET #",用于獲取被排序對象(我們這里的例子是user_id)的當前元素。
比如你希望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"
只獲取對象而不排序
BY修飾符可以將一個不存在的key當作權重,讓SORT跳過排序操作。
該方法用于你希望獲取外部對象而又不希望引起排序開銷時使用。
# 確保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"
保存排序結果
默認情況下,SORT操作只是簡單地返回排序結果,如果你希望保存排序結果,可以給STORE選項指定一個key作為參數(shù),排序結果將以列表的形式被保存到這個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)); # 查看排序結果 //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"
一個有趣的用法是將SORT結果保存,用EXPIRE為結果集設置生存時間,這樣結果集就成了SORT操作的一個緩存。
這樣就不必頻繁地調(diào)用SORT操作了,只有當結果集過期時,才需要再調(diào)用一次SORT操作。
有時候為了正確實現(xiàn)這一用法,你可能需要加鎖以避免多個客戶端同時進行緩存重建(也就是多個客戶端,同一時間進行SORT操作,并保存為結果集),具體參見SETNX命令。
在GET和BY中使用哈希表
可以使用哈希表特有的語法,在SORT命令中進行GET和BY操作。
# 假設現(xiàn)在我們的用戶表新增了一個serial項來為作為每個用戶的序列號
# 序列號以哈希表的形式保存在serial哈希域內(nèi)。
$redis_hash_testdata_array=array(1=>'23131283',
2=>'23810573',
222=>'502342349',
59230=>'2435829758'
);
$redis->HMSET('serial',$redis_hash_testdata_array);
# 我們希望以比較serial中的大小來作為排序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"
符號"->"用于分割哈希表的關鍵字(key name)和索引域(hash field),格式為"key->field"。
除此之外,哈希表的BY和GET操作和上面介紹的其他數(shù)據(jù)結構(列表、集合、有序集合)沒有什么不同。
將字符串值value關聯(lián)到key。
如果key已經(jīng)持有其他值,SET就覆寫舊值,無視類型。
時間復雜度:O(1)返回值:總是返回OK(TRUE),因為SET不可能失敗。
# 情況1:對字符串類型的key進行SET
$redis->SET('apple', 'www.apple.com');#OK //bool(true)
$redis->GET('apple');//"www.apple.com"
# 情況2:對非字符串類型的key進行SET
$redis->LPUSH('greet_list', "hello"); # 建立一個列表 #(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)
將key的值設為value,當且僅當key不存在。
若給定的key已經(jīng)存在,則SETNX不做任何動作。
SETNX是”SET if Not eXists”(如果不存在,則SET)的簡寫。
//SETNX
echo '<br><br>SETNX<br>';
$redis->EXISTS('job'); # job不存在 //bool(false);
$redis->SETNX('job', "programmer"); # job設置成功 //bool(true)
$redis->SETNX('job', "code-farmer"); # job設置失敗 //bool(false)
echo $redis->GET('job'); # 沒有被覆蓋 //"programmer"
設計模式(Design pattern): 將SETNX用于加鎖(locking)
SETNX可以用作加鎖原語(locking primitive)。比如說,要對關鍵字(key)foo加鎖,客戶端可以嘗試以下方式:
SETNX lock.foo <current Unix time + lock timeout + 1>
如果SETNX返回1,說明客戶端已經(jīng)獲得了鎖,key設置的unix時間則指定了鎖失效的時間。之后客戶端可以通過DEL lock.foo來釋放鎖。
如果SETNX返回0,說明key已經(jīng)被其他客戶端上鎖了。如果鎖是非阻塞(non blocking lock)的,我們可以選擇返回調(diào)用,或者進入一個重試循環(huán),直到成功獲得鎖或重試超時(timeout)。
處理死鎖(deadlock)
上面的鎖算法有一個問題:如果因為客戶端失敗、崩潰或其他原因導致沒有辦法釋放鎖的話,怎么辦?
這種狀況可以通過檢測發(fā)現(xiàn)——因為上鎖的key保存的是unix時間戳,假如key值的時間戳小于當前的時間戳,表示鎖已經(jīng)不再有效。
但是,當有多個客戶端同時檢測一個鎖是否過期并嘗試釋放它的時候,我們不能簡單粗暴地刪除死鎖的key,再用SETNX上鎖,因為這時競爭條件(race condition)已經(jīng)形成了:
幸好,以下算法可以避免以上問題。來看看我們聰明的C4客戶端怎么辦:
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
警告
為了讓這個加鎖算法更健壯,獲得鎖的客戶端應該常常檢查過期時間以免鎖因諸如DEL等命令的執(zhí)行而被意外解開,因為客戶端失敗的情況非常復雜,不僅僅是崩潰這么簡單,還可能是客戶端因為某些操作被阻塞了相當長時間,緊接著DEL命令被嘗試執(zhí)行(但這時鎖卻在另外的客戶端手上)。
將值value關聯(lián)到key,并將key的生存時間設為seconds(以秒為單位)。
如果key 已經(jīng)存在,SETEX命令將覆寫舊值。
這個命令類似于以下兩個命令:
$redis->SET('key', 'value');
$redis->EXPIRE('key','seconds'); # 設置生存時間
不同之處是,SETEX是一個原子性(atomic)操作,關聯(lián)值和設置生存時間兩個動作會在同一時間內(nèi)完成,該命令在Redis用作緩存時,非常實用。
# 情況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'); # 剩余生存時間 //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 key offset value
用value參數(shù)覆寫(Overwrite)給定key所儲存的字符串值,從偏移量offset開始。
不存在的key當作空白字符串處理。
SETRANGE命令會確保字符串足夠長以便將value設置在指定的偏移量上,如果給定key原來儲存的字符串長度比偏移量小(比如字符串只有5個字符長,但你設置的offset是10),那么原字符和偏移量之間的空白將用零比特(zerobytes,"\x00")來填充。
注意你能使用的最大偏移量是2^29-1(536870911),因為Redis的字符串被限制在512兆(megabytes)內(nèi)。如果你需要使用比這更大的空間,你得使用多個key。
警告
當生成一個很長的字符串時,Redis需要分配內(nèi)存空間,該操作有時候可能會造成服務器阻塞(block)。在2010年的Macbook Pro上,設置偏移量為536870911(512MB內(nèi)存分配),耗費約300毫秒, 設置偏移量為134217728(128MB內(nèi)存分配),耗費約80毫秒,設置偏移量33554432(32MB內(nèi)存分配),耗費約30毫秒,設置偏移量為8388608(8MB內(nèi)存分配),耗費約8毫秒。 注意若首次內(nèi)存分配成功之后,再對同一個key調(diào)用SETRANGE操作,無須再重新內(nèi)存。
模式
因為有了SETRANGE和GETRANGE命令,你可以將Redis字符串用作具有O(1)隨機訪問時間的線性數(shù)組。這在很多真實用例中都是非常快速且高效的儲存方式。
# 情況1:對非空字符串進行SETRANGE
$redis->SET('greeting', "hello world");
$redis->SETRANGE('greeting', 6, "Redis"); //int(11)
$redis->GET('greeting');//"hello Redis"
# 情況2:對空字符串/不存在的key進行SETRANGE
$redis->EXISTS('empty_string');//bool(false)
$redis->SETRANGE('empty_string', 5 ,"Redis!"); # 對不存在的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 ...]
同時設置一個或多個key-value對。
當發(fā)現(xiàn)同名的key存在時,MSET會用新值覆蓋舊值,如果你不希望覆蓋同名key,請使用MSETNX命令。
MSET是一個原子性(atomic)操作,所有給定key都在同一時間內(nèi)被設置,某些給定key被更新而另一些給定key沒有改變的情況,不可能發(fā)生。
#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('*')); # 確保指定的三個key-value對被插入 //array(3) { [0]=> string(4) "time" [1]=> string(7) "weather" [2]=> string(4) "date" }
# MSET覆蓋舊值的例子 但是經(jīng)過測試覆蓋不了
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手冊的示例結果不符
同時設置一個或多個key-value對,當且僅當key不存在。
即使只有一個key已存在,MSETNX也會拒絕所有傳入key的設置操作
MSETNX是原子性的,因此它可以用作設置多個不同key表示不同字段(field)的唯一性邏輯對象(unique logic object),所有字段要么全被設置,要么全不被設置。
# 情況1:對不存在的key進行MSETNX
$array_mset=array('rmdbs'=>'MySQL',
'nosql'=>'MongoDB',
'key-value-store'=>'redis'
);
$redis->MSETNX($array_mset);//bool(true)
# 情況2:對已存在的key進行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沒有被設置 bool(false)
echo $redis->GET('rmdbs'); # rmdbs沒有被修改 //"MySQL"
$array_mset_keys=array( 'rmdbs', 'nosql', 'key-value-store');
print_r($redis->MGET($array_mset_keys)); //Array ( [0] => MySQL [1] => MongoDB [2] => redis )
如果key已經(jīng)存在并且是一個字符串,APPEND命令將value追加到key原來的值之后。
如果key不存在,APPEND就簡單地將給定key設為value,就像執(zhí)行SET key value一樣。
# 情況1:對不存在的key執(zhí)行APPEND
$redis->EXISTS('myphone'); # 確保myphone不存在 //bool(false)
$redis->APPEND('myphone',"nokia"); # 對不存在的key進行APPEND,等同于SET myphone "nokia" //int(5) # 字符長度
# 情況2:對字符串進行APPEND
$redis->APPEND('myphone', " - 1110");# 長度從5個字符增加到12個字符 //int(12)
echo $redis->GET('myphone'); # 查看整個字符串 //"nokia - 1110"
返回key所關聯(lián)的字符串值。
如果key不存在則返回特殊值nil。
假如key儲存的值不是字符串類型,返回一個錯誤,因為GET只能用于處理字符串值。
//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"
返回所有(一個或多個)給定key的值。
如果某個指定key不存在,那么返回特殊值nil。因此,該命令永不失敗。
//MGET
echo '<br><br>MGET<br>';
$redis_mget_data_array=array('name'=>'ikodota','blog'=>'cnblogs.com/ikodota');
$redis->MSET($redis_mget_data_array);#用MSET一次儲存多個值
$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)); # 當MGET中有不存在key的情況 //array(2) { [0]=> string(7) "ikodota" [1]=> bool(false) }
返回key中字符串值的子字符串,字符串的截取范圍由start和end兩個偏移量決定(包括start和end在內(nèi))。
負數(shù)偏移量表示從字符串最后開始計數(shù),-1表示最后一個字符,-2表示倒數(shù)第二個,以此類推。
GETRANGE通過保證子字符串的值域(range)不超過實際字符串的值域來處理超出范圍的值域請求。
注解:在<=2.0的版本里,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>'; # 負數(shù)索引 //"end"
echo $redis->GETRANGE('greeting', 0, -1).'<br>'; # 從第一個到最后一個 //"hello, my friend"
echo $redis->GETRANGE('greeting', 0, 1008611).'<br>'; # 值域范圍不超過實際字符串,超過部分自動被符略 //"hello, my friend"
將給定key的值設為value,并返回key的舊值。
當key存在但不是字符串類型時,返回一個錯誤。
//GETSET
echo '<br><br>GETSET<br>';
var_dump($redis->EXISTS('mail'));//return bool(false);
var_dump($redis->GETSET('mail','xxx@google.com')); # 因為mail之前不存在,沒有舊值,返回nil ,#(nil) //bool(false)
var_dump($redis->GETSET('mail','xxx@yahoo.com')); # mail被更新,舊值被返回 //string(14) "xxx@google.com"
設計模式
GETSET可以和INCR組合使用,實現(xiàn)一個有原子性(atomic)復位操作的計數(shù)器(counter)。
舉例來說,每次當某個事件發(fā)生時,進程可能對一個名為mycount的key調(diào)用INCR操作,通常我們還要在一個原子時間內(nèi)同時完成獲得計數(shù)器的值和將計數(shù)器值復位為0兩個操作。
可以用命令GETSET mycounter 0來實現(xiàn)這一目標。
$redis->SELECT(2);
echo $redis->INCR('mycount').'<br>'; #(integer) 11
if($redis->GET('mycount')>19){
echo $redis->GETSET('mycount', 0).'<br>'; # 一個原子內(nèi)完成GET mycount和SET mycount 0操作 #"11"
}
echo $redis->GET('mycount'); #"0"
返回key所儲存的字符串值的長度。
當key儲存的不是字符串值時,返回一個錯誤。
$redis->SET('mykey', "Hello world");
echo $redis->STRLEN('mykey'); //int(11)
echo $redis->STRLEN('nonexisting'); # 不存在的key長度視為0 //int(0)
將key中儲存的數(shù)字值增一。
如果key不存在,以0為key的初始值,然后執(zhí)行INCR操作。
如果值包含錯誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個錯誤。
本操作的值限制在64位(bit)有符號數(shù)字表示之內(nèi)。
注解:這是一個針對字符串的操作,因為Redis沒有專用的整數(shù)類型,所以key內(nèi)儲存的字符串被解釋為十進制64位有符號整數(shù)來執(zhí)行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
將key所儲存的值加上增量increment。
如果key不存在,以0為key的初始值,然后執(zhí)行INCRBY命令。
如果值包含錯誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個錯誤。
本操作的值限制在64位(bit)有符號數(shù)字表示之內(nèi)。
關于更多遞增(increment)/遞減(decrement)操作信息,參見INCR命令。
//INCRBY
echo '<br><br>INCRBY<br>';
# 情況1:key存在且是數(shù)字值
$redis->SET('rank', 50); # 設置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)測試 與手冊上結果不一樣,不能直接從bool型轉為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)
將key中儲存的數(shù)字值減一。
如果key不存在,以0為key的初始值,然后執(zhí)行DECR操作。
如果值包含錯誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個錯誤。
本操作的值限制在64位(bit)有符號數(shù)字表示之內(nèi)。
關于更多遞增(increment)/遞減(decrement)操作信息,參見INCR命令。
//DECR
$redis->SELECT(3);
$redis->flushdb();
echo '<br><br>DECR<br>';
# 情況1:對存在的數(shù)字值key進行DECR
$redis->SET('failure_times', 10);
$redis->DECR('failure_times'); //int(9)
echo $redis->GET('failure_times').'<br>'; //string(1) "9"
# 情況2:對不存在的key值進行DECR
$redis->EXISTS('count'); #(integer) 0 //bool(false)
$redis->DECR('count'); //int(-1)
echo $redis->GET('count').'<br>'; //string(2) "-1"
# 情況3:對存在但不是數(shù)值的key進行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
將key所儲存的值減去減量decrement。
如果key不存在,以0為key的初始值,然后執(zhí)行DECRBY操作。
如果值包含錯誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個錯誤。
本操作的值限制在64位(bit)有符號數(shù)字表示之內(nèi)。
關于更多遞增(increment)/遞減(decrement)操作信息,參見INCR命令。
# 情況1:對存在的數(shù)值key進行DECRBY
$redis->SET('count', 100);
var_dump($redis->DECRBY('count', 20)); //int(80)
var_dump($redis->GET('count')); //string(2) "80"
# 情況2:對不存在的key進行DECRBY
$redis->EXISTS('pages');#(integer) 0 //bool(false)
var_dump($redis->DECRBY('pages', 10)); //int(-10)
var_dump($redis->GET('pages')); //string(3) "-10"
對key所儲存的字符串值,設置或清除指定偏移量上的位(bit)。
位的設置或清除取決于value參數(shù),可以是0也可以是1。
當key不存在時,自動生成一個新的字符串值。
字符串會增長(grown)以確保它可以將value保存在指定的偏移量上。當字符串值增長時,空白位置以0填充。
offset參數(shù)必須大于或等于0,小于2^32(bit映射被限制在512MB內(nèi))。
警告:對使用大的offset的SETBIT操作來說,內(nèi)存分配可能造成Redis服務器被阻塞。具體參考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" ,二進制為: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 ,二進制為:1000101,ASCII:69l
對key所儲存的字符串值,獲取指定偏移量上的位(bit)。
當offset比字符串值的長度大,或者key不存在時,返回0。
#參見SETBIT的示例
將哈希表key中的域field的值設為value。
如果key不存在,一個新的哈希表被創(chuàng)建并進行HSET操作。
如果域field已經(jīng)存在于哈希表中,舊值將被覆蓋。
將哈希表key中的域field的值設置為value,當且僅當域field不存在。
若域field已經(jīng)存在,該操作無效。
如果key不存在,一個新哈希表被創(chuàng)建并執(zhí)行HSETNX命令。
同時將多個field - value(域-值)對設置到哈希表key中。
此命令會覆蓋哈希表中已存在的域。
如果key不存在,一個空哈希表被創(chuàng)建并執(zhí)行HMSET操作。
返回哈希表key中給定域field的值。
返回哈希表key中,一個或多個給定域的值。
如果給定的域不存在于哈希表,那么返回一個nil值。
因為不存在的key被當作一個空哈希表來處理,所以對一個不存在的key進行HMGET操作將返回一個只帶有nil值的表。
返回哈希表key中,所有的域和值。
在返回值里,緊跟每個域名(field name)之后是域的值(value),所以返回值的長度是哈希表大小的兩倍。
刪除哈希表key中的一個或多個指定域,不存在的域將被忽略。
注解:在Redis2.4以下的版本里,HDEL每次只能刪除單個域,如果你需要在一個原子時間內(nèi)刪除多個域,請將命令包含在MULTI/ EXEC塊內(nèi)。
返回哈希表key中域的數(shù)量。
查看哈希表key中,給定域field是否存在。
為哈希表key中的域field的值加上增量increment。
增量也可以為負數(shù),相當于對給定域進行減法操作。
如果key不存在,一個新的哈希表被創(chuàng)建并執(zhí)行HINCRBY命令。
如果域field不存在,那么在執(zhí)行命令前,域的值被初始化為0。
對一個儲存字符串值的域field執(zhí)行HINCRBY命令將造成一個錯誤。
本操作的值限制在64位(bit)有符號數(shù)字表示之內(nèi)。
返回哈希表key中的所有域。
返回哈希表key中的所有值。
頭元素和尾元素
頭元素指的是列表左端/前端第一個元素,尾元素指的是列表右端/后端第一個元素。
舉個例子,列表list包含三個元素:x, y, z,其中x是頭元素,而z則是尾元素。
空列表
指不包含任何元素的列表,Redis將不存在的key也視為空列表。
將一個或多個值value插入到列表key的表頭。
如果有多個value值,那么各個value值按從左到右的順序依次插入到表頭:比如對一個空列表(mylist)執(zhí)行LPUSH mylist a b c,則結果列表為c b a,等同于執(zhí)行執(zhí)行命令LPUSH mylist a、LPUSH mylist b、LPUSH mylist c。
如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行LPUSH操作。
當key存在但不是列表類型時,返回一個錯誤。
注解:在Redis 2.4版本以前的LPUSH命令,都只接受單個value值。
將值value插入到列表key的表頭,當且僅當key存在并且是一個列表。
和LPUSH命令相反,當key不存在時,LPUSHX命令什么也不做。
將一個或多個值value插入到列表key的表尾。
如果有多個value值,那么各個value值按從左到右的順序依次插入到表尾:比如對一個空列表(mylist)執(zhí)行RPUSH mylist a b c,則結果列表為a b c,等同于執(zhí)行命令RPUSHmylist a、RPUSH mylist b、RPUSH mylist c。
如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行RPUSH操作。
當key存在但不是列表類型時,返回一個錯誤。
注解:在Redis 2.4版本以前的RPUSH命令,都只接受單個value值。
將值value插入到列表key的表尾,當且僅當key存在并且是一個列表。
和RPUSH命令相反,當key不存在時,RPUSHX命令什么也不做。
移除并返回列表key的頭元素。
移除并返回列表key的尾元素。
BLPOP是列表的阻塞式(blocking)彈出原語。
它是LPOP命令的阻塞版本,當給定列表內(nèi)沒有任何元素可供彈出的時候,連接將被BLPOP命令阻塞,直到等待超時或發(fā)現(xiàn)可彈出元素為止。
當給定多個key參數(shù)時,按參數(shù)key的先后順序依次檢查各個列表,彈出第一個非空列表的頭元素。
非阻塞行為
當BLPOP被調(diào)用時,如果給定key內(nèi)至少有一個非空列表,那么彈出遇到的第一個非空列表的頭元素,并和被彈出元素所屬的列表的名字一起,組成結果返回給調(diào)用者。
當存在多個給定key時,BLPOP按給定key參數(shù)排列的先后順序,依次檢查各個列表。
假設現(xiàn)在有job、 command和request三個列表,其中job不存在,command和request都持有非空列表??紤]以下命令:
BLPOP job command request 0
BLPOP保證返回的元素來自command,因為它是按”查找job -> 查找command -> 查找request“這樣的順序,第一個找到的非空列表。
阻塞行為
如果所有給定key都不存在或包含空列表,那么BLPOP命令將阻塞連接,直到等待超時,或有另一個客戶端對給定key的任意一個執(zhí)行LPUSH或RPUSH命令為止。
超時參數(shù)timeout接受一個以秒為單位的數(shù)字作為值。超時參數(shù)設為0表示阻塞時間可以無限期延長(block indefinitely) 。
相同的key被多個客戶端同時阻塞
在MULTI/EXEC事務中的BLPOP
BLPOP可以用于流水線(pipline,批量地發(fā)送多個命令并讀入多個回復),但把它用在MULTI/EXEC塊當中沒有意義。因為這要求整個服務器被阻塞以保證塊執(zhí)行時的原子性,該行為阻止了其他客戶端執(zhí)行LPUSH或RPUSH命令。
因此,一個被包裹在MULTI/EXEC塊內(nèi)的BLPOP命令,行為表現(xiàn)得就像LPOP一樣,對空列表返回nil,對非空列表彈出列表元素,不進行任何阻塞操作。
時間復雜度:O(1)返回值:
BRPOP是列表的阻塞式(blocking)彈出原語。
它是RPOP命令的阻塞版本,當給定列表內(nèi)沒有任何元素可供彈出的時候,連接將被BRPOP命令阻塞,直到等待超時或發(fā)現(xiàn)可彈出元素為止。
當給定多個key參數(shù)時,按參數(shù)key的先后順序依次檢查各個列表,彈出第一個非空列表的尾部元素。
關于阻塞操作的更多信息,請查看BLPOP命令,BRPOP除了彈出元素的位置和BLPOP不同之外,其他表現(xiàn)一致。
返回列表key的長度。
如果key不存在,則key被解釋為一個空列表,返回0.
如果key不是列表類型,返回一個錯誤。
返回列表key中指定區(qū)間內(nèi)的元素,區(qū)間以偏移量start和stop指定。
下標(index)參數(shù)start和stop都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。
你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。
注意LRANGE命令和編程語言區(qū)間函數(shù)的區(qū)別
假如你有一個包含一百個元素的列表,對該列表執(zhí)行LRANGE list 0 10,結果是一個包含11個元素的列表,這表明stop下標也在LRANGE命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語言的區(qū)間函數(shù)可能不一致,比如Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標
超出范圍的下標值不會引起錯誤。
如果start下標比列表的最大下標end(LLEN list減去1)還要大,或者start > stop,LRANGE返回一個空列表。
如果stop下標比end下標還要大,Redis將stop的值設置為end。
根據(jù)參數(shù)count的值,移除列表中與參數(shù)value相等的元素。
將列表key下標為index的元素的值甚至為value。
更多信息請參考LINDEX操作。
當index參數(shù)超出范圍,或對一個空列表(key不存在)進行LSET時,返回一個錯誤。
對一個列表進行修剪(trim),就是說,讓列表只保留指定區(qū)間內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除。
舉個例子,執(zhí)行命令LTRIM list 0 2,表示只保留列表list的前三個元素,其余元素全部刪除。
下標(index)參數(shù)start和stop都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。
你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。
當key不是列表類型時,返回一個錯誤。
LTRIM命令通常和LPUSH命令或RPUSH命令配合使用,舉個例子:
這個例子模擬了一個日志程序,每次將最新日志newest_log放到log列表中,并且只保留最新的100項。注意當這樣使用LTRIM命令時,時間復雜度是O(1),因為平均情況下,每次只有一個元素被移除。
注意LTRIM命令和編程語言區(qū)間函數(shù)的區(qū)別
假如你有一個包含一百個元素的列表list,對該列表執(zhí)行LTRIM list 0 10,結果是一個包含11個元素的列表,這表明stop下標也在LTRIM命令的取值范圍之內(nèi)(閉區(qū)間),這和某些語言的區(qū)間函數(shù)可能不一致,比如Ruby的Range.new、Array#slice和Python的range()函數(shù)。
超出范圍的下標
超出范圍的下標值不會引起錯誤。
如果start下標比列表的最大下標end(LLEN list減去1)還要大,或者start > stop,LTRIM返回一個空列表(因為LTRIM已經(jīng)將整個列表清空)。
如果stop下標比end下標還要大,Redis將stop的值設置為end。
返回列表key中,下標為index的元素。
下標(index)參數(shù)start和stop都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。
你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。
如果key不是列表類型,返回一個錯誤。
將值value插入到列表key當中,位于值pivot之前或之后。
當pivot不存在于列表key時,不執(zhí)行任何操作。
當key不存在時,key被視為空列表,不執(zhí)行任何操作。
如果key不是列表類型,返回一個錯誤。
命令RPOPLPUSH在一個原子時間內(nèi),執(zhí)行以下兩個動作:
- 將列表source中的最后一個元素(尾元素)彈出,并返回給客戶端。
- 將source彈出的元素插入到列表destination,作為destination列表的的頭元素。
舉個例子,你有兩個列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,執(zhí)行RPOPLPUSH source destination之后,source列表包含元素a, b,destination列表包含元素c, x, y, z ,并且元素c被返回。
如果source不存在,值nil被返回,并且不執(zhí)行其他動作。
如果source和destination相同,則列表中的表尾元素被移動到表頭,并返回該元素,可以把這種特殊情況視作列表的旋轉(rotation)操作。
設計模式: 一個安全的隊列
Redis的列表經(jīng)常被用作隊列(queue),用于在不同程序之間有序地交換消息(message)。一個程序(稱之為生產(chǎn)者,producer)通過LPUSH命令將消息放入隊列中,而另一個程序(稱之為消費者,consumer)通過RPOP命令取出隊列中等待時間最長的消息。
不幸的是,在這個過程中,一個消費者可能在獲得一個消息之后崩潰,而未執(zhí)行完成的消息也因此丟失。
使用RPOPLPUSH命令可以解決這個問題,因為它在返回一個消息之余,還將該消息添加到另一個列表當中,另外的這個列表可以用作消息的備份表:假如一切正常,當消費者完成該消息的處理之后,可以用LREM命令將該消息從備份表刪除。
另一方面,助手(helper)程序可以通過監(jiān)視備份表,將超過一定處理時限的消息重新放入隊列中去(負責處理該消息的消費者可能已經(jīng)崩潰),這樣就不會丟失任何消息了。
BRPOPLPUSH是RPOPLPUSH的阻塞版本,當給定列表source不為空時,BRPOPLPUSH的表現(xiàn)和RPOPLPUSH一樣。
當列表source為空時,BRPOPLPUSH命令將阻塞連接,直到等待超時,或有另一個客戶端對source執(zhí)行LPUSH或RPUSH命令為止。
超時參數(shù)timeout接受一個以秒為單位的數(shù)字作為值。超時參數(shù)設為0表示阻塞時間可以無限期延長(block indefinitely) 。
更多相關信息,請參考RPOPLPUSH命令。
附錄,常用集合運算:
A = {'a', 'b', 'c'}
B = {'a', 'e', 'i', 'o', 'u'}inter(x, y): 交集,在集合x和集合y中都存在的元素。inter(A, B) = {'a'}union(x, y): 并集,在集合x中或集合y中的元素,如果一個元素在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ù),一個集合中元素的數(shù)量。card(A) = 3空集: 基數(shù)為0的集合。
將一個或多個member元素加入到集合key當中,已經(jīng)存在于集合的member元素將被忽略。
假如key不存在,則創(chuàng)建一個只包含member元素作成員的集合。
當key不是集合類型時,返回一個錯誤。
注解:在Redis2.4版本以前,SADD只接受單個member值。
移除集合key中的一個或多個member元素,不存在的member元素會被忽略。
當key不是集合類型,返回一個錯誤。
注解:在Redis2.4版本以前,SREM只接受單個member值。
返回集合key中的所有成員。
判斷member元素是否是集合key的成員。
返回集合key的基數(shù)(集合中元素的數(shù)量)。
將member元素從source集合移動到destination集合。
SMOVE是原子性操作。
如果source集合不存在或不包含指定的member元素,則SMOVE命令不執(zhí)行任何操作,僅返回0。否則,member元素從source集合中被移除,并添加到destination集合中去。
當destination集合已經(jīng)包含member元素時,SMOVE命令只是簡單地將source集合中的member元素刪除。
當source或destination不是集合類型時,返回一個錯誤。
移除并返回集合中的一個隨機元素。
也可以參考:如果只想獲取一個隨機元素,但不想該元素從集合中被移除的話,可以使用SRANDMEMBER命令。
返回集合中的一個隨機元素。
該操作和SPOP相似,但SPOP將隨機元素從集合中移除并返回,而SRANDMEMBER則僅僅返回隨機元素,而不對集合進行任何改動。
返回一個集合的全部成員,該集合是所有給定集合的交集。
不存在的key被視為空集。
當給定集合當中有一個空集時,結果也為空集(根據(jù)集合運算定律)。
此命令等同于SINTER,但它將結果保存到destination集合,而不是簡單地返回結果集。
如果destination集合已經(jīng)存在,則將其覆蓋。
destination可以是key本身。
返回一個集合的全部成員,該集合是所有給定集合的并集。
不存在的key被視為空集。
此命令等同于SUNION,但它將結果保存到destination集合,而不是簡單地返回結果集。
如果destination已經(jīng)存在,則將其覆蓋。
destination可以是key本身。
返回一個集合的全部成員,該集合是所有給定集合的差集 。
不存在的key被視為空集。
此命令等同于SDIFF,但它將結果保存到destination集合,而不是簡單地返回結果集。
如果destination集合已經(jīng)存在,則將其覆蓋。
destination可以是key本身。
將一個或多個member元素及其score值加入到有序集key當中。
如果某個member已經(jīng)是有序集的成員,那么更新這個member的score值,并通過重新插入這個member元素,來保證該member在正確的位置上。
score值可以是整數(shù)值或雙精度浮點數(shù)。
如果key不存在,則創(chuàng)建一個空的有序集并執(zhí)行ZADD操作。
當key存在但不是有序集類型時,返回一個錯誤。
對有序集的更多介紹請參見sorted set。
注解:在Redis2.4版本以前,ZADD每次只能添加一個元素。
移除有序集key中的一個或多個成員,不存在的成員將被忽略。
當key存在但不是有序集類型時,返回一個錯誤。
注解:在Redis2.4版本以前,ZREM每次只能刪除一個元素。
返回有序集key的基數(shù)。
返回有序集key中,score值在min和max之間(默認包括score值等于min或max)的成員。
關于參數(shù)min和max的詳細使用方法,請參考ZRANGEBYSCORE命令。
返回有序集key中,成員member的score值。
如果member元素不是有序集key的成員,或key不存在,返回nil。
為有序集key的成員member的score值加上增量increment。
你也可以通過傳遞一個負數(shù)值increment,讓score減去相應的值,比如ZINCRBY key -5 member,就是讓member的score值減去5。
當key不存在,或member不是key的成員時,ZINCRBY key increment member等同于ZADD key increment member。
當key不是有序集類型時,返回一個錯誤。
score值可以是整數(shù)值或雙精度浮點數(shù)。
返回有序集key中,指定區(qū)間內(nèi)的成員。
其中成員的位置按score值遞增(從小到大)來排序。
具有相同score值的成員按字典序(lexicographical order)來排列。
如果你需要成員按score值遞減(從大到小)來排列,請使用ZREVRANGE命令。
返回有序集key中,指定區(qū)間內(nèi)的成員。
除了成員按score值遞減的次序排列這一點外,ZREVRANGE命令的其他方面和ZRANGE命令一樣。
返回有序集key中,所有score值介于min和max之間(包括等于min或max)的成員。有序集成員按score值遞增(從小到大)次序排列。
具有相同score值的成員按字典序(lexicographical order)來排列(該屬性是有序集提供的,不需要額外的計算)。
可選的LIMIT參數(shù)指定返回結果的數(shù)量及區(qū)間(就像SQL中的SELECT LIMIT offset, count),注意當offset很大時,定位offset的操作可能需要遍歷整個有序集,此過程最壞復雜度為O(N)時間。
區(qū)間及無限
min和max可以是-inf和+inf,這樣一來,你就可以在不知道有序集的最低和最高score值的情況下,使用ZRANGEBYSCORE這類命令。
默認情況下,區(qū)間的取值使用閉區(qū)間(小于等于或大于等于),你也可以通過給參數(shù)前增加(符號來使用可選的開區(qū)間(小于或大于)。
舉個例子:
返回所有符合條件1 < score <= 5的成員;
返回所有符合條件5 < score < 10的成員。
返回有序集key中,score值介于max和min之間(默認包括等于max或min)的所有的成員。有序集成員按score值遞減(從大到小)的次序排列。
具有相同score值的成員按字典序的反序(reverse lexicographical order)排列。
除了成員按score值遞減的次序排列這一點外,ZREVRANGEBYSCORE命令的其他方面和ZRANGEBYSCORE命令一樣。
返回有序集key中成員member的排名。其中有序集成員按score值遞增(從小到大)順序排列。
排名以0為底,也就是說,score值最小的成員排名為0。
使用ZREVRANK命令可以獲得成員按score值遞減(從大到小)排列的排名。
返回有序集key中成員member的排名。其中有序集成員按score值遞減(從大到小)排序。
排名以0為底,也就是說,score值最大的成員排名為0。
使用ZRANK命令可以獲得成員按score值遞增(從小到大)排列的排名。
移除有序集key中,指定排名(rank)區(qū)間內(nèi)的所有成員。
區(qū)間分別以下標參數(shù)start和stop指出,包含start和stop在內(nèi)。
移除有序集key中,所有score值介于min和max之間(包括等于min或max)的成員。
自版本2.1.6開始,score值等于min或max的成員也可以不包括在內(nèi),詳情請參見ZRANGEBYSCORE命令。
計算給定的一個或多個有序集的交集,其中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該交集(結果集)儲存到destination。
默認情況下,結果集中某個成員的score值是所有給定集下該成員score值之和。
關于WEIGHTS和AGGREGATE選項的描述,參見ZUNIONSTORE命令。
計算給定的一個或多個有序集的并集,其中給定key的數(shù)量必須以numkeys參數(shù)指定,并將該并集(結果集)儲存到destination。
默認情況下,結果集中某個成員的score值是所有給定集下該成員score值之和。
WEIGHTS
使用WEIGHTS選項,你可以為每個給定有序集分別指定一個乘法因子(multiplication factor),每個給定有序集的所有成員的score值在傳遞給聚合函數(shù)(aggregation function)之前都要先乘以該有序集的因子。
如果沒有指定WEIGHTS選項,乘法因子默認設置為1。
AGGREGATE
使用AGGREGATE選項,你可以指定并集的結果集的聚合方式。
默認使用的參數(shù)SUM,可以將所有集合中某個成員的score值之和作為結果集中該成員的score值;使用參數(shù)MIN,可以將所有集合中某個成員的最小score值作為結果集中該成員的score值;而參數(shù)MAX則是將所有集合中某個成員的最大score值作為結果集中該成員的score值。
將信息 message 發(fā)送到指定的頻道 channel 。
訂閱給定頻道的信息。
訂閱符合給定模式的頻道。
每個模式以 * 作為匹配符,比如 huangz* 匹配所有以 huangz 開頭的頻道( huangzmsg 、 huangz-blog 、 huangz.tweets 等等), news.* 匹配所有以 news. 開頭的頻道(news.it 、 news.global.today 等等),諸如此類。
警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
警告:此命令在新版 Redis 中似乎已經(jīng)被廢棄?
監(jiān)視一個(或多個) key ,如果在事務執(zhí)行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。
UNWATCH
取消 WATCH 命令對所有 key 的監(jiān)視。
如果在執(zhí)行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被執(zhí)行了的話,那么就不需要再執(zhí)行 UNWATCH 了。
因為 EXEC 命令會執(zhí)行事務,因此 WATCH 命令的效果已經(jīng)產(chǎn)生了;而 DISCARD 命令在取消事務的同時也會取消所有對 key 的監(jiān)視,因此這兩個命令執(zhí)行之后,就沒有必要執(zhí)行 UNWATCH 了。
MULTI
標記一個事務塊的開始。
事務塊內(nèi)的多條命令會按照先后順序被放進一個隊列當中,最后由 EXEC 命令在一個原子時間內(nèi)執(zhí)行。
EXEC
執(zhí)行所有事務塊內(nèi)的命令。
假如某個(或某些) key 正處于 WATCH 命令的監(jiān)視之下,且事務塊中有和這個(或這些) key 相關的命令,那么 EXEC 命令只在這個(或這些) key 沒有被其他命令所改動的情況下執(zhí)行并生效,否則該事務被打斷(abort)。
DISCARD
取消事務,放棄執(zhí)行事務塊內(nèi)的所有命令。
如果正在使用 WATCH 命令監(jiān)視某個(或某些) key ,那么取消所有監(jiān)視,等同于執(zhí)行命令 UNWATCH 。
通過設置配置文件中 requirepass 項的值(使用命令 CONFIG SET requirepass password ),可以使用密碼來保護 Redis 服務器。
如果開啟了密碼保護的話,在每次連接 Redis 服務器之后,就要使用 AUTH 命令解鎖,解鎖之后才能使用其他 Redis 命令。
如果 AUTH 命令給定的密碼 password 和配置文件中的密碼相符的話,服務器會返回 OK 并開始接受命令輸入。
反之,如果密碼不匹配的話,服務器將返回一個錯誤,并要求客戶端需重新輸入密碼。
警告:因為 Redis 高性能的特點,在很短時間內(nèi)嘗試猜測非常多個密碼是有可能的,因此請確保使用的密碼足夠復雜和足夠長,以免遭受密碼猜測攻擊。
PING
客戶端向服務器發(fā)送一個 PING ,然后服務器返回客戶端一個 PONG 。
通常用于測試與服務器的連接是否仍然生效,或者用于測量延遲值。
切換到指定的數(shù)據(jù)庫,數(shù)據(jù)庫索引號用數(shù)字值指定,以 0 作為起始索引值。
新的鏈接總是使用 0 號數(shù)據(jù)庫。
打印一個特定的信息 message ,測試時使用。
QUIT
請求服務器關閉與當前客戶端的連接。
一旦所有等待中的回復(如果有的話)順利寫入到客戶端,連接就會被關閉。
BGREWRITEAOF
異步(Asynchronously)重寫 AOF 文件以反應當前數(shù)據(jù)庫的狀態(tài)。
即使 BGREWRITEAOF 命令執(zhí)行失敗,舊 AOF 文件中的數(shù)據(jù)也不會因此丟失或改變。
在后臺異步保存當前數(shù)據(jù)庫的數(shù)據(jù)到磁盤。
BGSAVE 命令執(zhí)行之后立即返回 OK ,然后 Redis fork出一個新子進程,原來的 Redis 進程(父進程)繼續(xù)處理客戶端請求,而子進程則負責將數(shù)據(jù)保存到磁盤,然后退出。
客戶端可以通過 LASTSAVE 命令查看相關信息,判斷 BGSAVE 命令是否執(zhí)行成功。
SAVE
同步保存當前數(shù)據(jù)庫的數(shù)據(jù)到磁盤。
LASTSAVE
返回最近一次 Redis 成功執(zhí)行保存操作的時間點( SAVE 、 BGSAVE 等),以 UNIX 時間戳格式表示。
DBSIZE
返回當前數(shù)據(jù)庫的 key 的數(shù)量。
SLAVEOF 命令用于在 Redis 運行時動態(tài)地修改復制(replication)功能的行為。
通過執(zhí)行 SLAVEOF host port 命令,可以將當前服務器轉變?yōu)橹付ǚ掌鞯膹膶俜掌?slave server)。
如果當前服務器已經(jīng)是某個主服務器(master server)的從屬服務器,那么執(zhí)行 SLAVEOF host port 將使當前服務器停止對舊主服務器的同步,丟棄舊數(shù)據(jù)集,轉而開始對新主服務器進行同步。
另外,對一個從屬服務器執(zhí)行命令 SLAVEOF NO ONE 將使得這個從屬服務器關閉復制功能,并從從屬服務器轉變回主服務器,原來同步所得的數(shù)據(jù)集不會被丟棄。
利用“ SLAVEOF NO ONE 不會丟棄同步所得數(shù)據(jù)集”這個特性,可以在主服務器失敗的時候,將從屬服務器用作新的主服務器,從而實現(xiàn)無間斷運行。
FLUSHALL
清空整個 Redis 服務器的數(shù)據(jù)(刪除所有數(shù)據(jù)庫的所有 key)。
此命令從不失敗。
FLUSHDB
清空當前數(shù)據(jù)庫中的所有 key 。
此命令從不失敗。
SHUTDOWN
SHUTDOWN 命令執(zhí)行以下操作:
如果持久化被打開的話, SHUTDOWN 命令會保證服務器正常關閉而不丟失任何數(shù)據(jù)。
假如只是單純地執(zhí)行 SAVE 命令,然后再執(zhí)行 QUIT 命令,則沒有這一保證 —— 因為在執(zhí)行 SAVE 之后、執(zhí)行 QUIT 之前的這段時間中間,其他客戶端可能正在和服務器進行通訊,這時如果執(zhí)行 QUIT 就會造成數(shù)據(jù)丟失。
什么是 SLOWLOG
Slow log 是 Redis 用來記錄查詢執(zhí)行時間的日志系統(tǒng)。
查詢執(zhí)行時間指的是不包括像客戶端響應(talking)、發(fā)送回復等 IO 操作,而單單是執(zhí)行一個查詢命令所耗費的時間。
另外,slow log 保存在內(nèi)存里面,讀寫速度非???,因此你可以放心地使用它,不必擔心因為開啟 slow log 而損害 Redis 的速度。
設置 SLOWLOG
Slow log 的行為由兩個配置參數(shù)(configuration parameter)指定,可以通過改寫 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令對它們動態(tài)地進行修改。
第一個選項是 slowlog-log-slower-then ,它決定要對執(zhí)行時間大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的查詢進行記錄。
比如執(zhí)行以下命令將讓 slow log 記錄所有查詢時間大于等于 100 微秒的查詢:
CONFIG SET slowlog-log-slower-then 100 ,
而以下命令記錄所有查詢時間大于 1000 微秒的查詢:
CONFIG SET slowlog-log-slower-then 1000 。
另一個選項是 slowlog-max-len ,它決定 slow log 最多能保存多少條日志, slow log 本身是一個 LIFO 隊列,當隊列大小超過 slowlog-max-len 時,最舊的一條日志將被刪除,而最新的一條日志加入到 slow log ,以此類推。
以下命令讓 slow log 最多保存 1000 條日志:
CONFIG SET slowlog-max-len 1000 。
使用 CONFIG GET 命令可以查詢兩個選項的當前值:
查看 slow log
要查看 slow log ,可以使用 SLOWLOG GET 或者 SLOWLOG GET number 命令,前者打印所有 slow log ,最大長度取決于 slowlog-max-len 選項的值,而 SLOWLOG GET number 則只打印指定數(shù)量的日志。
最新的日志會最先被打?。?/p>
日志的唯一 id 只有在 Redis 服務器重啟的時候才會重置,這樣可以避免對日志的重復處理(比如你可能會想在每次發(fā)現(xiàn)新的慢查詢時發(fā)郵件通知你)。
查看當前日志的數(shù)量
使用命令 SLOWLOG LEN 可以查看當前日志的數(shù)量。
請注意這個值和 slower-max-len 的區(qū)別,它們一個是當前日志的數(shù)量,一個是允許記錄的最大日志的數(shù)量。
清空日志
使用命令 SLOWLOG RESET 可以清空 slow log 。
時間復雜度:O(1)
返回值:取決于不同命令,返回不同的值。
INFO
返回關于 Redis 服務器的各種信息和統(tǒng)計值。
CONFIG GET 命令用于取得運行中的 Redis 服務器的配置參數(shù)(configuration parameters),不過并非所有配置參數(shù)都被 CONFIG GET 命令所支持。
CONFIG GET 接受單個參數(shù) parameter 作為搜索關鍵字,查找所有匹配的配置參數(shù),其中參數(shù)和值以“鍵-值對”(key-value pairs)的方式排列。
比如執(zhí)行 CONFIG GET s* 命令,服務器就會返回所有以 s 開頭的配置參數(shù)及參數(shù)的值:
如果你只是尋找特定的某個參數(shù)的話,你當然也可以直接指定參數(shù)的名字:
使用命令 CONFIG GET * ,可以列出 CONFIG GET 命令支持的所有參數(shù):
所有被 CONFIG SET 所支持的配置參數(shù)都可以在配置文件 redis.conf 中找到,不過 CONFIG GET 和 CONFIG SET 使用的格式和 redis.conf 文件所使用的格式有以下兩點不同:
CONFIG SET 命令可以動態(tài)地調(diào)整 Redis 服務器的配置(configuration)而無須重啟。
你可以使用它修改配置參數(shù),或者改變 Redis 的持久化(Persistence)方式。
CONFIG SET 可以修改的配置參數(shù)可以使用命令 CONFIG GET * 來列出,所有被 CONFIG SET 修改的配置參數(shù)都會立即生效。
關于 CONFIG SET 命令的更多消息,請參見命令 CONFIG GET 的說明。
關于如何使用 CONFIG SET 命令修改 Redis 持久化方式,請參見 Redis Persistence 。
重置 INFO 命令中的某些統(tǒng)計數(shù)據(jù),包括:
返回給定 key 的調(diào)試信息。
令 Redis 服務器崩潰,調(diào)試用。
MONITOR
實時打印出 Redis 服務器接收到的命令,調(diào)試用。
YNC
用于復制功能(replication)的內(nèi)部命令。
聯(lián)系客服