phpredis是redis的php的一个扩展,效率是至关高有链表排序功能,对建立内存级的模块业务关系php
颇有用;如下是redis官方提供的命令使用技巧:前端
下载地址以下:python
https://github.com/owlient/phpredis(支持redis 2.0.4)git
Redis::__construct构造函数
$redis = new Redis();github
connect, open 连接redis服务
参数
host: string,服务地址
port: int,端口号
timeout: float,连接时长 (可选, 默认为 0 ,不限连接时间)
注: 在redis.conf中也有时间,默认为300web
pconnect, popen 不会主动关闭的连接
参考上面redis
setOption 设置redis模式算法
getOption 查看redis设置的模式sql
ping 查看链接状态数据库
KEY相关操做
DEL
移除给定的一个或多个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的速度很是快,但在一个大的数据库中使用它仍然可能形成性能问题,若是你须要从一个数据集中查找特定的key,你最好仍是用集合(Set)。
//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 )
RANDOMKEY
从当前数据库中随机返回(不删除)一个key。
//RANDOMKEY
$redis->FLUSHALL();
# 状况1:数据库不为空
$array_mset_randomkey=array('fruit'=>'apple',
'drink'=>'beer',
'food'=>'cookis');
$redis->mset($array_mset_randomkey);
echo $redis->randomkey();
print_r($redis->keys('*')); # 查看数据库内全部key,证实RANDOMKEY并不删除key//Array ( [0] => food [1] => drink [2] => fruit )
# 状况2:数据库为空
$redis->flushdb(); # 删除当前数据库全部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)
MOVE
MOVE key db
将当前数据库(默认为0)的key移动到给定的数据库db当中。
若是当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定key,或者key不存在于当前数据库,那么MOVE没有任何效果。
所以,也能够利用这一特性,将MOVE看成锁(locking)原语。
//MOVE
echo '<br><br>MOVE<br>';
# 状况1: key存在于当前数据库
$redis->SELECT(0); # redis默认使用数据库0,为了清晰起见,这里再显式指定一次。//OK
$redis->SET('song',"secret base - Zone"); //OK
var_dump ($redis->MOVE('song',1)); # 将song移动到数据库1 //bool(true)
# 状况2:当key不存在的时候
$redis->SELECT(1);
var_dump ($redis->EXISTS('fake_key'));//bool(false);
var_dump($redis->MOVE('fake_key', 0)); # 试图从数据库1移动一个不存在的key到数据库0,失败) //bool(false)
$redis->SELECT(0); # 使用数据库0
var_dump($redis->EXISTS('fake_key')); # 证明fake_key不存在 //bool(false)
# 状况3:当源数据库和目标数据库有相同的key时
$redis->SELECT(0); # 使用数据库0
$redis->SET('favorite_fruit',"banana");
$redis->SELECT(1); # 使用数据库1
$redis->SET('favorite_fruit',"apple");
$redis->SELECT(0); # 使用数据库0,并试图将favorite_fruit移动到数据库1
var_dump($redis->MOVE('favorite_fruit',1)); # 由于两个数据库有相同的key,MOVE失败 //return bool(false)
echo $redis->GET('favorite_fruit'); # 数据库0的favorite_fruit没变 //return banana
$redis->SELECT(1);
echo $redis->GET('favorite_fruit'); # 数据库1的favorite_fruit也是 //return apple
RENAME
将key更名为newkey。
当key和newkey相同或者key不存在时,返回一个错误。
当newkey已经存在时,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
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命令接受的时间参数是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命令容许从内部察看给定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)状态 //return WOW
//echo $redis->OBJECT('IDLETIME','game'); # 再也不处于空转 //(integer) 0
var_dump($redis->OBJECT('ENCODING','game')); # 字符串的编码方式 //string(3) "raw"
$redis->SET('phone',15820123123); # 大的数字也被编码为字符串
var_dump($redis->OBJECT('ENCODING','phone')); //string(3) "raw"
$redis->SET('age',20); # 短数字被编码为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)
SORT
排序,分页等
参数
array(
‘by’ => ‘some_pattern_*’,
‘limit’ => array(0, 1),
‘get’ => ‘some_other_pattern_*’ or an array of patterns,
‘sort’ => ‘asc’ or ‘desc’,
‘alpha’ => TRUE,
‘store’ => ‘external-key’
)
返回或保存给定列表、集合、有序集合key中通过排序的元素。
排序默认以数字做为对象,值被解释为双精度浮点数,而后进行比较。
通常SORT用法
最简单的SORT使用方法是SORT key。
假设today_cost是一个保存数字的列表,SORT命令默认会返回该列表值的递增(从小到大)排序结果。
# 将数据一一加入到列表中
$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" }
当数据集中保存的是字符串值时,你能够用ALPHA修饰符(modifier)进行排序。
# 将数据一一加入到列表中
$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环境变量的话,Redis能识别UTF-8编码。
如下例子返回排序结果的前5个对象(offset为0表示没有元素被跳过)。
# 将数据一一加入到列表中
$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做为权重来比较元素,代替默认的对比方法。
假设如今有用户(user)数据以下:
id name level
-------------------------------
1 admin 9999
2 huangz 10
59230 jack 3
222 hacker 9999
id数据保存在key名为user_id的列表中。
name数据保存在key名为user_name_{id}的列表中
level数据保存在user_level_{id}的key中。
# 先将要使用的数据加入到数据库中
# 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。
好比你不但但愿获取用户名,还但愿连用户的密码也一并列出,可使用如下命令:
# 先添加一些测试数据
$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还有一个特殊的规则——"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参数,不排序,只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做为参数,排序结果将以列表的形式被保存到这个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操做的一个缓存。
这样就没必要频繁地调用SORT操做了,只有当结果集过时时,才须要再调用一次SORT操做。
有时候为了正确实现这一用法,你可能须要加锁以免多个客户端同时进行缓存重建(也就是多个客户端,同一时间进行SORT操做,并保存为结果集),具体参见SETNX命令。
在GET和BY中使用哈希表
可使用哈希表特有的语法,在SORT命令中进行GET和BY操做。
# 假设如今咱们的用户表新增了一个serial项来为做为每一个用户的序列号
# 序列号以哈希表的形式保存在serial哈希域内。
$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操做和上面介绍的其余数据结构(列表、集合、有序集合)没有什么不一样。
SET
将字符串值value关联到key。
若是key已经持有其余值,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已经存在,则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,说明客户端已经得到了锁,key设置的unix时间则指定了锁失效的时间。以后客户端能够经过DEL lock.foo来释放锁。
若是SETNX返回0,说明key已经被其余客户端上锁了。若是锁是非阻塞(non blocking lock)的,咱们能够选择返回调用,或者进入一个重试循环,直到成功得到锁或重试超时(timeout)。
处理死锁(deadlock)
上面的锁算法有一个问题:若是由于客户端失败、崩溃或其余缘由致使没有办法释放锁的话,怎么办?
这种情况能够经过检测发现——由于上锁的key保存的是unix时间戳,假如key值的时间戳小于当前的时间戳,表示锁已经再也不有效。
可是,当有多个客户端同时检测一个锁是否过时并尝试释放它的时候,咱们不能简单粗暴地删除死锁的key,再用SETNX上锁,由于这时竞争条件(race condition)已经造成了:
幸亏,如下算法能够避免以上问题。来看看咱们聪明的C4客户端怎么办:
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
警告
为了让这个加锁算法更健壮,得到锁的客户端应该经常检查过时时间以避免锁因诸如DEL等命令的执行而被意外解开,由于客户端失败的状况很是复杂,不只仅是崩溃这么简单,还多是客户端由于某些操做被阻塞了至关长时间,紧接着DEL命令被尝试执行(但这时锁却在另外的客户端手上)。
将值value关联到key,并将key的生存时间设为seconds(以秒为单位)。
若是key 已经存在,SETEX命令将覆写旧值。
这个命令相似于如下两个命令:
$redis->SET('key', 'value');
$redis->EXPIRE('key','seconds'); # 设置生存时间
不一样之处是,SETEX是一个原子性(atomic)操做,关联值和设置生存时间两个动做会在同一时间内完成,该命令在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已经存在,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参数覆写(Overwrite)给定key所储存的字符串值,从偏移量offset开始。
不存在的key看成空白字符串处理。
SETRANGE命令会确保字符串足够长以便将value设置在指定的偏移量上,若是给定key原来储存的字符串长度比偏移量小(好比字符串只有5个字符长,但你设置的offset是10),那么原字符和偏移量之间的空白将用零比特(zerobytes,"\x00")来填充。
注意你能使用的最大偏移量是2^29-1(536870911),由于Redis的字符串被限制在512兆(megabytes)内。若是你须要使用比这更大的空间,你得使用多个key。
警告
当生成一个很长的字符串时,Redis须要分配内存空 间,该操做有时候可能会形成服务器阻塞(block)。在2010年的Macbook Pro上,设置偏移量为536870911(512MB内存分配),耗费约300毫秒, 设置偏移量为134217728(128MB内存分配),耗费约80毫秒,设置偏移量33554432(32MB内存分配),耗费约30毫秒,设置偏移量 为8388608(8MB内存分配),耗费约8毫秒。 注意若首次内存分配成功以后,再对同一个key调用SETRANGE操做,无须再从新内存。
模式
由于有了SETRANGE和GETRANGE命令,你能够将Redis字符串用做具备O(1)随机访问时间的线性数组。这在不少真实用例中都是很是快速且高效的储存方式。
# 状况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对。
当发现同名的key存在时,MSET会用新值覆盖旧值,若是你不但愿覆盖同名key,请使用MSETNX命令。
MSET是一个原子性(atomic)操做,全部给定key都在同一时间内被设置,某些给定key被更新而另外一些给定key没有改变的状况,不可能发生。
#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覆盖旧值的例子 可是通过测试覆盖不了
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键已经存在,操做失败 //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已经存在而且是一个字符串,APPEND命令将value追加到key原来的值以后。
若是key不存在,APPEND就简单地将给定key设为value,就像执行SET key value同样。
# 状况1:对不存在的key执行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所关联的字符串值。
若是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在内)。
负数偏移量表示从字符串最后开始计数,-1表示最后一个字符,-2表示倒数第二个,以此类推。
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>'; # 负数索引 //"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组合使用,实现一个有原子性(atomic)复位操做的计数器(counter)。
举例来讲,每次当某个事件发生时,进程可能对一个名为mycount的key调用INCR操做,一般咱们还要在一个原子时间内同时完成得到计数器的值和将计数器值复位为0两个操做。
能够用命令GETSET mycounter 0来实现这一目标。
$redis->SELECT(2);
echo $redis->INCR('mycount').'<br>'; #(integer) 11
if($redis->GET('mycount')>19){
echo $redis->GETSET('mycount', 0).'<br>'; # 一个原子内完成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中储存的数字值增一。
若是key不存在,以0为key的初始值,而后执行INCR操做。
若是值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操做的值限制在64位(bit)有符号数字表示以内。
注解:这是一个针对字符串的操做,由于Redis没有专用的整数类型,因此key内储存的字符串被解释为十进制64位有符号整数来执行INCR操做。
$redis->SET('page_view', 20);
var_dump($redis->INCR('page_view')); //int(21)
var_dump($redis->GET('page_view')); # 数字值在Redis中以字符串的形式保存 //string(2) "21
将key所储存的值加上增量increment。
若是key不存在,以0为key的初始值,而后执行INCRBY命令。
若是值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操做的值限制在64位(bit)有符号数字表示以内。
关于更多递增(increment)/递减(decrement)操做信息,参见INCR命令。
//INCRBY
echo '<br><br>INCRBY<br>';
# 状况1:key存在且是数字值
$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 //经测试 与手册上结果不同,不能直接从bool型转为int型。 return bool(false)
# 状况3:key不是数字值
$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中储存的数字值减一。
若是key不存在,以0为key的初始值,而后执行DECR操做。
若是值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操做的值限制在64位(bit)有符号数字表示以内。
关于更多递增(increment)/递减(decrement)操做信息,参见INCR命令。
//DECR
$redis->SELECT(3);
$redis->flushdb();
echo '<br><br>DECR<br>';
# 状况1:对存在的数字值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:对存在但不是数值的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的初始值,而后执行DECRBY操做。
若是值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操做的值限制在64位(bit)有符号数字表示以内。
关于更多递增(increment)/递减(decrement)操做信息,参见INCR命令。
# 状况1:对存在的数值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参数,能够是0也能够是1。
当key不存在时,自动生成一个新的字符串值。
字符串会增加(grown)以确保它能够将value保存在指定的偏移量上。当字符串值增加时,空白位置以0填充。
offset参数必须大于或等于0,小于2^32(bit映射被限制在512MB内)。
警告:对使用大的offset的SETBIT操做来讲,内存分配可能形成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不存在,一个新的哈希表被建立并进行HSET操做。
若是域field已经存在于哈希表中,旧值将被覆盖。
将哈希表key中的域field的值设置为value,当且仅当域field不存在。
若域field已经存在,该操做无效。
若是key不存在,一个新哈希表被建立并执行HSETNX命令。
同时将多个field - value(域-值)对设置到哈希表key中。
此命令会覆盖哈希表中已存在的域。
若是key不存在,一个空哈希表被建立并执行HMSET操做。
返回哈希表key中给定域field的值。
返回哈希表key中,一个或多个给定域的值。
若是给定的域不存在于哈希表,那么返回一个nil值。
由于不存在的key被看成一个空哈希表来处理,因此对一个不存在的key进行HMGET操做将返回一个只带有nil值的表。
返回哈希表key中,全部的域和值。
在返回值里,紧跟每一个域名(field name)以后是域的值(value),因此返回值的长度是哈希表大小的两倍。
删除哈希表key中的一个或多个指定域,不存在的域将被忽略。
注解:在Redis2.4如下的版本里,HDEL每次只能删除单个域,若是你须要在一个原子时间内删除多个域,请将命令包含在MULTI/ EXEC块内。
返回哈希表key中域的数量。
查看哈希表key中,给定域field是否存在。
为哈希表key中的域field的值加上增量increment。
增量也能够为负数,至关于对给定域进行减法操做。
若是key不存在,一个新的哈希表被建立并执行HINCRBY命令。
若是域field不存在,那么在执行命令前,域的值被初始化为0。
对一个储存字符串值的域field执行HINCRBY命令将形成一个错误。
本操做的值限制在64位(bit)有符号数字表示以内。
返回哈希表key中的全部域。
返回哈希表key中的全部值。
头元素和尾元素
头元素指的是列表左端/前端第一个元素,尾元素指的是列表右端/后端第一个元素。
举个例子,列表list包含三个元素:x, y, z,其中x是头元素,而z则是尾元素。
空列表
指不包含任何元素的列表,Redis将不存在的key也视为空列表。
将一个或多个值value插入到列表key的表头。
若是有多个value值,那么各个value值按从左到右的顺序依次插入到表头:好比对一个空列表(mylist)执行LPUSH mylist a b c,则结果列表为c b a,等同于执行执行命令LPUSH mylist a、LPUSH mylist b、LPUSH mylist c。
若是key不存在,一个空列表会被建立并执行LPUSH操做。
当key存在但不是列表类型时,返回一个错误。
注解:在Redis 2.4版本之前的LPUSH命令,都只接受单个value值。
将值value插入到列表key的表头,当且仅当key存在而且是一个列表。
和LPUSH命令相反,当key不存在时,LPUSHX命令什么也不作。
将一个或多个值value插入到列表key的表尾。
若是有多个value值,那么各个value值按从左到右的顺序依次插入到表尾:好比对一个空列表(mylist)执行RPUSH mylist a b c,则结果列表为a b c,等同于执行命令RPUSHmylist a、RPUSH mylist b、RPUSH mylist c。
若是key不存在,一个空列表会被建立并执行RPUSH操做。
当key存在但不是列表类型时,返回一个错误。
注解:在Redis 2.4版本之前的RPUSH命令,都只接受单个value值。
将值value插入到列表key的表尾,当且仅当key存在而且是一个列表。
和RPUSH命令相反,当key不存在时,RPUSHX命令什么也不作。
移除并返回列表key的头元素。
移除并返回列表key的尾元素。
BLPOP是列表的阻塞式(blocking)弹出原语。
它是LPOP命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,链接将被BLPOP命令阻塞,直到等待超时或发现可弹出元素为止。
当给定多个key参数时,按参数key的前后顺序依次检查各个列表,弹出第一个非空列表的头元素。
非阻塞行为
当BLPOP被调用时,若是给定key内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字一块儿,组成结果返回给调用者。
当存在多个给定key时,BLPOP按给定key参数排列的前后顺序,依次检查各个列表。
假设如今有job、 command和request三个列表,其中job不存在,command和request都持有非空列表。考虑如下命令:
BLPOP job command request 0
BLPOP保证返回的元素来自command,由于它是按”查找job -> 查找command -> 查找request“这样的顺序,第一个找到的非空列表。
阻塞行为
若是全部给定key都不存在或包含空列表,那么BLPOP命令将阻塞链接,直到等待超时,或有另外一个客户端对给定key的任意一个执行LPUSH或RPUSH命令为止。
超时参数timeout接受一个以秒为单位的数字做为值。超时参数设为0表示阻塞时间能够无限期延长(block indefinitely) 。
相同的key被多个客户端同时阻塞
在MULTI/EXEC事务中的BLPOP
BLPOP能够用于流水线(pipline,批量地发送多个命令并读入多个回复),但把它用在MULTI/EXEC块当中没有意义。由于这要求整个服务器被阻塞以保证块执行时的原子性,该行为阻止了其余客户端执行LPUSH或RPUSH命令。
所以,一个被包裹在MULTI/EXEC块内的BLPOP命令,行为表现得就像LPOP同样,对空列表返回nil,对非空列表弹出列表元素,不进行任何阻塞操做。
时间复杂度:O(1)返回值:
BRPOP是列表的阻塞式(blocking)弹出原语。
它是RPOP命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,链接将被BRPOP命令阻塞,直到等待超时或发现可弹出元素为止。
当给定多个key参数时,按参数key的前后顺序依次检查各个列表,弹出第一个非空列表的尾部元素。
关于阻塞操做的更多信息,请查看BLPOP命令,BRPOP除了弹出元素的位置和BLPOP不一样以外,其余表现一致。
返回列表key的长度。
若是key不存在,则key被解释为一个空列表,返回0.
若是key不是列表类型,返回一个错误。
返回列表key中指定区间内的元素,区间以偏移量start和stop指定。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
注意LRANGE命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表,对该列表执行LRANGE list 0 10,结果是一个包含11个元素的列表,这代表stop下标也在LRANGE命令的取值范围以内(闭区间),这和某些语言的区间函数可能不一致,好比Ruby的Range.new、Array#slice和Python的range()函数。
超出范围的下标
超出范围的下标值不会引发错误。
若是start下标比列表的最大下标end(LLEN list减去1)还要大,或者start > stop,LRANGE返回一个空列表。
若是stop下标比end下标还要大,Redis将stop的值设置为end。
根据参数count的值,移除列表中与参数value相等的元素。
将列表key下标为index的元素的值甚至为value。
更多信息请参考LINDEX操做。
当index参数超出范围,或对一个空列表(key不存在)进行LSET时,返回一个错误。
对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间以内的元素都将被删除。
举个例子,执行命令LTRIM list 0 2,表示只保留列表list的前三个元素,其他元素所有删除。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
当key不是列表类型时,返回一个错误。
LTRIM命令一般和LPUSH命令或RPUSH命令配合使用,举个例子:
这个例子模拟了一个日志程序,每次将最新日志newest_log放到log列表中,而且只保留最新的100项。注意当这样使用LTRIM命令时,时间复杂度是O(1),由于平均状况下,每次只有一个元素被移除。
注意LTRIM命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表list,对该列表执行LTRIM list 0 10,结果是一个包含11个元素的列表,这代表stop下标也在LTRIM命令的取值范围以内(闭区间),这和某些语言的区间函数可能不一致,好比Ruby的Range.new、Array#slice和Python的range()函数。
超出范围的下标
超出范围的下标值不会引发错误。
若是start下标比列表的最大下标end(LLEN list减去1)还要大,或者start > stop,LTRIM返回一个空列表(由于LTRIM已经将整个列表清空)。
若是stop下标比end下标还要大,Redis将stop的值设置为end。
返回列表key中,下标为index的元素。
下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。
你也可使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
若是key不是列表类型,返回一个错误。
将值value插入到列表key当中,位于值pivot以前或以后。
当pivot不存在于列表key时,不执行任何操做。
当key不存在时,key被视为空列表,不执行任何操做。
若是key不是列表类型,返回一个错误。
命令RPOPLPUSH在一个原子时间内,执行如下两个动做:
- 将列表source中的最后一个元素(尾元素)弹出,并返回给客户端。
- 将source弹出的元素插入到列表destination,做为destination列表的的头元素。
举个例子,你有两个列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,执行RPOPLPUSH source destination以后,source列表包含元素a, b,destination列表包含元素c, x, y, z ,而且元素c被返回。
若是source不存在,值nil被返回,而且不执行其余动做。
若是source和destination相同,则列表中的表尾元素被移动到表头,并返回该元素,能够把这种特殊状况视做列表的旋转(rotation)操做。
设计模式: 一个安全的队列
Redis的列表常常被用做队列(queue),用于在不一样程序之间有序地交换消息(message)。一个程序(称之为生产者,producer)经过LPUSH命令将消息放入队列中,而另外一个程序(称之为消费者,consumer)经过RPOP命令取出队列中等待时间最长的消息。
不幸的是,在这个过程当中,一个消费者可能在得到一个消息以后崩溃,而未执行完成的消息也所以丢失。
使用RPOPLPUSH命令能够解决这个问题,由于它在返回一个消息之余,还将该消息添加到另外一个列表当中,另外的这个列表能够用做消息的备份表:假如一切正常,当消费者完成该消息的处理以后,能够用LREM命令将该消息从备份表删除。
另外一方面,助手(helper)程序能够经过监视备份表,将超过必定处理时限的消息从新放入队列中去(负责处理该消息的消费者可能已经崩溃),这样就不会丢失任何消息了。
BRPOPLPUSH是RPOPLPUSH的阻塞版本,当给定列表source不为空时,BRPOPLPUSH的表现和RPOPLPUSH同样。
当列表source为空时,BRPOPLPUSH命令将阻塞链接,直到等待超时,或有另外一个客户端对source执行LPUSH或RPUSH命令为止。
超时参数timeout接受一个以秒为单位的数字做为值。超时参数设为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中都出现,那只记录一次便可。 union(A,B) = {'a', 'b', 'c', 'e', 'i', 'o', 'u'} diff(x, y): 差集,在集合x中而不在集合y中的元素。 diff(A,B) = {'b', 'c'} card(x): 基数,一个集合中元素的数量。 card(A) = 3 空集: 基数为0的集合。
将一个或多个member元素加入到集合key当中,已经存在于集合的member元素将被忽略。
假如key不存在,则建立一个只包含member元素做成员的集合。
当key不是集合类型时,返回一个错误。
注解:在Redis2.4版本之前,SADD只接受单个member值。
移除集合key中的一个或多个member元素,不存在的member元素会被忽略。
当key不是集合类型,返回一个错误。
注解:在Redis2.4版本之前,SREM只接受单个member值。
返回集合key中的全部成员。
判断member元素是不是集合key的成员。
返回集合key的基数(集合中元素的数量)。
将member元素从source集合移动到destination集合。
SMOVE是原子性操做。
若是source集合不存在或不包含指定的member元素,则SMOVE命令不执行任何操做,仅返回0。不然,member元素从source集合中被移除,并添加到destination集合中去。
当destination集合已经包含member元素时,SMOVE命令只是简单地将source集合中的member元素删除。
当source或destination不是集合类型时,返回一个错误。
移除并返回集合中的一个随机元素。
也能够参考:若是只想获取一个随机元素,但不想该元素从集合中被移除的话,可使用SRANDMEMBER命令。
返回集合中的一个随机元素。
该操做和SPOP类似,但SPOP将随机元素从集合中移除并返回,而SRANDMEMBER则仅仅返回随机元素,而不对集合进行任何改动。
返回一个集合的所有成员,该集合是全部给定集合的交集。
不存在的key被视为空集。
当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。
此命令等同于SINTER,但它将结果保存到destination集合,而不是简单地返回结果集。
若是destination集合已经存在,则将其覆盖。
destination能够是key自己。
返回一个集合的所有成员,该集合是全部给定集合的并集。
不存在的key被视为空集。
此命令等同于SUNION,但它将结果保存到destination集合,而不是简单地返回结果集。
若是destination已经存在,则将其覆盖。
destination能够是key自己。
返回一个集合的所有成员,该集合是全部给定集合的差集 。
不存在的key被视为空集。
此命令等同于SDIFF,但它将结果保存到destination集合,而不是简单地返回结果集。
若是destination集合已经存在,则将其覆盖。
destination能够是key自己。
将一个或多个member元素及其score值加入到有序集key当中。
若是某个member已是有序集的成员,那么更新这个member的score值,并经过从新插入这个member元素,来保证该member在正确的位置上。
score值能够是整数值或双精度浮点数。
若是key不存在,则建立一个空的有序集并执行ZADD操做。
当key存在但不是有序集类型时,返回一个错误。
对有序集的更多介绍请参见sorted set。
注解:在Redis2.4版本之前,ZADD每次只能添加一个元素。
移除有序集key中的一个或多个成员,不存在的成员将被忽略。
当key存在但不是有序集类型时,返回一个错误。
注解:在Redis2.4版本之前,ZREM每次只能删除一个元素。
返回有序集key的基数。
返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。
关于参数min和max的详细使用方法,请参考ZRANGEBYSCORE命令。
返回有序集key中,成员member的score值。
若是member元素不是有序集key的成员,或key不存在,返回nil。
为有序集key的成员member的score值加上增量increment。
你也能够经过传递一个负数值increment,让score减去相应的值,好比ZINCRBY key -5 member,就是让member的score值减去5。
当key不存在,或member不是key的成员时,ZINCRBY key increment member等同于ZADD key increment member。
当key不是有序集类型时,返回一个错误。
score值能够是整数值或双精度浮点数。
返回有序集key中,指定区间内的成员。
其中成员的位置按score值递增(从小到大)来排序。
具备相同score值的成员按字典序(lexicographical order)来排列。
若是你须要成员按score值递减(从大到小)来排列,请使用ZREVRANGE命令。
返回有序集key中,指定区间内的成员。
除了成员按score值递减的次序排列这一点外,ZREVRANGE命令的其余方面和ZRANGE命令同样。
返回有序集key中,全部score值介于min和max之间(包括等于min或max)的成员。有序集成员按score值递增(从小到大)次序排列。
具备相同score值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不须要额外的计算)。
可选的LIMIT参数指定返回结果的数量及区间(就像SQL中的SELECT LIMIT offset, count),注意当offset很大时,定位offset的操做可能须要遍历整个有序集,此过程最坏复杂度为O(N)时间。
区间及无限
min和max能够是-inf和+inf,这样一来,你就能够在不知道有序集的最低和最高score值的状况下,使用ZRANGEBYSCORE这类命令。
默认状况下,区间的取值使用闭区间(小于等于或大于等于),你也能够经过给参数前增长(符号来使用可选的开区间(小于或大于)。
举个例子:
返回全部符合条件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)区间内的全部成员。
区间分别如下标参数start和stop指出,包含start和stop在内。
移除有序集key中,全部score值介于min和max之间(包括等于min或max)的成员。
自版本2.1.6开始,score值等于min或max的成员也能够不包括在内,详情请参见ZRANGEBYSCORE命令。
计算给定的一个或多个有序集的交集,其中给定key的数量必须以numkeys参数指定,并将该交集(结果集)储存到destination。
默认状况下,结果集中某个成员的score值是全部给定集下该成员score值之和。
关于WEIGHTS和AGGREGATE选项的描述,参见ZUNIONSTORE命令。
计算给定的一个或多个有序集的并集,其中给定key的数量必须以numkeys参数指定,并将该并集(结果集)储存到destination。
默认状况下,结果集中某个成员的score值是全部给定集下该成员score值之和。
WEIGHTS
使用WEIGHTS选项,你能够为每一个给定有序集分别指定一个乘法因子(multiplication factor),每一个给定有序集的全部成员的score值在传递给聚合函数(aggregation function)以前都要先乘以该有序集的因子。
若是没有指定WEIGHTS选项,乘法因子默认设置为1。
AGGREGATE
使用AGGREGATE选项,你能够指定并集的结果集的聚合方式。
默认使用的参数SUM,能够将全部集合中某个成员的score值之和做为结果集中该成员的score值;使用参数MIN,能够将全部集合中某个成员的最小score值做为结果集中该成员的score值;而参数MAX则是将全部集合中某个成员的最大score值做为结果集中该成员的score值。
将信息 message 发送到指定的频道 channel 。
订阅给定频道的信息。
订阅符合给定模式的频道。
每一个模式以 * 做为匹配符,好比 huangz* 匹配全部以 huangz 开头的频道( huangzmsg 、 huangz-blog 、 huangz.tweets 等等), news.* 匹配全部以 news. 开头的频道(news.it 、 news.global.today 等等),诸如此类。
警告:此命令在新版 Redis 中彷佛已经被废弃?
警告:此命令在新版 Redis 中彷佛已经被废弃?
监视一个(或多个) key ,若是在事务执行以前这个(或这些) key 被其余命令所改动,那么事务将被打断。
UNWATCH
取消 WATCH 命令对全部 key 的监视。
若是在执行 WATCH 命令以后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不须要再执行 UNWATCH 了。
由于 EXEC 命令会执行事务,所以 WATCH 命令的效果已经产生了;而 DISCARD 命令在取消事务的同时也会取消全部对 key 的监视,所以这两个命令执行以后,就没有必要执行 UNWATCH 了。
MULTI
标记一个事务块的开始。
事务块内的多条命令会按照前后顺序被放进一个队列当中,最后由 EXEC 命令在一个原子时间内执行。
EXEC
执行全部事务块内的命令。
假如某个(或某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么 EXEC 命令只在这个(或这些) key 没有被其余命令所改动的状况下执行并生效,不然该事务被打断(abort)。
DISCARD
取消事务,放弃执行事务块内的全部命令。
若是正在使用 WATCH 命令监视某个(或某些) key ,那么取消全部监视,等同于执行命令 UNWATCH 。
经过设置配置文件中 requirepass 项的值(使用命令 CONFIG SET requirepass password ),可使用密码来保护 Redis 服务器。
若是开启了密码保护的话,在每次链接 Redis 服务器以后,就要使用 AUTH 命令解锁,解锁以后才能使用其余 Redis 命令。
若是 AUTH 命令给定的密码 password 和配置文件中的密码相符的话,服务器会返回 OK 并开始接受命令输入。
反之,若是密码不匹配的话,服务器将返回一个错误,并要求客户端需从新输入密码。
警告:由于 Redis 高性能的特色,在很短期内尝试猜想很是多个密码是有可能的,所以请确保使用的密码足够复杂和足够长,以避免遭受密码猜想攻击。
PING
客户端向服务器发送一个 PING ,而后服务器返回客户端一个 PONG 。
一般用于测试与服务器的链接是否仍然生效,或者用于测量延迟值。
切换到指定的数据库,数据库索引号用数字值指定,以 0 做为起始索引值。
新的连接老是使用 0 号数据库。
打印一个特定的信息 message ,测试时使用。
QUIT
请求服务器关闭与当前客户端的链接。
一旦全部等待中的回复(若是有的话)顺利写入到客户端,链接就会被关闭。
BGREWRITEAOF
异步(Asynchronously)重写 AOF 文件以反应当前数据库的状态。
即便 BGREWRITEAOF 命令执行失败,旧 AOF 文件中的数据也不会所以丢失或改变。
在后台异步保存当前数据库的数据到磁盘。
BGSAVE 命令执行以后当即返回 OK ,而后 Redis fork出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,而后退出。
客户端能够经过 LASTSAVE 命令查看相关信息,判断 BGSAVE 命令是否执行成功。
SAVE
同步保存当前数据库的数据到磁盘。
LASTSAVE
返回最近一次 Redis 成功执行保存操做的时间点( SAVE 、 BGSAVE 等),以 UNIX 时间戳格式表示。
DBSIZE
返回当前数据库的 key 的数量。
SLAVEOF 命令用于在 Redis 运行时动态地修改复制(replication)功能的行为。
经过执行 SLAVEOF host port 命令,能够将当前服务器转变为指定服务器的从属服务器(slave server)。
若是当前服务器已是某个主服务器(master server)的从属服务器,那么执行 SLAVEOF host port 将使当前服务器中止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。
另外,对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。
利用“ SLAVEOF NO ONE 不会丢弃同步所得数据集”这个特性,能够在主服务器失败的时候,将从属服务器用做新的主服务器,从而实现无间断运行。
FLUSHALL
清空整个 Redis 服务器的数据(删除全部数据库的全部 key)。
此命令从不失败。
FLUSHDB
清空当前数据库中的全部 key 。
此命令从不失败。
SHUTDOWN
SHUTDOWN 命令执行如下操做:
若是持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。
假如只是单纯地执行 SAVE 命令,而后再执行 QUIT 命令,则没有这一保证 —— 由于在执行 SAVE 以后、执行 QUIT 以前的这段时间中间,其余客户端可能正在和服务器进行通信,这时若是执行 QUIT 就会形成数据丢失。
什么是 SLOWLOG
Slow log 是 Redis 用来记录查询执行时间的日志系统。
查询执行时间指的是不包括像客户端响应(talking)、发送回复等 IO 操做,而单单是执行一个查询命令所耗费的时间。
另外,slow log 保存在内存里面,读写速度很是快,所以你能够放心地使用它,没必要担忧由于开启 slow log 而损害 Redis 的速度。
设置 SLOWLOG
Slow log 的行为由两个配置参数(configuration parameter)指定,能够经过改写 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令对它们动态地进行修改。
第一个选项是 slowlog-log-slower-then ,它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的查询进行记录。
好比执行如下命令将让 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 则只打印指定数量的日志。
最新的日志会最早被打印:
日志的惟一 id 只有在 Redis 服务器重启的时候才会重置,这样能够避免对日志的重复处理(好比你可能会想在每次发现新的慢查询时发邮件通知你)。
查看当前日志的数量
使用命令 SLOWLOG LEN 能够查看当前日志的数量。
请注意这个值和 slower-max-len 的区别,它们一个是当前日志的数量,一个是容许记录的最大日志的数量。
清空日志
使用命令 SLOWLOG RESET 能够清空 slow log 。
时间复杂度:O(1)
返回值:取决于不一样命令,返回不一样的值。
INFO
返回关于 Redis 服务器的各类信息和统计值。
CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),不过并不是全部配置参数都被 CONFIG GET 命令所支持。
CONFIG GET 接受单个参数 parameter 做为搜索关键字,查找全部匹配的配置参数,其中参数和值以“键-值对”(key-value pairs)的方式排列。
好比执行 CONFIG GET s* 命令,服务器就会返回全部以 s 开头的配置参数及参数的值:
若是你只是寻找特定的某个参数的话,你固然也能够直接指定参数的名字:
使用命令 CONFIG GET * ,能够列出 CONFIG GET 命令支持的全部参数:
全部被 CONFIG SET 所支持的配置参数均可以在配置文件 redis.conf 中找到,不过 CONFIG GET 和 CONFIG SET 使用的格式和 redis.conf 文件所使用的格式有如下两点不一样:
CONFIG SET 命令能够动态地调整 Redis 服务器的配置(configuration)而无须重启。
你可使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。
CONFIG SET 能够修改的配置参数可使用命令 CONFIG GET * 来列出,全部被 CONFIG SET 修改的配置参数都会当即生效。
关于 CONFIG SET 命令的更多消息,请参见命令 CONFIG GET 的说明。
关于如何使用 CONFIG SET 命令修改 Redis 持久化方式,请参见 Redis Persistence 。
重置 INFO 命令中的某些统计数据,包括:
返回给定 key 的调试信息。
令 Redis 服务器崩溃,调试用。
MONITOR
实时打印出 Redis 服务器接收到的命令,调试用。
YNC
用于复制功能(replication)的内部命令。