如上圖,在分布式系統中,訂單模組為了迎戰高併發,訂單服務被橫向拆分,拆分成了不同的程序,就像上圖,兩個人同時訪問訂單服務,然後訂單系統1和訂單系統2共用乙個mysql當成資料庫,經過他們查詢發現僅有一件商品,所以他們自個認為都可以下單
如果不加鎖限制,可能會出現庫存減為負數的情況
怎麼辦呢?
如上圖mysql自帶行級鎖,可以考慮使用它的行級鎖,可以保證資料的安全,但是不足之處也跟著來了,使用mysql的行級鎖,系統的中壓力就全部集中在mysql,那mysql就是系統吞吐量的瓶頸了,系統的吞吐量也會收到mysql的限制
可以使用分布式鎖
如上圖,分布式鎖將系統的壓力從mysql上面轉移到自己身上來
一句話,分布式鎖是實現有序排程不同的程序,解決不同程序之間相互干擾的問題的技術手段
先去redis中使用setnx(商品id,數量) 得到返回結果
這裡的數量無所謂,它的作用就是告訴其他服務,我加上了鎖
發現redis中有數量,說明已經可以加鎖了
發現redis中沒有資料,說明已經獲得到了鎖
解鎖: 使用redis的 del商品id
鎖超時, 設定exprie 生命週期,如30秒, 到了指定時間,自定解鎖
三個致命問題
因為 setnx和expire不是原子性的,要麼都成功要麼都失敗, 一旦出現了上面的情況,就會導致死鎖出現
redis提供了原子性的操作set ( key , value , expire)
解決方法, 在刪除之前,判斷是不是自己的鎖
redis提供了原子性的操作set ( key ,threadid, expire)
增加乙個守護執行緒,當快要超時,但是任務還沒執行完成,就增加鎖的時間
使用zookeeper的臨時順序節點
系統1和系統2在執行業務邏輯之前都需要先獲取到鎖,然後他們就是/lock
節點下建立臨時順序節點,序號最小的節點的建立者視為獲取到了鎖,可以進行其他業務操作,當它執行完成後,將這個節點刪除掉視為釋放了鎖
釋放鎖後如何通知其他節點呢?
使用zk的watcher**機制, 讓後乙個節點對它的前乙個臨時順序節點繫結watcher,當有事務性操作時發生**,進而判斷出自己剛才建立的節點是不是最小的,如果是說明自己拿到了鎖
臨時順序節點保證了系統不會因為某台機器掛掉而出現死鎖的情況
嘗試加鎖的方法如下:
public boolean trylock() else
}});
// 在countdownlatch減完之前,會阻塞在這裡等待
countdownlatch.await();
return true;
}} catch (exception e)
// 按理說應該在監聽的**裡面返回true,但是在這個**裡面返回不了true,現在就使用countdownlatch,**的時候去改變countdownlatch的值
return true;
}
深入理解分布式事務
碼農網 吳極心 當資料庫單錶一年產生的資料超過1000w,那麼就要考慮分庫分表,具體分庫分表的原理在此不做解釋,以後有空詳細說,簡單的說就是原來的乙個資料庫變成了多個資料庫。這時候,如果乙個操作既訪問01庫,又訪問02庫,而且要保證資料的一致性,那麼就要用到分布式事務。所謂的soa化,就是業務的服務...
深入理解分布式事務
當資料庫單錶一年產生的資料超過1000w,那麼就要考慮分庫分表,具體分庫分表的原理在此不做解釋,以後有空詳細說,簡單的說就是原來的乙個資料庫變成了多個資料庫。這時候,如果乙個操作既訪問01庫,又訪問02庫,而且要保證資料的一致性,那麼就要用到分布式事務。所謂的soa化,就是業務的服務化。比如原來單機...
深入理解分布式事務
我在上一期介紹了spring的事務原理 詳情見 深入理解spring事務原理 spring事務 本質是單機下的事務,是由資料庫本身保證的。今天,我將介紹一種比較複雜的事務 分布式事務 當資料庫單錶一年產生的資料超過1000w,那麼就要考慮分庫分表,具體分庫分表的原理在此不做解釋,以後有空詳細說,簡單...