談談Redis的SETNX

來源:互聯網
上載者:User

標籤:

談談Redis的SETNX發表於2015-09-14在 Redis 裡,所謂 SETNX,是「SET if Not eXists」的縮寫,也就是只有不存在的時候才設定,可以利用它來實現鎖的效果,不過很多人沒有意識到 SETNX 有陷阱!比如說:某個查詢資料庫的介面,因為調用量比較大,所以加了緩衝,並設定緩衝到期後重新整理,問題是當並發量比較大的時候,如果沒有鎖機制,那麼緩衝到期的瞬間,大量並發請求會穿透緩衝直接查詢資料庫,造成雪崩效應,如果有鎖機制,那麼就可以控制只有一個請求去更新緩衝,其它的請求視情況要麼等待,要麼使用到期的緩衝。下面以目前 PHP 社區裡最流行的 PHPRedis 擴充為例,實現一段示範代碼:<?php$ok = $redis->setNX($key, $value);if ($ok) {    $cache->update();    $redis->del($key);}?>緩衝到期時,通過 SetNX  擷取鎖,如果成功了,那麼更新緩衝,然後刪除鎖。看上去邏輯非常簡單,可惜有問題:如果請求執行因為某些原因意外退出了,導致建立了鎖但是沒有刪除鎖,那麼這個鎖將一直存在,以至於以後緩衝再也得不到更新。於是乎我們需要給鎖加一個到期時間以防不測:<?php$redis->multi();$redis->setNX($key, $value);$redis->expire($key, $ttl);$redis->exec();?>因為 SetNX 不具備設定到期時間的功能,所以我們需要藉助 Expire 來設定,同時我們需要把兩者用 Multi/Exec 包裹起來以確保請求的原子性,以免 SetNX 成功了 Expire 卻失敗了。 可惜還有問題:當多個請求到達時,雖然只有一個請求的 SetNX 可以成功,但是任何一個請求的 Expire 卻都可以成功,如此就意味著即便擷取不到鎖,也可以重新整理到期時間,如果請求比較密集的話,那麼到期時間會一直被重新整理,導致鎖一直有效。於是乎我們需要在保證原子性的同時,有條件的執行 Expire,接著便有了如下 Lua 代碼:local key   = KEYS[1]local value = KEYS[2]local ttl   = KEYS[3]local ok = redis.call(‘setnx‘, key, value) if ok == 1 then  redis.call(‘expire‘, key, ttl)end return ok沒想到實現一個看起來很簡單的功能還要用到 Lua 指令碼,著實有些麻煩。其實 Redis 已經考慮到了大家的疾苦,從 2.6.12 起,SET 涵蓋了 SETEX 的功能,並且 SET 本身已經包含了設定到期時間的功能,也就是說,我們前面需要的功能只用 SET 就可以實現。<?php$ok = $redis->set($key, $value, array(‘nx‘, ‘ex‘ => $ttl));if ($ok) {    $cache->update();    $redis->del($key);}?>如上代碼是完美的嗎?答案是還差一點!設想一下,如果一個請求更新緩衝的時間比較長,甚至比鎖的有效期間還要長,導致在緩衝更新過程中,鎖就失效了,此時另一個請求會擷取鎖,但前一個請求在緩衝更新完畢的時候,如果不加以判斷直接刪除鎖,就會出現誤刪除其它請求建立的鎖的情況,所以我們在建立鎖的時候需要引入一個隨機值:<?php$ok = $redis->set($key, $random, array(‘nx‘, ‘ex‘ => $ttl));if ($ok) {    $cache->update();    if ($redis->get($key) == $random) {        $redis->del($key);    }}?>如此基本實現了單機鎖,假如要實現分布鎖,請參考:Distributed locks with Redis,這裡就不深入討論了,總結:避免掉入 SETNX 陷阱的最好方法就是永遠不要使用它!

 

談談Redis的SETNX

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.