深入理解分布式鎖

2022-01-10 20:41:33 字數 1952 閱讀 6787

如上圖,在分布式系統中,訂單模組為了迎戰高併發,訂單服務被橫向拆分,拆分成了不同的程序,就像上圖,兩個人同時訪問訂單服務,然後訂單系統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,那麼就要考慮分庫分表,具體分庫分表的原理在此不做解釋,以後有空詳細說,簡單...