[轉]predis操做方法大全(redis)

predis是php鏈接redis的操做庫,因爲它徹底使用php編寫,大量使用命名空間以及閉包等功能,只支持php5.3以上版本,故實測性能通常,每秒25000次讀寫,相信改換c語言編寫的php擴展後性能會大幅提高(好比使用C擴展phpredis https://github.com/owlient/phpredis)。 php

將session數據存放到redis也很簡單:
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379" node

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
//使用autoload加載相關庫,這邊重點就是爲了require $file;
spl_autoload_register ( function ( $class )  {
     $file  = __DIR__ . '/lib/Predis/' . $class . '.php' ;
     if  ( file_exists ( $file ) )  {
         require  $file ;
         return  true ;
     }
} ) ;


//配置鏈接的IP、端口、以及相應的數據庫
$server  =  array (
     'host'      =>  '127.0.0.1' ,
     'port'      =>  6379 ,
     'database'  =>  15
) ;
$redis  =  new Client ( $server ) ;



//普通set/get操做
$redis -> set ( 'library' ,  'predis' ) ;
$retval  =  $redis -> get ( 'library' ) ;
echo  $retval ;  //顯示 'predis'

//setex set一個存儲時效
$redis -> setex ( 'str' ,  10 ,  'bar' ) ;  //表示存儲有效期爲10秒

//setnx/msetnx至關於add操做,不會覆蓋已有值
$redis -> setnx ( 'foo' , 12 ) ;  //true
$redis -> setnx ( 'foo' , 34 ) ;  //false

//getset操做,set的變種,結果返回替換前的值
$redis -> getset ( 'foo' , 56 ) ; //返回34

// incrby/incr/decrby/decr 對值的遞增和遞減
$redis -> incr ( 'foo' ) ;  //foo爲57
$redis -> incrby ( 'foo' , 2 ) ;  //foo爲59

//exists檢測是否存在某值
$redis -> exists ( 'foo' ) ; //true

//del 刪除
$redis -> del ( 'foo' ) ; //true

//type 類型檢測,字符串返回string,列表返回 list,set表返回set/zset,hash表返回hash
$redis -> type ( 'foo' ) ; //不存在,返回none
$redis -> set ( 'str' , 'test' ) ; 
$redis -> type ( 'str' ) ;  //字符串,返回string

//append 鏈接到已存在字符串
$redis -> append ( 'str' , '_123' ) ;  //返回累加後的字符串長度8,此進str爲 'test_123'

//setrange 部分替換操做
$redis -> setrange ( 'str' , 0 , 'abc' ) ;  //返回3,參數2爲0時等同於set操做
$redis -> setrange ( 'str' , 2 , 'cd' ) ; //返回4,表示從第2個字符後替換,這時'str'爲'abcd'

//substr 部分獲取操做
$redis -> substr ( 'str' , 0 , 2 ) ; //表示從第0個起,取到第2個字符,共3個,返回'abc'

//strlen 獲取字符串長度
$redis -> strlen ( 'str' ) ;  //返回4

//setbit/getbit 位存儲和獲取
$redis -> setbit ( 'binary' , 31 , 1 ) ;   //表示在第31位存入1,這邊可能會有大小端問題?不過不要緊,getbit 應該不會有問題
$redis -> getbit ( 'binary' , 31 ) ;     //返回1

//keys 模糊查找功能,支持*號以及?號(匹配一個字符)
$redis -> set ( 'foo1' , 123 ) ;
$redis -> set ( 'foo2' , 456 ) ;
$redis -> keys ( 'foo*' ) ;  //返回foo1和foo2的array
$redis -> keys ( 'f?o?' ) ;   //同上

//randomkey 隨機返回一個key
$redis -> randomkey ( ) ;  //多是返回 'foo1'或者是'foo2'及其它任何一存在redis的key

//rename/renamenx 對key進行更名,所不一樣的是renamenx不容許改爲已存在的key
$redis -> rename ( 'str' , 'str2' ) ;  //把原先命名爲'str'的key改爲了'str2'

//expire 設置key-value的時效性,ttl 獲取剩餘有效期,persist 從新設置爲永久存儲
$redis -> expire ( 'foo' ,  1 ) ;  //設置有效期爲1秒
$redis -> ttl ( 'foo' ) ;  //返回有效期值1s
$redis -> expire ( 'foo' ) ;  //取消expire行爲

//dbsize 返回redis當前數據庫的記錄總數
$redis -> dbsize ( ) ;

/*
隊列操做
*/


//rpush/rpushx 有序列表操做,從隊列後插入元素
//lpush/lpushx 和rpush/rpushx的區別是插入到隊列的頭部,同上,'x'含義是隻對已存在的key進行操做
$redis -> rpush ( 'fooList' ,  'bar1' ) ;  //返回一個列表的長度1
$redis -> lpush ( 'fooList' ,  'bar0' ) ;  //返回一個列表的長度2
$redis -> rpushx ( 'fooList' ,  'bar2' ) ;  //返回3,rpushx只對已存在的隊列作添加,不然返回0
//llen返回當前列表長度
$redis -> llen ( 'fooList' ) ; //3

//lrange 返回隊列中一個區間的元素
$redis -> lrange ( 'fooList' , 0 , 1 ) ;  //返回數組包含第0個至第1個共2個元素
$redis -> lrange ( 'fooList' , 0 ,- 1 ) ; //返回第0個至倒數第一個,至關於返回全部元素,注意redis中不少時候會用到負數,下同

//lindex 返回指定順序位置的list元素
$redis -> lindex ( 'fooList' , 1 ) ;  //返回'bar1'

//lset 修改隊列中指定位置的value
$redis -> lset ( 'fooList' , 1 , '123' ) ; //修改位置1的元素,返回true

//lrem 刪除隊列中左起指定數量的字符
$redis -> lrem ( 'fooList' , 1 , '_' ) ;  //刪除隊列中左起(右起使用-1)1個字符'_'(如有)

//lpop/rpop 相似棧結構地彈出(並刪除)最左或最右的一個元素
$redis -> lpop ( 'fooList' ) ;  //'bar0'
$redis -> rpop ( 'fooList' ) ;  //'bar2'

//ltrim 隊列修改,保留左邊起若干元素,其他刪除
$redis -> ltrim ( 'fooList' ,  0 , 1 ) ;  //保留左邊起第0個至第1個元素

//rpoplpush 從一個隊列中pop出元素並push到另外一個隊列
$redis -> rpush ( 'list1' , 'ab0' ) ;
$redis -> rpush ( 'list1' , 'ab1' ) ;
$redis -> rpush ( 'list2' , 'ab2' ) ;
$redis -> rpush ( 'list2' , 'ab3' ) ;
$redis -> rpoplpush ( 'list1' , 'list2' ) ; //結果list1 =>array('ab0'),list2 =>array('ab1','ab2','ab3')
$redis -> rpoplpush ( 'list2' , 'list2' ) ; //也適用於同一個隊列,把最後一個元素移到頭部list2 =>array('ab3','ab1','ab2')

//linsert 在隊列的中間指定元素前或後插入元素
$redis -> linsert ( 'list2' ,  'before' , 'ab1' , '123' ) ;  //表示在元素'ab1'以前插入'123'
$redis -> linsert ( 'list2' ,  'after' , 'ab1' , '456' ) ;    //表示在元素'ab1'以後插入'456'


//blpop/brpop 阻塞並等待一個列隊不爲空時,再pop出最左或最右的一個元素(這個功能在php之外能夠說很是好用)
//brpoplpush 一樣是阻塞並等待操做,結果同rpoplpush同樣
$redis -> blpop ( 'list3' , 10 ) ;  //若是list3爲空則一直等待,直到不爲空時將第一元素彈出,10秒後超時



/**
set表操做
*/


//sadd 增長元素,返回true,重複返回false
$redis -> sadd ( 'set1' , 'ab' ) ;
$redis -> sadd ( 'set1' , 'cd' ) ;
$redis -> sadd ( 'set1' , 'ef' ) ;

//srem 移除指定元素
$redis -> srem ( 'set1' , 'cd' ) ;  //刪除'cd'元素

//spop 彈出首元素
$redis -> spop ( 'set1' ) ;

//smove 移動當前set表的指定元素到另外一個set表
$redis -> sadd ( 'set2' , '123' ) ;
$redis -> smove ( 'set1' , 'set2' , 'ab' ) ; //移動'set1'中的'ab'到'set2',返回true or false

//scard 返回當前set表元素個數
$redis -> scard ( 'set2' ) ; //2

//sismember 判斷元素是否屬於當前表
$redis -> sismember ( 'set2' , '123' ) ;  //true or false

//smembers 返回當前表的全部元素
$redis -> smembers ( 'set2' ) ;  //array('123','ab');

//sinter/sunion/sdiff  返回兩個表中元素的交集/並集/補集
$redis -> sadd ( 'set1' , 'ab' ) ;
$redis -> sinter ( 'set2' , 'set1' ) ;  //返回array('ab')

//sinterstore/sunionstore/sdiffstore 將兩個表交集/並集/補集元素copy到第三個表中
$redis -> set ( 'foo' , 0 ) ;
$redis -> sinterstore ( 'foo' , 'set1' ) ;  //這邊等同於將'set1'的內容copy到'foo'中,並將'foo'轉爲set表
$redis -> sinterstore ( 'foo' , array ( 'set1' , 'set2' ) ) ;  //將'set1'和'set2'中相同的元素copy到'foo'表中,覆蓋'foo'原有內容

//srandmember 返回表中一個隨機元素
$redis -> srandmember ( 'set1' ) ;



/**
有序set表操做
*/


//sadd 增長元素,並設置序號,返回true,重複返回false
$redis -> zadd ( 'zset1' , 1 , 'ab' ) ;
$redis -> zadd ( 'zset1' , 2 , 'cd' ) ;
$redis -> zadd ( 'zset1' , 3 , 'ef' ) ;

//zincrby 對指定元素索引值的增減,改變元素排列次序
$redis -> zincrby ( 'zset1' , 10 , 'ab' ) ; //返回11

//zrem 移除指定元素
$redis -> zrem ( 'zset1' , 'ef' ) ;  //true or false

//zrange 按位置次序返回表中指定區間的元素
$redis -> zrange ( 'zset1' , 0 , 1 ) ;  //返回位置0和1之間(兩個)的元素
$redis -> zrange ( 'zset1' , 0 ,- 1 ) ; //返回位置0和倒數第一個元素之間的元素(至關於全部元素)

//zrevrange 同上,返回表中指定區間的元素,按次序倒排
$redis -> zrevrange ( 'zset1' , 0 ,- 1 ) ;  //元素順序和zrange相反

//zrangebyscore/zrevrangebyscore 按順序/降序返回表中指定索引區間的元素
$redis -> zadd ( 'zset1' , 3 , 'ef' ) ;
$redis -> zadd ( 'zset1' , 5 , 'gh' ) ;
$redis -> zrangebyscore ( 'zset1' , 2 , 9 ) ;  //返回索引值2-9之間的元素 array('ef','gh')
//參數形式
$redis -> zrangebyscore ( 'zset1' , 2 , 9 , 'withscores' ) ;  //返回索引值2-9之間的元素幷包含索引值 array(array('ef',3),array('gh',5))
$redis -> zrangebyscore ( 'zset1' , 2 , 9 , array ( 'withscores'  => true , 'limit' => array ( 1 ,  2 ) ) ) ;  //返回索引值2-9之間的元素,'withscores' =>true表示包含索引值; 'limit'=>array(1, 2),表示最多返回2條,結果爲array(array('ef',3),array('gh',5))

//zunionstore/zinterstore 將多個表的並集/交集存入另外一個表中
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' , 'zset0' ) ) ;  //將'zset1','zset2','zset0'的並集存入'zset3'
//其它參數 
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' ) , array ( 'weights'  =>  array ( 5 , 0 ) ) ) ; //weights參數表示權重,其中表示並集後值大於5的元素排在前,大於0的排在後
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' ) , array ( 'aggregate'  =>  'max' ) ) ; //'aggregate' => 'max'或'min'表示並集後相同的元素是取大值或是取小值

//zcount 統計一個索引區間的元素個數
$redis -> zcount ( 'zset1' , 3 , 5 ) ; //2
$redis -> zcount ( 'zset1' , '(3' , 5 ) ) ;  //'(3'表示索引值在3-5之間但不含3,同理也可使用'(5'表示上限爲5但不含5

//zcard 統計元素個數
$redis -> zcard ( 'zset1' ) ; //4

//zscore 查詢元素的索引
$redis -> zscore ( 'zset1' , 'ef' ) ; //3

//zremrangebyscore 刪除一個索引區間的元素
$redis -> zremrangebyscore ( 'zset1' , 0 , 2 ) ;  //刪除索引在0-2之間的元素('ab','cd'),返回刪除元素個數2

//zrank/zrevrank 返回元素所在表順序/降序的位置(不是索引)
$redis -> zrank ( 'zset1' , 'ef' ) ; //返回0,由於它是第一個元素;zrevrank則返回1(最後一個)

//zremrangebyrank 刪除表中指定位置區間的元素
$redis -> zremrangebyrank ( 'zset1' , 0 , 10 ) ;  //刪除位置爲0-10的元素,返回刪除的元素個數2 


/**
hash表操做
*/


//hset/hget 存取hash表的數據
$redis -> hset ( 'hash1' , 'key1' , 'v1' ) ;  //將key爲'key1' value爲'v1'的元素存入hash1表
$redis -> hset ( 'hash1' , 'key2' , 'v2' ) ;
$redis -> hget ( 'hash1' , 'key1' ) ;   //取出表'hash1'中的key 'key1'的值,返回'v1'

//hexists 返回hash表中的指定key是否存在
$redis -> hexists  ( 'hash1' , 'key1' ) ;  //true or false

//hdel 刪除hash表中指定key的元素
$redis -> hdel ( 'hash1' , 'key2' ) ;  //true or false

//hlen 返回hash表元素個數
$redis -> hlen ( 'hash1' ) ;  //1

//hsetnx 增長一個元素,但不能重複
$redis -> hsetnx ( 'hash1' , 'key1' , 'v2' ) ;  //false
$redis -> hsetnx ( 'hash1' , 'key2' , 'v2' ) ;  //true

//hmset/hmget 存取多個元素到hash表
$redis -> hmset ( 'hash1' , array ( 'key3' => 'v3' , 'key4' => 'v4' ) ) ; 
$redis -> hmget ( 'hash1' , array ( 'key3' , 'key4' ) ) ;  //返回相應的值 array('v3','v4')

//hincrby 對指定key進行累加
$redis -> hincrby ( 'hash1' , 'key5' , 3 ) ;  //返回3
$redis -> hincrby ( 'hash1' , 'key5' , 10 ) ;  //返回13

//hkeys 返回hash表中的全部key
$redis -> hkeys ( 'hash1' ) ;  //返回array('key1','key2','key3','key4','key5')

//hvals 返回hash表中的全部value
$redis -> hvals ( 'hash1' ) ;  //返回array('v1','v2','v3','v4',13)

//hgetall 返回整個hash表元素
$redis -> hgetall ( 'hash1' ) ;  //返回array('key1'=>'v1','key2'=>'v2','key3'=>'v3','key4'=>'v4','key5'=>13)



/**
排序操做
*/


//sort 排序
$redis -> rpush ( 'tab' , 3 ) ;
$redis -> rpush ( 'tab' , 2 ) ;
$redis -> rpush ( 'tab' , 17 ) ;
$redis -> sort ( 'tab' ) ;   //返回array(2,3,17)
//使用參數,可組合使用 array('sort' => 'desc','limit' => array(1, 2))
$redis -> sort ( 'tab' , array ( 'sort'  =>  'desc' ) ) ;   //降序排列,返回array(17,3,2)
$redis -> sort ( 'tab' , array ( 'limit'  =>  array ( 1 ,  2 ) ) ) ;   //返回順序位置中1的元素2個(這裏的2是指個數,而不是位置),返回array(3,17)
$redis -> sort ( 'tab' , array ( 'limit'  =>  array ( 'alpha'  =>  true ) ) ) ;  //按首字符排序返回array(17,2,3),由於17的首字符是'1'因此排首位置
$redis -> sort ( 'tab' , array ( 'limit'  =>  array ( 'store'  =>  'ordered' ) ) ) ;  //表示永久性排序,返回元素個數
$redis -> sort ( 'tab' , array ( 'limit'  =>  array ( 'get'  =>  'pre_*' ) ) ) ;  //使用了通配符'*'過濾元素,表示只返回以'pre_'開頭的元素


/**
redis管理操做
*/


//select 指定要操做的數據庫
$redis -> select ( 'mydb' ) ;  //指定爲mydb,不存在則建立

//flushdb 清空當前庫
$redis -> flushdb ( ) ;

//move 移動當庫的元素到其它庫
$redis -> set ( 'foo' ,  'bar' ) ;
$redis -> move ( 'foo' ,  'mydb2' ) ;  //若'mydb2'庫存在

//info 顯示服務當狀態信息
$redis -> info ( ) ;

//slaveof 配置從服務器
$redis -> slaveof ( '127.0.0.1' , 80 ) ;  //配置127.0.0.1端口80的服務器爲從服務器
$redis -> slaveof ( ) ;  //清除從服務器

//同步保存服務器數據到磁盤
$redis -> save ( ) ;
//異步保存服務器數據到磁盤
$redis -> bgsave ( ) ;
//??
$redis -> bgrewriteaof ( ) ;
//返回最後更新磁盤的時間
$redis -> lastsave ( ) ;


//set/get多個key-value
$mkv  =  array (
     'usr:0001'  =>  'First user' ,
     'usr:0002'  =>  'Second user' ,
     'usr:0003'  =>  'Third user'
) ;
$redis -> mset ( $mkv ) ;  //存儲多個key對應的value
$retval  =  $redis -> mget ( array_keys ( $mkv ) ) ;  //獲取多個key對應的value
print_r ( $retval ) ;



//批量操做
$replies  =  $redis -> pipeline ( function ( $pipe )  {
     $pipe -> ping ( ) ;
     $pipe -> flushdb ( ) ;
     $pipe -> incrby ( 'counter' ,  10 ) ;  //增量操做
     $pipe -> incrby ( 'counter' ,  30 ) ;
     $pipe -> exists ( 'counter' ) ;
     $pipe -> get ( 'counter' ) ;
     $pipe -> mget ( 'does_not_exist' ,  'counter' ) ;  
} ) ;
print_r ( $replies ) ;




//CAS,事務性操做

function zpop ( $client ,  $zsetKey )  {
     $element  =  null ;
     $options  =  array (
         'cas'    =>  true ,      // Initialize with support for CAS operations
         'watch'  =>  $zsetKey ,  // Key that needs to be WATCHed to detect changes
         'retry'  =>  3 ,         // Number of retries on aborted transactions, after
                              // which the client bails out with an exception.
     ) ;

     $txReply  =  $client -> multiExec ( $options ,  function ( $tx )
         use  ( $zsetKey ,  & $element )  {
         @ list ( $element )  =  $tx -> zrange ( $zsetKey ,  0 ,  0 ) ;
         if  ( isset ( $element ) )  {
             $tx -> multi ( ) ;      // With CAS, MULTI *must* be explicitly invoked.
             $tx -> zrem ( $zsetKey ,  $element ) ;
         }
     } ) ;
     return  $element ;
}
$zpopped  = zpop ( $redis ,  'zset' ) ;
echo  isset ( $zpopped ) ?  "ZPOPed $zpopped"  :  "Nothing to ZPOP!" ,  "\n" ;


//對存取的key加前綴,如: 'nrk:'
$redis -> getProfile ( ) -> setPreprocessor ( new KeyPrefixPreprocessor ( 'nrk:' ) ) ;







//分佈式存儲的一些方法
$multiple_servers  =  array (
     array (
        'host'      =>  '127.0.0.1' ,
        'port'      =>  6379 ,
        'database'  =>  15 ,
        'alias'     =>  'first' ,
     ) ,
     array (
        'host'      =>  '127.0.0.1' ,
        'port'      =>  6380 ,
        'database'  =>  15 ,
        'alias'     =>  'second' ,
     ) ,
) ;


use Predis\Distribution\IDistributionStrategy ;

class NaiveDistributionStrategy implements IDistributionStrategy  {
     private  $_nodes ,  $_nodesCount ;

     public  function __constructor ( )  {
         $this ->_nodes  =  array ( ) ;
         $this ->_nodesCount  =  0 ;
     }

     public  function add ( $node ,  $weight  =  null )  {
         $this ->_nodes [ ]  =  $node ;
         $this ->_nodesCount ++;
     }

     public  function remove ( $node )  {
         $this ->_nodes  =  array_filter ( $this ->_nodes ,  function ( $n )  use ( $node )  {
             return  $n  !==  $node ;
         } ) ;
         $this ->_nodesCount  =  count ( $this ->_nodes ) ;
     }

     public  function get ( $key )  {
         $count  =  $this ->_nodesCount ;
         if  ( $count  ===  0 )  {
             throw  new RuntimeException ( 'No connections' ) ;
         }
         return  $this ->_nodes [ $count  >  1 ?  abs ( crc32 ( $key )  %  $count )  :  0 ] ;
     }

     public  function generateKey ( $value )  {
         return  crc32 ( $value ) ;
     }
}

//配置鍵分佈策略
$options  =  array (
     'key_distribution'  =>  new NaiveDistributionStrategy ( ) ,
) ;

$redis  =  new Predis\Client ( $multiple_servers ,  $options ) ;

for  ( $i  =  0 ;  $i set ( "key:$i" ,  str_pad ( $i ,  4 ,  '0' ,  0 ) ) ;
     $redis -> get ( "key:$i" ) ;
}

$server1  =  $redis -> getClientFor ( 'first' ) -> info ( ) ;
$server2  =  $redis -> getClientFor ( 'second' ) -> info ( ) ;

printf ( "Server '%s' has %d keys while server '%s' has %d keys.\n" ,
     'first' ,  $server1 [ 'db15' ] [ 'keys' ] ,  'second' ,  $server2 [ 'db15' ] [ 'keys' ]
) ;
相關文章
相關標籤/搜索