目前幾乎不少大型網站及應用都是分佈式部署的,分佈式場景中咱們也都會遇到一個很是重要的問題:數據一致性。正如分佈式的CAP理論說的同樣:「任何一個分佈式系統都沒法同時知足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),最多隻能同時知足兩項。」因此,不少系統在設計之初就要對這三者進行取捨。在互聯網領域的絕大多數的場景中,都須要犧牲強一致性來換取系統的高可用性,系統每每只須要保證「最終一致性」,只要這個最終時間是在用戶能夠接受的範圍內便可。redis
在不少場景中,咱們爲了保證數據的最終一致性,須要不少的技術方案來支撐,好比分佈式事務、分佈式鎖、定時任務調度等。儘管Java提供了不少併發處理API,但這些API在分佈式場景中就顯得無能爲力了。sql
因此針對分佈式鎖的實現咱們須要藉助別的工具,目前比較經常使用的有如下幾種方案:數據庫
本篇發文咱們主要說下基於Redis的分佈式鎖實戰。編程
實際編寫代碼以前,咱們說下首要條件緩存
編寫ILock接口架構
編寫ILock接口實現併發
LockGetter抽象類dom
從圖示咱們能夠看出,經過LockGetter抽象類進行具體的加鎖成功或則失敗的具體業務走向。這一個思想同窗們要謹記於心。可以熟練應用的話,他會使你在編程之路上走的更加順暢。分佈式
此外,能夠看到,咱們實際加鎖就一行代碼:jedis.set(fieldKey, value, "NX", "EX", seconds);,這個set()方法一共有五個形參:memcached
第一個參數爲key,咱們使用key來當鎖,由於key是惟一的。
第二個參數爲value,咱們傳的是requestId,不少童鞋可能不明白,有key做爲鎖不就夠了嗎,爲何還要用到value?緣由就是咱們在上面講到可靠性時,分佈式鎖要知足第四個條件解鈴還須繫鈴人,經過給value賦值爲requestId,咱們就知道這把鎖是哪一個請求加的了,在解鎖的時候就能夠有依據。requestId可使用UUID.randomUUID().toString()方法生成。
第三個參數爲nxxx,這個參數咱們填的是NX,意思是SET IF NOT EXIST,即當key不存在時,咱們進行set操做;若key已經存在,則不作任何操做;
第四個參數爲expx,這個參數咱們傳的是PX,意思是咱們要給這個key加一個過時的設置,具體時間由第五個參數決定。
第五個參數爲time,與第四個參數相呼應,表明key的過時時間。
總的來講,執行上面的set()方法以後會出現兩種狀況:
使用緩存來實現分佈式鎖優勢:
使用緩存實現分佈式鎖儘管性能好,實現起來較爲方便。但也不是沒有缺點,有時候咱們的程序內部出現異常後可能會發生死鎖,這就須要開發時候注意代碼編寫,後續測試人員測試時候測試案例要儘量覆蓋。
最後,歡迎作Java的工程師朋友們加入Java高級架構進階Qqun:963944895
羣內有技術大咖指點難題,還提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)
比你優秀的對手在學習,你的仇人在磨刀,你的閨蜜在減肥,隔壁老王在練腰, 咱們必須不斷學習,不然咱們將被學習者超越!
趁年輕,使勁拼,給將來的本身一個交代!