Redis之分布式鎖(2)

? ? ? ? 上一篇文章我們介紹了什么是分布式鎖和分布式鎖的一些基本概念。這篇文章我們來講解一下基于數據庫如何實現分布式鎖。

基于數據庫實現分布式鎖

? ? ? ? 基于數據庫實現分布式鎖可以分為兩種方式,分別是基于數據庫表和基于數據庫排他鎖。

基于數據庫表

? ? ? ? 要實現分布式鎖,最簡單的方式可能就是直接創建一張鎖表,然后通過操作該表中的數據來實現。當我們要鎖住某個方法或者資源時,我們就在這張表中增加一條記錄,想要釋放鎖的時候就刪除這條記錄。

? ? ? ? 當我們想要鎖住某個方法時,執行以下SQL語句:

insert into methodLock(method_name,desc) values ('method_name','desc');

? ? ? ? 因為我們對method_name做了唯一性約束,這里如果有多個請求同時提交到數據庫的話,數據庫會保證只有一個操作可以成功,那么我們就可以認為操作成功的那個線程獲得了該方法的鎖,可以執行方法的具體內容。

? ? ? ? 當方法執行完成后,想要釋放鎖時,可以執行以下SQL語句:

delete from methodLock where method_name = 'method_name';

? ? ? ? 但是上面這種簡單的實現存在以下四個問題:

? ? ? ? (1)這把鎖強依賴數據庫的可用性,數據庫是一個單點,一旦數據庫掛掉,會導致業務系統不可用;

? ? ? ? (2)這把鎖沒有失效時間,一旦解鎖操作失敗,就會導致鎖記錄一直在數據庫中,其他線程無法再獲得到鎖;

? ? ? ? (3)這把鎖只能是非阻塞的,因為數據的insert操作,一旦插入失敗就會直接報錯。沒有獲得鎖的線程并不會進入排隊隊列,要想再次獲得鎖就要再次觸發獲得鎖的動作;

? ? ? ? (4)這把鎖是非重入的,同一個線程在沒有釋放鎖之前無法再次獲得該鎖。因為數據中數據已經存在了。

? ? ? ? 針對以上的問題,我們可以通過以下方式來進行解決:

? ? ? ? (1)可以使用數據庫集群來代替單點數據庫;

? ? ? ? (2)可以定義一個定時任務,每隔一定時間把數據庫中的超時數據清理一遍來解決鎖沒有超時時間的問題;

? ? ? ? (3)可以使用while循環進行不斷的insert嘗試,直到成功,解決鎖是非阻塞的問題;

? ? ? ? (4)可以在數據庫中加入一個字段,記錄當前獲得鎖的機器的主機信息和線程信息,那么下次再獲取鎖時先查詢數據庫,看這個字段記錄的是否是當前獲取鎖的主機信息和線程信息,如果是,那就直接進行鎖的分配即可。

基于數據庫排他鎖

? ? ? ? 除了可以通過增刪操作數據表中的記錄以外,還可以借助數據庫自帶的鎖來實現分布式鎖。

? ? ? ? 基于MySQL的InnoDB引擎,可以使用以下方式來進行加鎖操作:

public boolean lock(){connection.setAutoCommit(false);while(true){try{result = select * from methodLock where method_name = ... for update;if(result == null){return true;}}catch(Exception e){}sleep(1000);}return false;
}

? ? ? ? 在查詢語句后面增加for update,數據庫會在查詢過程中給數據庫表增加排他鎖(InnoDB引擎在加鎖的時候,只有通過索引進行檢索的時候才會使用行鎖,否則會使用表鎖。這里我們希望使用行鎖,就要給method_name添加索引。這個索引一定要創建成唯一索引,否則會出現多個重載方法之間無法同時被訪問的問題。重載方法的話建議把參數類型也加上)。當某條記錄被加上排他鎖之后,其他線程無法再在該行記錄上增加排他鎖。

? ? ? ? 我們可以認為獲得排他鎖的線程即可獲得分布式鎖,當獲取到鎖之后,可以執行方法的業務邏輯,執行完方法之后,再通過以下方式進行解鎖:

public void unlock(){connection.commit();
}

? ? ? ? 通過connection.commit()操作來釋放鎖,可以有效的解決上面提到的無法釋放鎖和非阻塞鎖問題。for update語句會在執行成功之后立即返回,在執行失敗時會一直處于阻塞狀態,直到成功;使用這種方式,出現意外時數據庫會自動將鎖釋放掉。但是這種方法還是無法直接解決掉數據庫單點和鎖不可重入問題。

? ? ? ?使用這種方法還會帶來新的問題,雖然我們對method_name使用了唯一索引,并且顯示使用for update來使用行鎖。但是,MySQL會對查詢進行優化,即使在條件中使用了索引字段,但是否使用索引來進行檢索還是由MySQL通過判斷不同執行計劃的代價來決定。如果最終MySQL走了表鎖而沒有走行鎖,那么這種方式就失效了;另一個問題是,如果我們使用排他鎖來實現分布式鎖,那么一個排他鎖長時間不提交,就會占用數據庫連接。一旦類似的連接變得多了,就可能把數據庫連接池撐爆。

總結

? ? ? ? 依賴數據庫實現分布式鎖有兩種方法,一種是基于數據庫表,一種是基于數據庫的排他鎖。直接借助數據庫實現分布式鎖容易理解,但是其實現上會有各種各樣的問題,解決這些問題會使得方案變得復雜,并且操作數據庫會帶來一定的性能開銷,行鎖的使用也不想我們認為的那樣可靠,尤其是表比較小的時候很可能不走索引導致使用表鎖。

? ? ? ? 這篇文章我們講解了如何基于數據庫實現分布式鎖,大家有什么問題或者勘誤可以在評論區留言,筆者看到都會回復的。

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

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

相關文章

智能檢測護航電池產業:容量設備如何提升效率與安全?

電池容量是衡量其儲能能力的重要指標,直接影響設備續航與使用壽命。電池容量檢測設備通過模擬真實使用場景,精準測量電池的充放電性能,為電池生產、質檢及回收環節提供關鍵數據支持,成為保障電池品質與安全的核心工具。 核心功能…

介紹一款免費MES、開源MES系統、MES源碼

一、系統概述: 萬界星空科技免費MES、開源MES、商業開源MES、市面上最好的開源MES、MES源代碼、適合二開的開源MES。 1.萬界星空開源MES制造執行系統的Java開源版本。 開源mes系統包括系統管理,車間基礎數據管理,計劃管理,物料控制…

構建高性能日志系統:QGroundControl日志模塊深度解析

引言:日志系統的重要性 在無人機地面站系統中,日志記錄是診斷問題、分析性能的關鍵基礎設施。QGroundControl(QGC)作為領先的開源無人機地面站軟件,其日志系統設計值得深入探討。本文將揭示QGC日志系統的核心技術&…

k8s查看內存占用前十的20個pod服務,不包括job

在 Kubernetes 中,您可以使用 kubectl 命令結合一些工具來查看內存占用前十的 Pod 服務,并排除 Job 類型的 Pod。以下是一個示例命令,您可以在終端中運行: kubectl top pods --all-namespaces --no-headers | grep -v job | sort …

Spring Boot 集成 LangChain4j 示例

文章目錄 概述一、DeepSeek API Key 獲取二、Spring Boot 集成 LangChain4j 示例三、拓展建議 概述 LangChain4j 是 LangChain 在 Java 生態下的實現,它是一個開源庫,幫助你更方便地在 Spring Boot 應用中集成大語言模型(如 OpenAI 的 GPT-4…

數據差異的iOS性能調試:設備日志導出和iOS文件管理

在復雜iOS項目中,尤其是集成多個第三方服務、使用混合數據源(本地遠程緩存)的系統里,“數據不一致”類問題極具迷惑性。一方面,數據看似可用,邏輯層也沒有明顯錯誤;另一方面,用戶層面…

二進制與生活:從數字世界到人生哲理

二進制與生活:從數字世界到人生哲理 最近重溫《少年謝爾頓》,被劇中謝爾頓與二進制對話的場景深深打動。這讓我思考:二進制這個看似冰冷的數字系統,其實與我們的生活有著千絲萬縷的聯系。今天,讓我們一起走進二進制的世…

基于SMB協議的內網存活主機探測技術研究

一、 技術背景 SMB(Server Message Block)協議是Windows環境中廣泛使用的網絡文件共享協議,默認開放于445端口。由于其在Windows系統中的核心地位,SMB協議常被用作內網探測的重要切入點。本文系統介紹多種基于SMB的存活主機探測技術,幫助安全…

IDEA21中文亂碼解決辦法

我改了很多,可能也改了一些沒用的 1.在VM options中添加-Dstdout.encodingUTF-8 -Dstderr.encodingUTF-8 2.IDEA 控制臺輸出設置為 UTF-8 打開 IDEA → File → Settings(或 CtrlAltS) 搜索 "Encoding" 設置 Project Encoding 和…

時序數據庫概念及IoTDB特性詳解

一、數據庫管理系統概述 數據,如同空氣般普遍存在于我們的數字生活中,每一次點擊手機都可能產生并記錄數據。這些數據被存儲在數據庫中,而數據庫實質上是“數據的集合”。數據庫管理系統(DBMS)則負責這些“數據容器”…

leetcode:263. 丑數(python3解法,數學相關算法題)

難度:簡單 丑數 就是只包含質因數 2、3 和 5 的 正 整數。 給你一個整數 n ,請你判斷 n 是否為 丑數 。如果是,返回 true ;否則,返回 false 。 示例 1: 輸入:n 6 輸出:true 解釋&am…

RK3568筆記八十五:LVGL播放AVI視頻

若該文為原創文章,轉載請注明原文出處。 最近有個需求,需要播放視頻,但使用的框架是LVGL顯示,所以了解了下LVGL怎么實現播放視頻。 目前了解到的方法有兩種: 一、使用ffmpeg方式,此方法適用于大部分視頻 二、使用opencv方式,此方法適用于大部分視頻 三、使用woshin…

stm32使用定時器PWM

1、定時器TIM PSC-Prescaler-預分頻器 CNT-Counter-計數器 ARR-Auto Reload Register-自動重裝寄存器 RCR-Repetition Counter Register-重復計數器 1、時鐘來源:晶振提供頻率,時鐘樹這些才提供時鐘 分頻系數 計數 3、實例 上面展示了假設使用外部石英晶振提供32.76…

2.3 Windows Vcpkg+MSVC編譯FFmpeg 4.4.1

一、vcpkg安裝ffmpeg 4.4.1 vcpkg的使用可以參考之前的文章:vcpkg 使用 1.1 查看vcpkg中的ffmpeg版本 查看庫的版本:vcpkg.io 1.2 vcpkg.json文件解析 創建vcpkg.json文件: {"builtin-baseline": "984f9232b2fe0eb94f…

docker -v 之后docker cp報錯

問題 我現在在本地已經可以正確運行這個文本糾錯接口了,使用了-v 掛載,,當我使用docker cp時,報錯了Error response from daemon: unlinkat /app/pycorrector/.git/objects/pack/pack-xxxxxx.pack: device or resource busy&…

10人團隊SolidWorks云桌面服務器怎么連接

在當今數字化設計領域,SolidWorks作為主流的三維CAD軟件,對硬件性能要求較高。 對于10人團隊共享使用場景,云桌面服務器方案能有效解決硬件成本高、協作效率低等問題,這需從硬件選型、網絡架構、云桌面平臺部署、軟件授權管理及用…

從源碼角度了解Elasticsaerch(分布式協調排序、深分頁問題)

引文 Elasticsearch基于Lucene所以很多系統實現都在其中,所以可以先看看Lucene的實現: https://blog.csdn.net/qq_35040959/article/details/147931034 項目組件 不像Kafka這種頂級項目核心性能組件全自己實現,ELK中有很多引用至第三方開放庫; 網絡模型-Netty 網絡模型多重…

共讀AI新圣經-深度學習讀書筆記01

提示:本文是我參加datawhale活動的讀書筆記,這是第一章的閱讀筆記 文章目錄 前言一、深度學習能做什么?二、教學案例總結 前言 隨著大數據和算力的大幅提升,基于數據學習的解決方案正取代基于人工設計的解決方案 提示&#xff1a…

Android項目資源字符串內容多語言對齊工具 Python

Android項目資源字符串內容多語言對齊工具: #!/usr/bin/env python3import re from dataclasses import dataclass, field from typing import Optional, Dict, List from pathlib import Path import tkinter as tk from tkinter import filedialog, messageboxda…