PHP操作Redis


目錄

基本指令

redis里有一些通用的操作,不管它是什么類型操作都是通用的,不過不管是做什么操作,都得先連接redis服務器,實例化redis對象

$redis = new Redis();
if (!$redis->connect('127.0.0.1', 6379)) {
    trigger_error('Redis連接出錯!!!', E_USER_ERROR);
} else {
    echo '連接正常<br>';
}

獲取所有的key(keys)

$data = $redis->keys('*');
dump($data);

判斷鍵對應值的類型(type)

type()方法用戶獲取一個key對應值的類型,返回值(1:string, 2:set, 3:list, 4:zset, 5:hash 6:未知)

$type = $redis->type('user');
dump($type);

刪除緩存項(del)

$redis->del('待刪除的key')

設置有效期(expire,expireAt)

需要在設置好了緩存項后,在設置有效期

expire()方法是設置某個時間段后過期,`expireAt()方法是在某個時間點(時間戳)過期失效

//expire用法示例
//expire()方法第二個參數的單位是秒(s),表示多少秒之后過期
$redis->expire('user', 3600);

//expire用法示例
$redis->expireAt('user', strtotime('2020-08-15 00:00:00'));

如果想精確到毫秒的話,redis還提供了pExpire()pExpireAt()方法可供使用

獲取有效期(ttl)

ttl()方法可以獲取某個鍵的剩余有效期

$redis->ttl('key');  //獲取剩余有效期,單位:秒(s)
$redis->pttl('key'); //獲取剩余有效期,單位:毫秒(ms)   

檢測緩存項是否存在(exists)

exists()方法用於檢測某個key是否存在

$redis->set('age', 25);
if ($redis->exists('age')) {
    echo '存在';
} else {
    echo '不存在';
}

查看當前數據庫key的數量(dbSize)

$dbSize = $redis->dbSize();
echo $dbSize;

清空當前數據庫(flushDB)

$isFlushed = $redis->flushDB();
var_dump($isFlushed);

清空所有數據庫(flushAll)

會清空所有庫的數據,默認是0~15這16個數據庫

$isFlushed = $redis->flushAll();
var_dump($isFlushed);

字符串(string)類型

string是Redis最基本的類型,你可以理解成Memcached一模一樣的類型,一個key對應一個value。

string類型是二進制安全的。這意味着Redis的string可以包含任何數據。比如JPG圖片或者序列化的對象。

一個Redis中字符串value最多可以是512M

設置(set)

僅僅支持字符串操作,不支持內置數據編碼功能。如果需要存儲PHP的非字符串類型,需要提前手動序列化,獲取時再反序列化。

$user = [
    'name' => 'bashlog',
    'age'  => 26,
    'email' => 'xxxx@gmail.com'
];
//將$user數組序列化成json字符串
$user = json_encode($user);
$redis->set('user', $user);
$data = $redis->get('user');
//拿到序列化后的字符串,再反序列化成PHP數組
$data = json_decode($data, true);
var_dump($data);

setnx()方法是只有在key不存在時設置key的值,

設置並指定過期時間(setex)

設置鍵的同時,設置過期時間(時間單位是秒)

$redis->setex('hobby', 60, 'fishing');

獲取(get)

$redis->set('name', 'bashlog'); //設置
$name = $redis->get('name');    //獲取
var_dump($name);

增加(incr, incrBy)

incr()incrBy()都是操作數字,對數字進行增加的操作,incr是執行原子加1操作,incrBy是增加指定的數

$redis->set('age', 10);
$redis->incr('age'); //等於$age++
$redis->incrBy('age', 5); // 等於$age = $age + 5

原子性

所謂原子操作是指不會被線程調度機制打斷的操作:這種操作一旦開始,就一直運行到結束,中阿金不會有任何context witch(切換到另一個線程).

(1)在單線程中,能夠在單條指令中完成的操作都可以認為是“原子操作”,因為中斷只能發生於指令之間。

(2)在多線程中,不能被其它進程(線程)打算的操作叫原子操作。

Redis單命令的原子性主要得益於Redis的單線程

減少(decr, decrBy)

decr()decrBy()方法是對數字進行減的操作,和incr正好相反

$redis->set('age', 10);
$redis->decr('age'); //等於$age--
$redis->decrBy('age', 5); // 等於$age = $age - 5

追加(append)

append()表示往字符串后面追加元素,返回值是字符串的總長度

示例:在'hello'后面追加' world'

$redis->set('respect', 'hello');
$length = $redis->append('respect', ' world');
var_dump($length);

獲取長度(strLen)

strLen()方法可以獲取字符串的長度

$redis->set('respect', 'hello');
$length = $redis->strlen('respect');
var_dump($length);

字符串截取(getRange)

getRange()方法可以用來截取字符串的部分內容,第二個參數是下標索引的開始位置,第三個參數是下標索引的結束位置(不是要截取的長度),

$redis->set('ID', '411521199809151234');
$subStr = $redis->getRange('ID', 0, 5);
var_dump($subStr);

此外,字符串(string)類型還有mget()mset()msetnx()getSet()等方法.....

列表(list)類型

Redis列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)

一個列表最多可以包含232 - 1 個元素 (4294967295, 每個列表超過40億個元素)。

將元素壓入鏈表(lPush)

可以使用lPush()方法將數據從左側壓入列表

$redis->lPush('list', 'v1');
$redis->lPush('list', 'v2');
$redis->lPush('list', 'v2', 'v3');

可以通過Redis Desktop Manager查看插入情況

也可以從右側壓入列表,對應的方式是rPush()

在某個位置插入新元素(lInsert)

位置的判斷,是根據相對的參考元素判斷

我們在之前的list鏈表往里插入數據

$redis->lInsert('list', Redis::BEFORE, 'v2', 'newInsert');

插入結果如下, 雖然有兩個'v2',但是也只會在第一個'v2'前插入數據

也可以在一個元素后面插入,使用Redis::AFTER

$redis->lInsert('list', Redis::AFTER, 'v2', 'newAfterInsert');

設置某個元素的值(lSet)

lSet()方法可以通過下標修改鏈表元素的值,下標是從0開始。

# 將list鏈表中的第一個元素v3改為newV3
$redis->lSet('list', 0, 'newV3');

獲取列表元素個數(lLen)

llen()方法可以獲取元素個數

$length = $redis->lLen('list');
echo $length;

獲取下標對應的元素(lIndex)

$val = $redis->lIndex('list', 1);
echo $val;

獲取某個選定范圍元素集(lRange)

lRange()方法支持通過起止下標來獲取列表某個范圍內的元素集

$arr = $redis->lRange('list', 0, 1); //前兩個元素
$arr = $redis->lRange('list', 0, -1); //全部元素
$arr = $redis->lRange('list', -2, -1); //后兩個元素
var_dump($arr);

從列表左側彈出數據(lPop)

lPop()方法將數據從列表左側彈出,返回彈出的元素,數據元素在list中消失。

$val = $redis->lPop('list');
echo $val;

查看list列表可以發現,原本第一個元素'newVe3'已經不在list中了

如果想從右側彈出數據,可以使用rPop()方法

根據值移除元素(lRem)

可以使用lRem()方法根據值來移除元素,並且可以指定要移除的元素個數,因為list中可能出現重復的元素

$res = $redis->lRem('list', 'v2', 2);
echo $res;

集合(set)類型

Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的接口,這是也是list所不能提供了。

Redis的Set是string類型的無需集合。它底層其實是一個value為null的hash表,所以添加、刪除、查找的復雜度都是O(1)。

集合數據的特征:

  1. 元素不能重復,保持唯一性
  2. 元素無序,不能使用索引(下標)操作

添加元素到集合(sAdd)

$redis->sAdd('team', 'kobe');
$redis->sAdd('team', 'jordan');
$redis->sAdd('team', 'curry'); 
$redis->sAdd('team', 'kobe');//由於kobe已經被添加到team集合中,所以重復添加是無效的

隨機獲取一個元素(sPop)

無序性,是隨機的

sPop()方法是從集合中隨機取出元素的,它有兩個參數,第二個參數表示要取出多少個數據,默認是1

$redis->sPop('team');

刪除集合里指定的值(sRem)

$redis->sAdd('k', 'v1', 'v2', 'v3');
$redis->sRem('k', 'v2', 'v3');
$leftData = $redis->sMembers('k');
dump($leftData);

遍歷集合(sScan)

//不使用迭代器,匹配所有的元素,進行遍歷
$iterator = null;
$elements = $redis->sScan('team', $iterator, '*');
foreach ($elements as $element) {
    echo $element, '<br>';
}

獲取所有成員(sMembers)

$members = $redis->sMembers('team');
var_dump($members);

獲取集合元素個數(sCard)

獲取集合中元素個數

$count = $redis->sCard('team');
echo $count;

並集(sUnion),差集(sDiff),交集(sInter)

PHPRedis提供了一些對集合的相互操作

$redis->sAdd('setA', 'a', 'b', 'c', 'd');
$redis->sAdd('setB', 'a', 'd', 'e', 'f');

$union = $redis->sUnion('setA', 'setB');
$diff  = $redis->sDiff('setA', 'setB');
$inter = $redis->sInter('setA', 'setB');
dump($union);
dump($diff);
dump($inter);

有序集合(zset)類型

Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復的成員。

不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。

有序集合的成員是唯一的,但分數(score)卻可以重復。

集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。 集合中最大的成員數為 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。

處理元素時,也要加上score的處理

添加元素(zAdd)

添加6個元素(1~6),分值都是0

$redis->zAdd('zSet', 0, 1);
$redis->zAdd('zSet', 0, 2);
$redis->zAdd('zSet', 0, 3);
$redis->zAdd('zSet', 0, 4);
$redis->zAdd('zSet', 0, 5);
$redis->zAdd('zSet', 0, 6);

元素分值增減(zIncrBy)

分值可以為負數,表示遞減

$redis->zIncrBy('zSet', mt_rand(0, 100), 1);
$redis->zIncrBy('zSet', mt_rand(0, 100), 2);
$redis->zIncrBy('zSet', mt_rand(0, 100), 3);
$redis->zIncrBy('zSet', mt_rand(0, 100), 4);
$redis->zIncrBy('zSet', mt_rand(0, 100), 5);
$redis->zIncrBy('zSet', mt_rand(0, 100), 6);

獲取根據score排序后的數據段(zRange,zRevRange)

根據分值排序后的,升序和降序的列表獲取

//獲取排行榜
//獲取分值(點擊率)前三的文章ID列表
$lists = $redis->zRevRange('zSet', 0, 2, true);
dump($lists);

獲取score過濾后排序的數據段(zRangeByScore,zRevRangeByScore)

根據分值過濾之后的列表

需要提供分值區間

$lists = $redis->zRangeByScore('zSet', 40, 90, ['withscores' => true]);
dump($lists);

原始數據如下圖

獲取元素個數(zCard)

$count = $redis->zCard('zSet');
echo $count;

獲取區間內的元素個數(zCount)

獲取分值在[50,90]的元素的數量

$count = $redis->zCount('zSet', 50, 90);
echo $count;

獲取元素的score(zScore)

獲取元素分值

$score = $redis->zScore('zSet', 6);
echo $score;

獲取某個元素在集合中的排名(zRank)

zRank()方法是返回元素在集合中的排名情況,從0開始。

$order = $redis->zRank('zSet', 56);

刪除元素(zRem)

zRem()方法支持通過元素的值來刪除元素

//通過元素值來刪除元素
$redis->zRem('zSet', 6);

根據排名來刪除(zRemRangeByRank)

//按照升序排序刪除第一個和第二個元素
$redis->zRemRangeByRank('zSet', 0, 1);

根據區間來刪除(zRemRangeByScore)

//刪除score在[40, 70]之間的元素
$redis->zRemRangeByScore('zSet', 40, 70);

哈希(hash)類型

Redis hash 是一個 string 類型的 field(字段) 和 value(值) 的映射表,hash 特別適合用於存儲對象。

Redis 中每個 hash 可以存儲 232 - 1 鍵值對(40多億)。

當前服務器一般都是將用戶登錄信息保存到Redis中,這里存儲用戶登錄信息就比較適合用hash表。hash表比string更合適,如果我們選擇使用string類型來存儲用戶的信息的時候,我們每次存儲的時候就得先序列化(json_encode()、serialize())成字符串才能存儲redis,

從redis拿到用戶信息后又得反序列化(json_decode()、unserialize())成數組或對象,這樣開銷比較大。如果使用hash的話我們通過key(用戶ID)+field(屬性標簽)就可以操作對應屬性數據了,既不需要重復存儲數據,也不會帶來序列化和並發修改控制的問題。

設置(hSet)

$redis->hSet('user', 'name', 'bashlog');
$redis->hSet('user', 'age', 10);
$redis->hSet('user', 'address', '浙江杭州濱江區');

上面的操作等價於PHP中的

$user['name'] = 'bashlog';
$user['age']  = 10;
$user['address'] = '浙江杭州濱江'

批量設置(hMset)

上面使用hSet設置的方式需要多次設置,不太方便,Redis提供了批量設置的方法hMset(),我們可以用這個方法將用戶登錄信息一次性保存到redis中

$u1 = [
    'id'=> 1,
    'name' => 'itbsl',
    'age'  => 25,
    'email' => 'itbsl@gmail.com',
    'address' => '北京朝陽區大望路'
];
$redis->hMSet('user:'.$u1['id'], $u1);

$u2 = [
    'id' => 2,
    'name' => 'bashlog',
    'age'  => 26,
    'email' => 'bash@gmail.com',
    'address' => '北京市海淀區西二旗'
];
$redis->hMSet('user:'.$u2['id'], $u2);

為什么要給存儲的數據加一個前綴呢,比如說上面示例的user前綴?

因為我們在redis一般需要存儲很多業務類型的數據,比如用戶登錄信息、驗證碼信息,我們都是以用戶唯一標識信息(如id,手機號)作為key,如果不加前綴就會導致多個業務類型的數據就存到一起了,這是不合理也不應該的。所以我們可以以業務名稱作為前綴然后配合上用戶唯一標識即前綴:唯一標識作為key,中間是用冒號:分隔,這樣就可以把數據按照業務類型分開,這也是業界通用的做法,比如我們php的session存儲默認也是一PHPREDIS_SESSION作為前綴,官方都是這么做了,我們還有什么理由不這樣做呢。

獲取(hGet)

下面的操作等價於PHP中的$name = $user['name'];

$name = $redis->hGet('user', 'name');
echo $name;

獲取全部元素(hGetAll)

$user = $redis->hGetAll('user');
dump($user);

刪除某個元素(hDle)

$res = $redis->hDel('user', 'address');
var_dump($res);

判斷元素是否存在(hExists)

$isExistent = $redis->hExists('user', 'address');
var_dump($isExistent);

獲取長度(hLen)

$hLen = $redis->hLen('user');
var_dump($hLen);

如果該文章對您有幫助,請您點個推薦,感謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM