一起嘮嘮分布式鎖

(1)分布式鎖和分布式事務的區別

1.分布式鎖是在集群環境下,用來控制不同機器對全局共享資源的訪問。
2.分布式事務是在集群環境下,用來保證全局事務的一致性,保證多個數據庫的數據整體上能正確的從一個一致性狀態轉到另一個一致性狀態。

(2)分布式鎖應用場景

在我們的某個jvm應用程序中,如果需要對某個共享變量進行多線程同步訪問,可以使用java多線程的同步工具,例如ReentrantLock、Synchronized等等。但是當我們的系統由單機部署演化成為分布式集群系統后,在不同機器上原來單機的并發控制鎖策略就會失效了,這時就需要引入分布式鎖。
舉個簡單的例子,比如某個外賣騎士每天需要購買一份保險,某天在購買保險時,這個騎士多次點擊了買保險的按鈕,前端沒有做控制,導致同時向服務器發送了多個買保險請求,那這個時候就會導致騎士多次購買保險,為了解決這個問題,我們可以使用分布式鎖,保證在某個時間段內,只能有一臺機器執行買保險操作,這時就能保障騎士不會多次購買保險。分布式鎖主要有三種實現方式:

  1. 基于數據庫實現
  2. 基于redis實現
  3. 基于ZooKeeper實現

(3)分布式鎖實現方式

1.基于數據庫實現

我們可以通過數據庫表來實現分布式鎖,表結構如下:在這里插入圖片描述
表中的每一條記錄就代表一個鎖,當我們需要獲取鎖時就去數據庫中查詢是否有該共享資源的記錄。
(1)如果有則獲取其中的node_info,與自己的機器信息進行比較,如果發現是自己已經獲取過的鎖,那直接使用共享資源,將count數加1,在使用完數據后將count數減1,當count數為0時將記錄刪除掉。否則就返回錯誤信息,提示已經有人獲取了鎖。
(2)如果獲取不到就建立一條記錄,那就自己建立一條記錄,并記錄下自己的機器信息,然后使用共享資源。
在這里插入圖片描述
上面其實就是利用數據庫實現鎖的簡單方式。這種方式存在比較嚴重的問題:1.數據庫機器可能存在單點、2.沒有超時時間,數據庫宕掉后可能導致無法獲取鎖、3.數據庫是磁盤文件,獲取鎖的時間和性能并不好。

2.基于redis實現

基于redis的分布式鎖,主要依賴于redis的幾個命令:

  1. setnx():set if not exists,其主要有兩個參數 setnx(key, value)。該方法是原子的,如果 key 不存在,則設置當前 key 成功,返回 1;如果當前 key 已經存在,則設置當前 key 失敗,返回 0。
  2. expire():expire 設置過期時間,要注意的是 setnx 命令不能設置 key 的超時時間,只能通過 expire() 來對 key 設置。

使用步驟:
1、setnx(lockkey, 1) 如果返回 0,則獲取鎖失敗;如果返回 1,則說明獲取鎖成功。
2、expire() 命令對 lockkey 設置超時時間,為的是避免死鎖。
3、執行完業務代碼后,可以通過 delete 命令刪除 key。

使用問題:
上面的使用方式是能滿足我們大部分的業務需求的,但是在某些極端的情況下,還是會存在問題。

  1. 問題: 當節點A執行完setnx后,節點A就宕掉了,還沒來得及執行expire,那么會導致其他節點一直無法獲取鎖。
    在這里插入圖片描述
    解決方案: 使用set命令代替setnx和expire。
// NX表示:key不存在就返回true,存在就返回false
// PX表示:指定的過期時間
SET lockName value NX PX
  1. 問題: 節點A獲取了鎖,并設置了30秒的過期時間,但是由于某些原因業務代碼執行了很久(超過了30秒),delete操作還沒執行。這時因為節點A獲取的鎖過期了,節點B獲取了鎖,而節點A執行了delete操作,釋放了節點B的鎖。
    在這里插入圖片描述
    解決方案: 在通過delete操作釋放鎖之前判斷當前的鎖是不是自己加的。

當然我們也可以使用RedLock,RedLock是redis實現的分布式鎖算法(RedLock),可以有效防止單點故障 。另外還有基于Zookeeper的實現,對于Zookeeper我不咋懂,所以這里就不寫了。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450933.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450933.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

luogu2577/bzoj1899 午餐 (貪心+dp)

首先,應該盡量讓吃飯慢的排在前面,先按這個排個序 然后再來決定每個人到底去哪邊 設f[i][j]是做到了第i個人,然后1號窗口目前的總排隊時間是j,目前的最大總時間 有這個i和j的話,再預處理出前i個人的排隊總時間sum[i]&a…

wpf中xps文檔合并功能實現

原文:wpf中xps文檔合并功能實現跟著上一篇的xps文檔套打的文章,近期一直在研究xps打印技術,其中用戶提到了一個需求,要求能夠多頁面進行打印,我的想法是,先生成xps文件,然后將文件讀取出來以后,…

DCT(離散余弦變換(DiscreteCosineTransform))

離散余弦變換(Discrete Cosine Transform,簡稱DCT變換)是一種與傅立葉變換緊密相關的數學運算。在傅立葉級數展開式中,如果被展開的函數是實偶函數,那么其傅立葉級數中只包含余弦項,再將其離散化可導出余弦…

從源碼看ConcurrentHashMap

簡介 ConcurrentHashMap是線程安全的HashMap實現,這里主要研究JDK8后的ConcurrentHashMap,下面是ConcurrentHashMap的簡單結構: ConcurrentHashMap基于HashMap的基本邏輯,通過CAS synchronized 來保證并發安全性。ConcurrentHas…

代碼重構的方法

見:http://blog.csdn.net/u011889786/article/details/51865344 見:http://blog.csdn.net/weiky626/article/details/1602691 一.提取子函數 說白了就是一個大函數里,可以根據不同功能分成幾個小函數,因為說不定,其他…

android 去掉標題欄、狀態欄、橫屏

// 去掉標題欄supportRequestWindowFeature(Window.FEATURE_NO_TITLE);// 全屏、隱藏狀態欄getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 橫屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION…

Spring Boot 整合Mybatis (一)

2019獨角獸企業重金招聘Python工程師標準>>> 新建spring-boot項目&#xff0c;相關依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><de…

x264 的 cache詳解

在這里和下一級別的分析中有必要先講一下這個h->mb.cache&#xff08;沒法講&#xff0c;就是cache!&#xff09;。 x264_macroblock_cache_load將參考幀中某位置的&#xff08;重建后&#xff09;數據保存進cache&#xff0c;供參考和反復使用。 x264_macroblock_cache_s…

同步/異步阻塞/非阻塞

平時開發中經常會聽大家說到什么同步阻塞、異步非阻塞等等名詞&#xff0c;這里我談下自己對這兩個名詞的理解&#xff0c;僅僅是個人觀點&#xff0c;并不一定正確。 1.阻塞/非阻塞 我認為判定阻塞還是非阻塞&#xff0c;取決于線程所做的操作是否需要將線程掛起等待。 舉個…

Repeater的使用

1.頁面代碼 如果要分頁&#xff0c;那么頁面開頭必須寫&#xff08;<% Register Src"~/Controls/Page.ascx" TagName"Page" TagPrefix"uc1" %>&#xff09; 并且分頁&#xff0c;頁腳<uc1:Page ID"Page2" runat"server&…

springboot 整合 mongodb實現 批量更新數據

現需求&#xff1a;需要批量將1000個數據先查詢在更新到mongodb&#xff08;如果查詢不到數據&#xff0c;則添加數據&#xff09; 1&#xff1a;工具類BathUpdateOptions 1 import org.springframework.data.mongodb.core.query.Query;2 import org.springframework.data.mong…

【開題報告】基于微信小程序的校園資訊平臺的設計與實現

1.選題背景與意義 隨著移動互聯網的快速發展&#xff0c;微信成為了人們日常生活中不可或缺的工具之一。在校園生活中&#xff0c;學生們對于校園資訊的獲取和交流需求也越來越高。然而&#xff0c;傳統的校園資訊發布方式存在信息不及時、傳播范圍有限等問題&#xff0c;無法…

三種Cache寫入方式原理簡介

三種Cache寫入方式原理簡介 在386以上檔次的微機中&#xff0c;為了提高系統效率&#xff0c;普遍采用Cache&#xff08;高速緩沖存儲器&#xff09;&#xff0c;現在的系統甚至可以擁有多級Cache。Cache實際上是位于CPU與DRAM主存儲器之間少量超高速的靜態存儲器&#xff08;S…

Minor GC和Full GC

我們在日常開發中可能經常會聽大家談論GC&#xff0c;但是其實很多人對GC的種類其實并不是很了解&#xff0c;接下來我們簡單介紹下Minor GC和Full GC及他們的區別。 MinorGC&#xff1a; 也可以叫作新生代GC&#xff0c;指的是發生在新生代的垃圾收集動作。因為新生代中對象大…

linux安裝軟件的幾種方法

見&#xff1a;http://blog.csdn.net/u010509774/article/details/50593231 一、rpm包安裝方式步驟&#xff1a; 1、找到相應的軟件包&#xff0c;比如soft.version.rpm&#xff0c;下載到本機某個目錄&#xff1b; 2、打開一個終端&#xff0c;su -成root用戶&#xff1b; …

Android NDK MediaCodec在ijkplayer中的實踐

https://www.jianshu.com/p/41d3147a5e07 從API 21&#xff08;Android 5.0&#xff09;開始Android提供C層的NDK MediaCodec的接口。 Java MediaCodec是對NDK MediaCodec的封裝&#xff0c;ijkplayer硬解通路一直使用的是Java MediaCodec接Surface的方式。 本文的主要內容是&a…

leetcode-49-字母異位詞分組(神奇的哈希)

題目描述&#xff1a; 給定一個字符串數組&#xff0c;將字母異位詞組合在一起。字母異位詞指字母相同&#xff0c;但排列不同的字符串。 示例: 輸入: ["eat", "tea", "tan", "ate", "nat", "bat"], 輸出: [[&quo…

【精心總結】java內存模型和多線程必會知識

內存模型 &#xff08;1&#xff09;java內存模型到底是個啥子東西&#xff1f; java內存模型是java虛擬機規范定義的一種特定模型&#xff0c;用以屏蔽不同硬件和操作系統的內存訪問差異&#xff0c;讓java在不同平臺中能達到一致的內存訪問效果&#xff0c;是在特定的協議下…

工作流 activity 視頻教程 + redis 視頻教程 百度網盤分享地址

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 云盤下載都沒有密碼&#xff0c;直接下載&#xff0c;解壓有密碼&#xff1a;chongxiangmengxiangjiaoyu&#xff0c; 解壓完成后就可以…

快速解決 GRADLE 項目下載 gradle-*-all.zip 慢的問題

1、首先根據項目中 gradle\wrapper\gradle-wrapper.properties 文件的 distributionUrl 屬性的值 #Tue Feb 06 12:27:20 CET 2018 distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/dists distributionUrlht…