日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

redis setnx 分布式锁_Redis 分布式锁PHP

發布時間:2025/3/15 php 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis setnx 分布式锁_Redis 分布式锁PHP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Redis 分布式鎖的作用

在單機環境下,有個秒殺商品的活動,在短時間內,服務器壓力和流量會陡然上升。這個就會存在并發的問題。想要解決并發需要解決一下問題

1、提高系統吞吐率也就是qps 每秒處理的請求書

解決問題一:采用內存型數據庫提高系統的qps

解決問題二:就要用到經常會遇到的鎖,例如MySQL 有讀鎖、寫鎖、排他鎖、悲觀鎖、樂觀鎖。不過這里只討論redis來實現鎖

簡單版設置鎖

$redis = new Redis();
$redis->connect('127.0.0.1', 6379); //連接Redis
$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//鎖的值 = Unix時間戳 + 鎖的有效期
$lock = $redis->setnx($key, $value);
//判斷是否上鎖成功,成功則執行下步操作
if(!empty($lock))
{
//下步操作...
}

如果以這樣的簡單版設置鎖就能解決所有問題,未免也太小看?鎖 在程序中應用了。

按正常的操作示例基本上都是這樣寫的。但是這樣寫有一些問題

1、假如有10000 個請求訪問了redis 不存在的鍵,這樣請求就是指接到了MySQL數據,造成CPU短時間內達到100%甚至宕機。這樣場景俗稱緩存擊穿造成的緩存雪崩。

解決問題:引用reids setnx 方法的作用是,當設置的key 不存在時,設置新的值。這樣就避免了緩存擊穿的問題。檢測鍵的過期時間,避免產生死鎖

解決死鎖問題

$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//鎖的值 = Unix時間戳 + 鎖的有效期
$status = true;
while($status)
{
$lock = $redis->setnx($key, $value);
if(empty($lock))
{
$value = $redis->get($key);
if($value < time())
{
$redis->del($key);
}
}else{
$status = false;
//下步操作....
}
}

2、分布式集群業務業務場景下,每臺服務器是獨立存在的。多臺服務器怎么通過一個標識來相互競爭鎖呢。這里就用到了分布式鎖

這里簡單介紹一下,以MYSQL 的事務機制來延生。事務四個特性ACID,有四種隔離級別:為提交讀、已提交讀、可重復讀、串行化。這些特性都只在單臺服務器上生效。到了分布式集群了,數據在不同的服務器上,緊靠事務很難保持數據的一致性及隔離性,事務的作用就意義不大了。Redis也是如此。

正確的分布式鎖的打開方式

/**
* 實現Redis分布鎖
*/
$key = 'demo'; //要更新信息的緩存KEY
$lockKey = 'lock:'.$key; //設置鎖KEY
$lockExpire = 10; //設置鎖的有效期為10秒
//獲取緩存信息
$result = $redis->get($key);
//判斷緩存中是否有數據
if(empty($result))
{
$status = TRUE;
while ($status)
{
//設置鎖值為當前時間戳 + 有效期
$lockValue = time() + $lockExpire;
/**
* 創建鎖
* 試圖以$lockKey為key創建一個緩存,value值為當前時間戳
* 由于setnx()函數只有在不存在當前key的緩存時才會創建成功
* 所以,用此函數就可以判斷當前執行的操作是否已經有其他進程在執行了
* @var [type]
*/
$lock = $redis->setnx($lockKey, $lockValue);
/**
* 滿足兩個條件中的一個即可進行操作
* 1、上面一步創建鎖成功;
* 2、 1)判斷鎖的值(時間戳)是否小于當前時間 $redis->get()
* 2)同時給鎖設置新值成功 $redis->getset()
*/
if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() ))
{
//給鎖設置生存時間
$redis->expire($lockKey, $lockExpire);
//******************************
//此處執行插入、更新緩存操作...
//******************************
//以上程序走完刪除鎖
//檢測鎖是否過期,過期鎖沒必要刪除
if($redis->ttl($lockKey))
$redis->del($lockKey);
$status = FALSE;
}else{
/**
* 如果存在有效鎖這里做相應處理
* 等待當前操作完成再執行此次請求
* 直接返回
*/
sleep(2);//等待2秒后再嘗試執行操作
}
}
}

結尾

文章從知識面的廣度(mysql)、示例代碼優缺點的簡介及應用的場景,區別于其他博客文章。嘿嘿~

更多精彩

敬請關注“PHP技術大全”微信公眾號

總結

以上是生活随笔為你收集整理的redis setnx 分布式锁_Redis 分布式锁PHP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。