欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP+redis實現(xiàn)的悲觀鎖機制示例

 更新時間:2018年06月12日 12:15:26   作者:grey256  
這篇文章主要介紹了PHP+redis實現(xiàn)的悲觀鎖機制,簡單介紹了redis鎖機制與樂觀鎖、悲觀鎖等概念,并結(jié)合實例形式分析了php+redis實現(xiàn)悲觀鎖相關(guān)操作技巧,需要的朋友可以參考下

本文實例講述了PHP+redis實現(xiàn)的悲觀鎖。分享給大家供大家參考,具體如下:

鎖機制

通常使用的鎖分為樂觀鎖,悲觀鎖這兩種,簡單介紹下這兩種鎖,作為本文的背景知識,對這類知識已經(jīng)有足夠了解的同學(xué)可以跳過這部分。

樂觀鎖

先來看下百度百科上的解釋:大多是基于數(shù)據(jù)版本( Version )記錄機制實現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個 “version” 字段來實現(xiàn)。讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進行比對,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。

其實說白了,就是好比一個健身房里只有一臺跑步機,在健身房門口有個排號機,每個進健身房的人都得先領(lǐng)一個號碼才能進入,如果跑步機上有人,則在一邊做做熱身、喝喝水,如果跑步機上沒人,則確認(rèn)跑步機上當(dāng)前顯示的號碼(上一個用過跑步機的人的號碼)是否比自己手持的小,如果小,則可以使用;否則,就意味著過號,而過號在現(xiàn)實中我們的都知道要么走,要么重排,就是不能插隊,在系統(tǒng)中也是一樣的,通常是返回錯誤。

悲觀鎖

同樣,來看下百度百科的解釋:具有強烈的獨占和排他特性。它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機制(也只有數(shù)據(jù)庫層提供的鎖機制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實現(xiàn)了加鎖機制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。

然后,也同樣通俗的解釋下,還是那個健身房。這次在門口不需要排號機了,而是掛著把鑰匙(只有一把),想進去的人必須拿到這把鑰匙才行,拿到鑰匙的人可以進入,不管是熱身、喝水還是跑步都可以,直到他出來把鑰匙掛回墻上,下一個才能去爭取,拿到的才可以再進去。聽著好像有點不人性化,所以悲觀鎖比較適合強一致性的場景,但效率比較低,特別是讀的并發(fā)低。樂觀鎖則適用于讀多寫少,并發(fā)沖突少的場景。

背景

先說下,本文的開發(fā)背景,方便大家了解為什么要使用悲觀鎖以及文中鎖的詳細(xì)設(shè)計。

任務(wù)分發(fā)系統(tǒng):任務(wù)池(mysql)中存在大量任務(wù)(文章),現(xiàn)在需要用戶協(xié)助編輯,系統(tǒng)基本需求如下(簡化版):

1、推送用戶感興趣的分類下的任務(wù)到用戶編輯器中;
2、用戶編輯提交一個任務(wù)后,自動推送下一個任務(wù);
3、每次只分配一個任務(wù)給用戶;
4、如果一個用戶占有某任務(wù)超過一定時間,則自動釋放任務(wù),任務(wù)進任務(wù)池,重新循環(huán);
5、……

目標(biāo)

目標(biāo)有兩個:

1、一個任務(wù)在同一時間段內(nèi)只能被一個用戶所持有;

2、避免出現(xiàn)死任務(wù),即避免任務(wù)被用戶長時間占有,無法釋放。

思路

由于系統(tǒng)并發(fā)量較大,并且有頻繁的寫操作,所以選擇悲觀鎖來控制每個任務(wù)只能同時被一個用戶領(lǐng)取。主要思路如下:

1、從任務(wù)池中找出一部分可分配的任務(wù);
2、根據(jù)一定順序,選擇一個任務(wù),作為候選推送任務(wù);
3、嘗試對候選推送任務(wù)加鎖;
4、如果加鎖成功,則推送任務(wù)給用戶,并修改對應(yīng)的任務(wù)狀態(tài)和用戶狀態(tài);
5、如果加鎖失敗,則任務(wù)已被領(lǐng)取,重復(fù)2-5,直到推送成功。

實現(xiàn)

這里只介紹下鎖的實現(xiàn)機制,其余業(yè)務(wù)邏輯略過。由于加鎖過程應(yīng)該是不可拆解的,也就是常說的原子型操作,因此這里選擇redis中的setnx操作作為加鎖的方法。

簡化版的代碼如下:

function lock($strMutex, $intTimeout) {
  $objRedis = new Redis();
  //使用setnx原子型操作加鎖
  $intRet  = $objRedis->setnx($strMutex, 1);
  if ($intRet) {
    //設(shè)置過期時間,防止死任務(wù)的出現(xiàn)
    $objRedis->expire($strMutex, $intTimeout);
    return true;
  }
  return false;
}

這段代碼有個問題,就是setnx成功,但expire失敗,這就可能存在死任務(wù)的情況。解決這個問題的一種通用方法是通過使用incr方法代替setnx,具體如下:

function lock($strMutex, $intTimeout, $intMaxTimes = 0) {
  $objRedis = new Redis();
  //使用incr原子型操作加鎖
  $intRet  = $objRedis->incr($strMutex);
  if ($intRet === 1) {
    //設(shè)置過期時間,防止死任務(wù)的出現(xiàn)
    $objRedis->expire($strMutex, $intTimeout);
    return true;
  }
  if ($intMaxTimes > 0 && $intRet >= $intMaxTimes && $objRedis->ttl($strMutex) === -1) {
    //當(dāng)設(shè)置了最大加鎖次數(shù)時,如果嘗試加鎖次數(shù)大于最大加鎖次數(shù)并且無過期時間則強制解鎖
    $objRedis->del($strMutex);
  }
  return false;
}

這段代碼通過$intMaxTimes來保證即使在expire未成功的時候也能強制解鎖,保證系統(tǒng)不會出現(xiàn)死任務(wù)。

還有沒有更好的方法呢?

其實redis中的set操作已兼容了setnx,并且支持設(shè)置過期時間。

function lock($strMutex, $intTimeout) {
  $objRedis = new Redis();
  //使用setnx操作加鎖,同時設(shè)置過期時間
  $strRet  = $objRedis->set($strMutex, 1, 'ex', $intTimeout, 'nx');
  if ($strRet === 'OK') {
    return true;
  }
  return false;
}

這個方法是我認(rèn)為目前最好的,但是為什么沒有直接介紹這個方法,而是先介紹incr那個方法呢?其實細(xì)心的同學(xué)可以看到上面那個方面有兩個加粗的字”通用“。之所以這么說是因為set方法是從redis2.6.12版本才開始支持多參數(shù)的。

水平有限,歡迎指正~

參考資料:http://redisdoc.com/string/set.html

更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php+redis數(shù)據(jù)庫程序設(shè)計技巧總結(jié)》、《php面向?qū)ο蟪绦蛟O(shè)計入門教程》、《PHP基本語法入門教程》、《PHP數(shù)組(Array)操作技巧大全》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫操作入門教程》及《php常見數(shù)據(jù)庫操作技巧匯總

希望本文所述對大家PHP程序設(shè)計有所幫助。

相關(guān)文章

  • php實現(xiàn)圖片以base64顯示的方法

    php實現(xiàn)圖片以base64顯示的方法

    這篇文章主要介紹了php實現(xiàn)圖片以base64顯示的方法,較為詳細(xì)的分析了base64編碼格式顯示圖片的相關(guān)實現(xiàn)技巧與注意事項,需要的朋友可以參考下
    2016-10-10
  • PHP的Yii框架中View視圖的使用進階

    PHP的Yii框架中View視圖的使用進階

    這篇文章主要介紹了PHP的Yii框架中View視圖的使用進階,包括布局和數(shù)據(jù)塊的創(chuàng)建使用等,需要的朋友可以參考下
    2016-03-03
  • php數(shù)組比較實現(xiàn)查找連續(xù)數(shù)的方法

    php數(shù)組比較實現(xiàn)查找連續(xù)數(shù)的方法

    這篇文章主要介紹了php數(shù)組比較實現(xiàn)查找連續(xù)數(shù)的方法,實例分析了php數(shù)組查找及字符串操作的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • PHP連續(xù)簽到功能實現(xiàn)方法詳解

    PHP連續(xù)簽到功能實現(xiàn)方法詳解

    這篇文章主要介紹了PHP連續(xù)簽到功能實現(xiàn)方法,結(jié)合實例形式詳細(xì)分析了PHP結(jié)合mysql數(shù)據(jù)庫實現(xiàn)連續(xù)簽到功能相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12
  • mac pecl 安裝php7.1擴展教程

    mac pecl 安裝php7.1擴展教程

    今天小編就為大家分享一篇mac pecl 安裝php7.1擴展教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • php判斷目錄存在的簡單方法

    php判斷目錄存在的簡單方法

    在本篇文章里小編給大家分享了關(guān)于php判斷目錄是否存在的相關(guān)知識點,有需要的朋友們參考學(xué)習(xí)下。
    2019-09-09
  • php 生成簽名及驗證簽名詳解

    php 生成簽名及驗證簽名詳解

    這篇文章主要介紹了php 生成簽名及驗證簽名詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Linux下編譯redis和phpredis的方法

    Linux下編譯redis和phpredis的方法

    這篇文章主要介紹了Linux下編譯redis和phpredis的方法,分析了redis的下載,編譯,安裝及遇到的問題與相應(yīng)的解決方法,需要的朋友可以參考下
    2016-04-04
  • 自制PHP框架之路由與控制器

    自制PHP框架之路由與控制器

    本文給大家介紹的是自制php框架的第一步,學(xué)會使用路由和控制器,非常的詳細(xì),有需要的小伙伴可以參考下
    2017-05-05
  • 解析在PHP中使用mysqli擴展庫對mysql的操作

    解析在PHP中使用mysqli擴展庫對mysql的操作

    本篇文章是對在PHP中使用mysqli擴展庫對mysql的操作進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07

最新評論