Redis在Web專案中的應用與實踐

2021-09-23 23:45:58 字數 3466 閱讀 1635

redis作為乙個開源的(bsd)基於記憶體的高效能儲存系統,已經被各大網際網路公司廣泛使用,並且有著諸多的應用場景。本篇文章將基於php來詳細講解redis在web專案中的主要應用與實踐。

這裡所介紹的快取是指可以丟失或過期的資料。常用的命令有set,hset,get,hget,使用redis作為快取時需要注意一下幾個問題:

在web專案中,redis可儲存讀寫非常頻繁的資料來緩解mysql等資料庫的壓力。redis如果作為儲存系統的話,為了防止資料丟失,持久化必須開啟。

典型場景

計數器的需求非常普遍,例如微博點讚數、帖子收藏數、文章分享數、使用者關注數等。

比如使用sets結構儲存關注列表、收藏列表、點讚列表等。

借助redis高效能的key-value儲存,可將使用者登入狀態儲存到redis中。

簡單佇列

一般使用redis的list結構作為佇列,rpush生產訊息,lpop消費訊息,當lpop沒有訊息的時候,要進行適當的sleep操作。

$queuekey = "queue";

// 生產者

$redis->rpush($queuekey, $data)

// 消費者

while (true)

// 業務邏輯

...}

由於沒有訊息時使用的sleep事件不好控制,生產環境盡量不要使用sleep來休眠,可使用blpop來消費訊息,在沒有新訊息的時候它會阻塞到訊息到來。

延時佇列

延時佇列可使用redis的sorted set資料結構,使用時間戳作為score,訊息內容作為member,使用zadd命令來生產訊息,消費者使用zrangebyscore命令獲取指定時間之前的訊息資料輪詢進行處理。

$queuekey = "queue";

// 生產訊息

// 消費時間, 這裡設定為1小時候

$consumetimestamp = time() + 3600;

// $data需要新增隨機串字首(or字尾),防止出現重複member被丟棄

$data = $data . md5(uniqid(rand(), true));

$redis->zadd($queuekey, $consumetimestamp, $data);

// 消費訊息

while (tue)

// 業務邏輯

foreach ($arrdata as $data)

}

多消費者

使用pub/sub主題訂閱者模式,可以實現1:n的訊息佇列。這種模式中在消費者下線的情況下,生產的訊息會丟失,在這裡不推薦使用。

需要強調的是不推薦使用redis作為訊息佇列服務,這不是redis的設計目標。如果一定要用可考慮 disque,是由redis的作者開發。

分布式鎖主要解決的幾個問題:

方案1

我們可能會考慮使用setnxexpire命令來實現加鎖,即當沒有key存在時才會成功寫入value:

$lockstatus = $redis->setnx($lockkey, 1);

if (1 === $lockstatus) elseif (0 === $lockstatus) else

但這種操作不是原子性的,如果在進行setnx時服務崩潰,沒有來得及對key進行超時設定,該鎖將一直無法釋放。

方案2

我們推薦set key value [ex seconds] [px milliseconds] [nx|xx]命令來進行加鎖

$lockstatus = $this->redis->set($lockkey, 1, "ex", 30, "nx");

if ("ok" === $lockstatus) elseif (null === $lockstatus)

如上**所示,如果set命令返回ok,那麼客戶端就可以獲得鎖(如果返回null,那麼應用服務可以在一段時間之後重新嘗試獲取鎖),並且可以通過del命令來釋放鎖。

此方法需要注意的問題:

可以通過如下優化使得上面的鎖系統變得更加健壯:

優化後的**可參考如下:

$locktoken = md5(uniqid(rand(), true));

// 此處超時時間根據具體業務邏輯配置

$expire = rand(280, 320);

$lockstatus = $this->redis->set($lockkey, $locktoken, "ex", $expire, "nx");

if ("ok" === $lockstatus)

} elseif (null === $lockstatus)

redis提供的原子自增減方法以及有序集合結構等可以承擔一些計算任務,例如瀏覽量統計等。

瀏覽計數

文章瀏覽量+1

$redis->incr($postskey);
批量獲取文章瀏覽量

$arrpostskey = [

//...

];$arrpostsviewnum = $redis->mget($arrpostskey);

排行榜

可以使用redis的有序集合來實現排行榜的功能,score作為權重排序並取前n條記錄。

// 儲存資料

$sortkey = "sort_key";

$redis->zadd($sortkey, 100, "tom");

$redis->zadd($sortkey, 80, "jon");

$redis->zadd($sortkey, 59, "lilei");

$redis->zadd($sortkey, 87, "hanmeimei");

// 獲取排行

// 由大到小排序

$arrret = $redis->zrevrange($sortkey, 0, -1, true);

// 由小到大排序

$arrret = $redis->zrange($sortkey, 0, -1, true);

Redis在Web專案中的應用與實踐

redis作為乙個開源的 bsd 基於記憶體的高效能儲存系統,已經被各大網際網路公司廣泛使用,並且有著諸多的應用場景。本篇文章將基於php來詳細講解redis在web專案中的主要應用與實踐。這裡所介紹的快取是指可以丟失或過期的資料。常用的命令有set,hset,get,hget,使用redis作為快...

Redis在Web專案中的應用與實踐

redis作為乙個開源的 bsd 基於記憶體的高效能儲存系統,已經被各大網際網路公司廣泛使用,並且有著諸多的應用場景。本篇文章將基於php來詳細講解redis在web專案中的主要應用與實踐。這裡所介紹的快取是指可以丟失或過期的資料。常用的命令有set,hset,get,hget,使用redis作為快...

Redis在Web專案中的應用與實踐

redis作為乙個開源的 bsd 基於記憶體的高效能儲存系統,已經被各大網際網路公司廣泛使用,並且有著諸多的應用場景。本篇文章將基於php來詳細講解redis在web專案中的主要應用與實踐。這裡所介紹的快取是指可以丟失或過期的資料。常用的命令有set,hset,get,hget,使用redis作為快...