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' ] ) ; |