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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

nx set 怎么实现的原子性_正确地使用Redis的SETNX实现锁机制

發布時間:2023/12/13 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nx set 怎么实现的原子性_正确地使用Redis的SETNX实现锁机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

setNX,是set if not exists 的縮寫,也就是只有不存在的時候才設置, 設置成功時返回 1 , 設置失敗時返回 0 ??梢岳盟鼇韺崿F鎖的效果,但是很多人在使用的過程中都有一些問題沒有考慮到。

例如某個查詢數據庫的接口因為請求量比較大所以加了緩存,并設定緩存過期后刷新。當并發量比較大并且緩存過期的瞬間,大量并發請求會直接查詢數據庫導致雪崩。如果使用鎖機制來控制只有一個請求去更新緩存就能避免雪崩的問題。下面是很多人下意識想到的加鎖方法

$rs = $redis->setNX($key, $value);

if ($rs) {

//處理更新緩存邏輯

// ......

//刪除鎖

$redis->del($key);

}

?>

通過 setNX 獲取鎖,如果成功了則更新緩存然后刪除鎖。其實這里有一個嚴重的問題:如果更新緩存的時候因為某些原因意外退出了,那么這個鎖就不會被刪除而一直存在,以至于緩存再也得不到更新。為了解決這個問題有人可能會想到給鎖設置一個過期時間,如下

$redis->multi();

$redis->setNX($key, $value);

$redis->expire($key, $ttl);

$redis->exec();

?>

因為 setNX 不具備設置過期時間的功能,所以要借助 Expire 來設置,同時需要使用 Multi/Exec 來確保請求的原子性,以免 setNX 成功了 Expire 卻失敗了。這樣還有問題:當多個請求到達時,雖然只有一個請求的 setNX 可以成功,但是任何一個請求的 Expire 卻都可以成功,這就意味著即便獲取不到鎖也可以刷新過期時間,導致鎖一直有效,還是解決不了上面的問題。顯然 setNX 滿足不了需求,Redis從 2.6.12 起,SET 涵蓋了 SETEX 的功能, SET 本身又包含了設置過期時間的功能,所以使用 SET 就可以解決上面遇到的問題。

$rs = $redis->set($key, $value, array('nx', 'ex' => $ttl));

if ($rs) {

//處理更新緩存邏輯

// ......

//刪除鎖

$redis->del($key);

}

?>

到這一步其實還是有問題的,如果一個請求更新緩存的時間比鎖的有效期還要長,導致在緩存更新過程中鎖就失效了,此時另一個請求就會獲取到鎖,但前一個請求在緩存更新完畢的時候,直接刪除鎖的話就會出現誤刪其它請求創建的鎖的情況。所以要避免這種問題,可以在創建鎖的時候需要引入一個隨機值并在刪除鎖的時候加以判斷

$rs = $redis->set($key, $random, array('nx', 'ex' => $ttl));

if ($rs) {

//處理更新緩存邏輯

// ......

//先判斷隨機數,是同一個則刪除鎖

if ($redis->get($key) == $random) {

$redis->del($key);

}

}

?>

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的nx set 怎么实现的原子性_正确地使用Redis的SETNX实现锁机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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