新聞中心
redis如何防止并發(fā)?
對(duì)于很多系統(tǒng)而言,都有集群處理。在集群中使用quartz或者task處理任務(wù)的時(shí)候,一般有三種選擇:

創(chuàng)新互聯(lián)公司于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目做網(wǎng)站、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元十堰鄖陽做網(wǎng)站,已為上家服務(wù),為十堰鄖陽各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
1. 多實(shí)例順序執(zhí)行
2. 單實(shí)例執(zhí)行
3. 多實(shí)例并行執(zhí)行
創(chuàng)保目前考慮的是1情況。
redis對(duì)于并發(fā)較小的情況下,進(jìn)行鎖控制,效果是較為理想的。目前創(chuàng)保只有八臺(tái)實(shí)例,適用于該方案。
1. 首先,redis提供了一個(gè)setnx方法,該方法執(zhí)行后會(huì)返回key值在設(shè)置之前是否存在。
這是進(jìn)行并發(fā)控制的基礎(chǔ),但并不夠。
2. 在利用 setnx 進(jìn)行 key 值設(shè)定后,如果instance發(fā)生異常(不僅僅是exception)會(huì)導(dǎo)致該鎖無法正常釋放。
所以,我們需要為鎖設(shè)置一個(gè)失效時(shí)間,即expire命令。
1. 問題描述
并發(fā)競(jìng)爭(zhēng)key這個(gè)問題簡(jiǎn)單講就是:
同時(shí)有多個(gè)客戶端去set一個(gè)key。
示例場(chǎng)景 1
例如有多個(gè)請(qǐng)求一起去對(duì)某個(gè)商品減庫存,通常操作流程是:
假設(shè)當(dāng)前庫存值為 20,現(xiàn)在有2個(gè)連接都要減 5,結(jié)果庫存值應(yīng)該是 10 才對(duì),但存在下面這種情況:
示例場(chǎng)景 2
比如有3個(gè)請(qǐng)求有序的修改某個(gè)key,按正常順序的話,數(shù)據(jù)版本應(yīng)該是 1->2->3,最后應(yīng)該是 3。
但如果第二個(gè)請(qǐng)求由于網(wǎng)絡(luò)原因遲到了,數(shù)據(jù)版本就變?yōu)榱?1->3->2,最后值為 2,出問題了。
1.Redis寫入是單線程的,單個(gè)命令執(zhí)行不存在并發(fā)問題
2.如果是get命令,然后判斷再進(jìn)行set,那就有并發(fā)問題,set值不正確,舉例:庫存系統(tǒng),get庫存大于零,則庫存減一再set庫存,并發(fā)條件下,get得到的庫存有可能是一樣的,所以set回去的庫存也是一樣的,所以庫存少減了,導(dǎo)致商品實(shí)際庫存不足,多賣的情況,秒殺活動(dòng)那就會(huì)比較危險(xiǎn)了
3.解決辦法,加入一個(gè)分布式鎖
redis 本身是單進(jìn)程、單線程的模型,就是說一個(gè)時(shí)刻就只能有一個(gè)東東在執(zhí)行,不管是多少個(gè)命令,只能是串行執(zhí)行,因此從這個(gè)意義上保證了單個(gè)命令執(zhí)行的多線程(多個(gè)客戶端操作)的安全,也就是不管有多少個(gè)客戶端在發(fā)請(qǐng)求,redis每次只能執(zhí)行一個(gè)客戶端的命令,不存在多線程。
但是redis對(duì)于多個(gè)客戶端的多個(gè)命令,并不能保證其線程安全性,比如有一個(gè)值x=1;如果ClientA 獲取x的值,x=x+1,然后再設(shè)置回去;在此期間,有一個(gè)ClientB做同樣的操作;如果ClientA、ClientB的操作被串行了,那么x=3;但是多個(gè)命令之間不能保證(除非是增加了所謂的鎖之類的東東),從而x的值就不一定是3了,這個(gè)時(shí)候就存在了并發(fā)操作的問題。
當(dāng)然redis也考慮到了相關(guān)的情況,提供了incr之類的原子操作命令,保證了多線程并發(fā)操作的安全性;
對(duì)于同一個(gè)客戶的多次點(diǎn)擊操作,如果不做區(qū)分,可能就存在問題,比如支付寶的種樹澆水這個(gè)操作,如果不做控制,一個(gè)用戶快速的多次點(diǎn)擊,可能就會(huì)超過3次(支付寶限制一天只能幫某個(gè)好友澆水3次),這個(gè)時(shí)候其實(shí)有簡(jiǎn)單的解決方法:比如每次澆水有一個(gè)澆水ID,第1、2、3次都有一個(gè)不同的ID,從第4次開始的操作其ID還是設(shè)置為3(由客戶端來限制),那么后臺(tái)只要判斷ID是否重復(fù),就可以做過濾; 同樣的問題在第三方API對(duì)接的時(shí)候也存在(比如調(diào)用支付寶付款,有時(shí)候網(wǎng)絡(luò)不好,是否會(huì)存在多次付費(fèi)問題?),此時(shí)我想每個(gè)支付的請(qǐng)求也帶了一個(gè)唯一的ID,保證了支付的唯一性(當(dāng)然可能還會(huì)有對(duì)用戶名、支付款項(xiàng)的驗(yàn)證--銀行支付的時(shí)候往往會(huì)提醒你,你支付了一筆同樣的款項(xiàng),需要確認(rèn)--具體的場(chǎng)景是你需要支付某人1000塊,你分成500、500兩筆,此時(shí)網(wǎng)銀操作是會(huì)提醒你的);
因此對(duì)于相同的2個(gè)請(qǐng)求,如果是一種冪等的操作--比如都是get某個(gè)值(不會(huì)變的),那么其實(shí)處不處理看策略,至少不會(huì)造成不一致;對(duì)于支付這樣的行為,肯定需要做判斷確定是同一個(gè)請(qǐng)求,對(duì)另外一個(gè)請(qǐng)求做過濾。
到此,以上就是小編對(duì)于redis 并發(fā)鎖的問題就介紹到這了,希望這1點(diǎn)解答對(duì)大家有用。
本文題目:redis如何防止并發(fā)?(redis怎么實(shí)現(xiàn)并發(fā)鎖)
網(wǎng)站網(wǎng)址:http://m.fisionsoft.com.cn/article/cddjjso.html


咨詢
建站咨詢
