視頻地址:https://ke.qq.com/course/3275764?_bid=167&_wv=3&taid=10872245856631796&term_id=103405163&from=iosapp
一、并發(fā)設(shè)計(jì)
1. 直接減庫(kù)存

存在問題:多個(gè)線程會(huì)有超賣問題
2.加進(jìn)程互斥鎖


存在問題:?jiǎn)螜C(jī)單進(jìn)程沒問題,多機(jī)(負(fù)載均衡)會(huì)有問題
3.redis 分布式鎖之setnx 命令


存在問題:沒有處理異常,鎖沒有超時(shí)時(shí)間
4. 加上處理異常,加上超時(shí)時(shí)間

存在問題:加索和超時(shí)時(shí)間是兩條命令,并非原子性
5.用原子性命令

存在問題:

高并發(fā)時(shí),問題很大。假如高并發(fā)情況下,第一個(gè)線程執(zhí)行需要15s(并發(fā)情況下服務(wù)器的執(zhí)行速度會(huì)大幅降低),但當(dāng)執(zhí)行到了第10s的時(shí)候,鎖因?yàn)槌瑫r(shí)被釋放了,第二個(gè)線程就下來(lái)了。假設(shè)第二個(gè)線程執(zhí)行需要8s,那么第一個(gè)線程執(zhí)行到了第15s時(shí),就會(huì)刪掉鎖,這時(shí)候,第二個(gè)線程還沒執(zhí)行完,但是鎖已經(jīng)被第一個(gè)線程delete掉了,這時(shí)候外面的線程又進(jìn)來(lái)了,可能第二個(gè)線程又會(huì)釋放掉第三個(gè)線程的鎖,這樣就全亂套了,這樣會(huì)導(dǎo)致鎖失效了,線程都進(jìn)來(lái)減庫(kù)存了,還是會(huì)有超賣的情況。
6. 將進(jìn)程id當(dāng)成鎖的value,在執(zhí)行完檢查當(dāng)前進(jìn)程的id是否與redis的key的值相等,相等才能釋放鎖,相當(dāng)于進(jìn)程只能釋放自己加的鎖。

存在問題:
如果在第一個(gè)線程判斷相等之后,程序卡頓,比如gc,此時(shí)剛好10s鎖超時(shí),那么第二個(gè)線程加鎖成功,此時(shí)第一個(gè)進(jìn)程再執(zhí)行delete操作,依然會(huì)釋放別的進(jìn)程的鎖。
7.鎖續(xù)命
分線程里面檢查超時(shí)時(shí)間之后,持有鎖的進(jìn)程是否還繼續(xù)持有該鎖,有則重設(shè)超時(shí)時(shí)間。
很復(fù)雜,要用成熟的中間件:redisson。
只需要三行:

原理:

利用了lua語(yǔ)言原子性。
存在問題:
1.主從架構(gòu)鎖失效問題;
線程1獲取鎖成功之后,redis master掛了,cluster 被推選為master,線程2又可以獲取鎖成功;此時(shí)又可能發(fā)生超賣問題;
解決方式:用zookeeper做分布式鎖,key-value 樹形結(jié)構(gòu)
區(qū)別(集群架構(gòu)):redis:滿足AP ; zookeeper: 滿足CAP
C 一致性,A 可用性,P分區(qū)容錯(cuò)性,zookeeper 會(huì)在返回客戶端結(jié)果之前同步所有從節(jié)點(diǎn),如果在寫了某節(jié)點(diǎn)的時(shí)候master掛了,zookeeper的選舉機(jī)制會(huì)保證寫成功的節(jié)點(diǎn)變?yōu)樾碌膌eader,意味著key不會(huì)丟失。
還有一種解決方式:RedLock(存在一些瑣碎的問題,不推薦。)

節(jié)點(diǎn)都是對(duì)等的,沒有主從關(guān)系。
2.鎖實(shí)現(xiàn)了串行,但帶來(lái)了性能問題
解決方式:分段鎖。
將庫(kù)存分布到多個(gè)鎖里面,相當(dāng)于多個(gè)隊(duì)列。

二、并發(fā)問題的解決問題
1.緩存數(shù)據(jù)庫(kù)雙寫不一致(時(shí)間線非順序,線程1更新緩存時(shí)卡頓,線程2更新了緩存后,線程1又改回去了)

加分布式鎖,有性能問題。
解決方式:
一般:讀寫鎖:讀和讀的線程互斥,寫和寫互斥。