<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官問:如何防超賣,有幾種實(shí)現(xiàn)方式

          共 1969字,需瀏覽 4分鐘

           ·

          2021-09-14 08:51

          場(chǎng)景


          第一種方法 悲觀鎖

          悲觀并發(fā)控制(又名 “悲觀鎖”,Pessimistic Concurrency Control,縮寫 “PCC”)是一種并發(fā)控制的方法。它可以阻止一個(gè)事務(wù)以影響其他用戶的方式來修改數(shù)據(jù)。如果一個(gè)事務(wù)執(zhí)行的操作讀某行數(shù)據(jù)應(yīng)用了鎖,那只有當(dāng)這個(gè)事務(wù)把鎖釋放,其他事務(wù)才能夠執(zhí)行與該鎖沖突的操作。


          悲觀并發(fā)控制主要用于數(shù)據(jù)爭(zhēng)用激烈的環(huán)境,以及發(fā)生并發(fā)沖突時(shí)使用鎖保護(hù)數(shù)據(jù)的成本要低于回滾事務(wù)的成本的環(huán)境中。

          竹子,公眾號(hào):碼農(nóng)編程進(jìn)階筆記php程序員面試題(偏中級(jí)面試題)

          簡(jiǎn)而言之,悲觀鎖主要用于保護(hù)數(shù)據(jù)的完整性。當(dāng)多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),某個(gè)事務(wù)對(duì)數(shù)據(jù)應(yīng)用了鎖,則其他事務(wù)只能等該事務(wù)執(zhí)行完了,才能進(jìn)行對(duì)該數(shù)據(jù)進(jìn)行修改操作。


          update goods set num = num - 1 WHERE id = 1001 and num > 0

          假設(shè)現(xiàn)在商品只剩下一件了,此時(shí)數(shù)據(jù)庫中 num = 1

          但有 100 個(gè)線程同時(shí)讀取到了這個(gè) num = 1,所以 100 個(gè)線程都開始減庫存了。

          但你會(huì)最終會(huì)發(fā)覺,其實(shí)只有一個(gè)線程減庫存成功,其他 99 個(gè)線程全部失敗。


          需要注意的是,F(xiàn)OR UPDATE 生效需要同時(shí)滿足兩個(gè)條件時(shí)才生效:

          • 數(shù)據(jù)庫的引擎為 innoDB

          • 操作位于事務(wù)塊中(BEGIN/COMMIT)


          悲觀鎖采用的是「先獲取鎖再訪問」的策略,來保障數(shù)據(jù)的安全。但是加鎖策略,依賴數(shù)據(jù)庫實(shí)現(xiàn),會(huì)增加數(shù)據(jù)庫的負(fù)擔(dān),且會(huì)增加死鎖的發(fā)生幾率。此外,對(duì)于不會(huì)發(fā)生變化的只讀數(shù)據(jù),加鎖只會(huì)增加額外不必要的負(fù)擔(dān)。在實(shí)際的實(shí)踐中,對(duì)于并發(fā)很高的場(chǎng)景并不會(huì)使用悲觀鎖,因?yàn)楫?dāng)一個(gè)事務(wù)鎖住了數(shù)據(jù),那么其他事務(wù)都會(huì)發(fā)生阻塞,會(huì)導(dǎo)致大量的事務(wù)發(fā)生積壓拖垮整個(gè)系統(tǒng)。




          第二種辦法 樂觀鎖

          select version from goods WHERE id1001;

          update goods set num = num - 1version = version + 1 WHERE id1001 AND num > 0 AND version = @version(上面查到的version);

          這種方式采用了版本號(hào)的方式,其實(shí)也就是 CAS 的原理。

          假設(shè)此時(shí) version = 100, num = 1; 100 個(gè)線程進(jìn)入到了這里,同時(shí)他們 select 出來版本號(hào)都是 version = 100。

          然后直接 update 的時(shí)候,只有其中一個(gè)先 update 了,同時(shí)更新了版本號(hào)。

          那么其他 99 個(gè)在更新的時(shí)候,會(huì)發(fā)覺 version 并不等于上次 select 的 version,就說明 version 被其他線程修改過了。那么我就放棄這次 update




          第三種方法 redis 消息隊(duì)列

          在秒殺的情況下,高頻率的去讀寫數(shù)據(jù)庫,會(huì)嚴(yán)重造成性能問題。所以必須借助其他服務(wù), 利用 redis 的單線程預(yù)減庫存。比如商品有 100 件。那么我在 redis 存儲(chǔ)一個(gè) k,v。例如

          每一個(gè)用戶線程進(jìn)來,key 值就減 1,等減到 0 的時(shí)候,全部拒絕剩下的請(qǐng)求。

          那么也就是只有 100 個(gè)線程會(huì)進(jìn)入到后續(xù)操作。所以一定不會(huì)出現(xiàn)超賣的現(xiàn)象。




          第四種辦法 redis 分布式鎖

          $expire = 10;//有效期10秒
          $key = 'lock';//key
          $value = time() + $expire;//鎖的值 = Unix時(shí)間戳 + 鎖的有效期
          $lock = $redis->setnx($key, $value);
          //判斷是否上鎖成功,成功則執(zhí)行下步操作
          if(!empty($lock))
          {
          //下單邏輯...
          }

          來自:https://learnku.com/articles/49280

          瀏覽 64
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩无码系列 | 91久久精品夜夜躁日日躁欧美 | 少妇国产jp | 91亚洲天堂 | 草啪啪 |