一、緩存
Redis最常見的用途是作為緩存。所謂緩存,就是將頻繁讀取、但不經常修改的數據存儲在內存中,用戶請求數據時優先從內存中讀取,可大幅提升數據訪問效率。Redis的數據結構特別適合緩存場景,並且其本身的讀取速度也非常快,可以在存儲海量並發訪問情況下保持響應性能。
對於訪問頻率較高的網站,可通過將熱門數據存入Redis中,降低對數據庫的訪問壓力。例如,盛大遊戲就使用Redis緩存了用戶會話信息,避免了每次訪問都需要讀取數據庫的開銷,從而獲得了更好的性能。
<?php
// 通過Redis緩存獲取數據
$key = 'hot_user_list';
$data = $redis->get($key);
if (!$data) {
// 緩存未命中,從數據庫獲取數據
$data = $db->select("SELECT * FROM user WHERE role = 'hot'");
$redis->set($key, $data);
}
二、分布式鎖
在高並發的場景下,請求可能會同時湧入並嘗試對同一個資源進行修改。例如,多個用戶同時搶購同一件商品,此時需要保證只有一個用戶能夠成功搶購。而分布式鎖就是用來解決這一問題的。
Redis可以通過SETNX(set if not exist)命令實現分布式鎖。當多個請求同時嘗試對同一資源加鎖時,只有一個請求能夠成功返回1,其他請求都會等待,直到鎖被釋放。由於Redis天生支持分布式,使用它實現分布式鎖非常方便。
<?php
// 嘗試加鎖
$is_locked = $redis->setnx("resource_key", 1);
if ($is_locked) {
// 成功加鎖,進行資源操作
operate_resource();
// 釋放鎖
$redis->del("resource_key");
} else {
// 未獲取到鎖,等待重試或返回錯誤
return 'Resource is locked';
}
三、消息隊列
消息隊列是一類特殊的數據結構,用於存儲並轉發消息。在高並發的場景下,將任務儘可能地異步化處理,是提高系統並發能力的關鍵。而Redis的LIST命令提供的隊列特性,使得它成為一個好的消息隊列候選者。
例如,在電商後台系統中,訂單狀態變化的同時需要發送通知給用戶,若採用同步方式處理,則用戶的請求響應速度會變慢。但若採用消息隊列,將訂單狀態變化事件放入隊列中,再使用後台任務進行異步處理,便能避免用戶等待,提升整體系統的性能。
<?php
// 生產者向消息隊列推送消息
$redis->lpush('order_queue', $order_id);
// 消費者從消息隊列獲取消息並處理
while ($order_id = $redis->rpop('order_queue')) {
process_order($order_id);
}
四、統計分析
Redis除了能夠存儲數據外,還可以進行一些簡單的數據分析。例如,可以利用Redis的HyperLogLog(基數統計算法)或者布隆過濾器(一種高效的數據結構,用於判斷一個元素是否存在於一個集合中)實現訪問用戶量、UV統計等數據分析。
前段時間,某直播平台的負責人表示,如果在數據庫中進行UV統計,每天都需要統計上億條數據,成本將會非常巨大。但如果使用Redis,就能大幅降低成本,提升實時性。
<?php
// 統計日訪問量
$redis->pfadd('day_visit', $user_id);
$visit_count = $redis->pfcount('day_visit');
五、分布式鎖模板代碼示例
<?php
class RedisLock
{
private $redis;
private $key;
private $expires;
private $token;
public function __construct(Redis $redis, string $key, int $expires = 5)
{
$this->redis = $redis;
$this->key = $key;
$this->expires = $expires;
$this->token = uniqid();
}
public function acquire(): bool
{
return $this->redis->set($this->key, $this->token, ['NX', 'EX' => $this->expires]);
}
public function release(): bool
{
$lua = <<redis->eval($lua, 1, $this->key, $this->token);
}
}
以上是純文本,可以直接複製使用。需要注意的是,該代碼示例使用了Lua腳本實現了釋放鎖時驗證鎖的持有者和刪除鎖的操作是一個原子操作,保證了鎖釋放的原子性。
原創文章,作者:JAHEC,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/372615.html