Java實現Redis分佈鎖
1、背景:
在多執行緒環境下,通常會使用鎖來保證有且只有一個執行緒來操作共享資源。比如:
object obj = new object();lock (obj)
{
//操作共享資源
}
利用作業系統提供的鎖機制,可以確保多執行緒或多程序下的併發唯一操作。但如果在多機環境下就不能滿足了,當A,B兩臺機器同時操作C機器的共享資源時,就需要第三方的鎖機制來保證在分散式環境下的資源協調,也稱分散式鎖。
在分散式環境下(多節點主機)加鎖處理場景,如:秒殺、全域性遞增ID等等,需要對資源(變數)同步互斥。大部分的解決方案是基於DB實現的,Redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶端對Redis的連線並不存在競爭關係。由於Redis是單執行緒模型,命令操作原子性,所以利用這個特性可以很容易的實現分散式鎖。
2、Redis有三個最基本屬性來保證分散式鎖的有效實現:
安全性: 互斥,在任何時候,只有一個客戶端能持有鎖。
活躍性A:沒有死鎖,即使客戶端在持有鎖的時候崩潰,最後也會有其他客戶端能獲得鎖,超時機制。
活躍性B:故障容忍,只有大多數Redis節點時存活的,客戶端仍可以獲得鎖和釋放鎖。
使用Redis實現分散式鎖,有兩個重要函式需要介紹
1)SETNX命令(SET if Not eXists)
語法:
SETNX key value
功能:
當且僅當 key 不存在,將 key 的值設為 value ,並返回1;若給定的 key 已經存在,則 SETNX 不做任何動作,並返回0。
2)GETSET命令
語法:
GETSET key value
功能:
將給定 key 的值設為 value ,並返回 key 的舊值 (old value),當 key 存在但不是字串型別時,返回一個錯誤,當key不存在時,返回nil。
3、程式碼:
package ct.tool; import redis.clients.jedis.Jedis; public class RedisDisLock { private static final long expired = 1000;//1秒超時 //上鎖 public static boolean acquireLock(Jedis jedis,String lock) { // 1. 通過SETNX試圖獲取一個lock boolean success = false; long value = System.currentTimeMillis() + expired + 1; long acquired = jedis.setnx(lock, String.valueOf(value)); jedis.expire(lock, 1);//設定1秒超時 //SETNX成功,則成功獲取一個鎖 if (acquired == 1) success = true; //SETNX失敗,說明鎖被其他客戶端保持,檢查其是否已經超時 /*else { long oldValue = Long.valueOf(jedis.get(lock)); if (oldValue < System.currentTimeMillis()) {//超時 //獲取上一個鎖到期時間,並設定現在的鎖到期時間, //只有一個執行緒才能獲取上一個線上的設定時間,因為jedis.getSet是同步的 String getValue = jedis.getSet(lock, String.valueOf(value)); if (getValue !=null) { if (Long.valueOf(getValue) == oldValue) success = true; else success = false;// 已被其他程序捷足先登了 } }else //未超時,則直接返回失敗 success = false; } */ return success; } //釋放鎖 public static void releaseLock(Jedis jedis,String lock) { //long current = System.currentTimeMillis(); // 避免刪除非自己獲取得到的鎖 //if (current < Long.valueOf(jedis.get(lock))) jedis.del(lock); } }
程式碼應用中,要共享的程式碼段前加:
//枷鎖
boolean lockFlag=true;
while(lockFlag){//迴圈等待拿鎖
if (RedisDisLock.acquireLock(jd,"o2o")) lockFlag=false;
}
業務處理後,釋放:
RedisDisLock.releaseLock(jd, "o2o");
相關推薦
Java實現Redis分佈鎖
1、背景: 在多執行緒環境下,通常會使用鎖來保證有且只有一個執行緒來操作共享資源。比如: object obj = new object(); lock (obj) { //操作共享資源 }利用作業系統提供的鎖機制,可以確保多執行緒或多程序下的併發唯一操作。但如果在多
Java實現Redis分散式鎖
1、背景: 在多執行緒環境下,通常會使用鎖來保證有且只有一個執行緒來操作共享資源。比如: object obj = new object();lock (obj) { //操作共享資源 } 利用作業系統提供的鎖機制,可以確保多執行緒或多程序下的併發唯一操作。但如果在多機
Java 正確實現 redis 分散式鎖
Java 正確實現 redis 分散式鎖 Java 正確實現 redis 分散式鎖 1 源起 2 我想要的效果 3 擼起袖子開幹 3.1 匯入 jedis 依賴
說說在JAVA中使用Redis,以及Redis分佈鎖
只上程式碼和說明,其他的不講了,權當做個筆記。 該程式碼使用了1年多,在高併發的情況下並無問題,所以分享給大家。 package util; import java.io.UnsupportedEncodingException; import java.net.So
註解形式實現,Redis分散式鎖
Redis工具類參考我的博文:https://blog.csdn.net/weixin_38399962/article/details/82753763 一個註解就可以實現分散式鎖?這麼神奇麼? 首先定義註解: /** * Description:分散式Redis鎖 * User:
如何實現一個分佈鎖?
基本概念 為何需要分散式鎖? 傳統環境中的情況: 在程式開發過程中不得不考慮的就是併發問題。在java中對於同一個jvm而言,jdk已經提供了lock和同步等。但是在分散式情況下,往往存在多個程序對一些資源產生競爭關係,而這些程序往往在不同的機器上,這個時候jdk中提供
Redisson實現Redis分散式鎖的N種姿勢
前幾天發的一篇文章《Redlock:Redis分散式鎖最牛逼的實現》,引起了一些同學的討論,也有一些同學提出了一些疑問,這是好事兒。本文在講解如何使用Redisson實現Redis普通分散式鎖,以及Redlock演算法分散式鎖的幾種方式的同時,也附帶解答這些同學的一些疑問。 Redis幾種架構 Redis
用java實現一個行鎖(RowLock)
java 版本的資料庫行鎖,使用wait/notify實現,當然可以使用別的方式如Lock下的await/signal 需求使用java寫一個類,這個類有一個lock(String identifie
基於官方推薦的Redisson實現Redis分散式鎖
RedLock 簡介 在不同程序需要互斥地訪問共享資源時,分散式鎖是一種非常有用的技術手段。實現高效的分散式鎖有三個屬性需要考慮: 安全屬性:互斥,不管什麼時候,只有一個客戶端持有鎖 效率屬性A:不會死鎖 效率屬性B:容錯,只要大多數redis節點能夠正常工作,客戶端端都能獲取和
PHP實現Redis單據鎖,防止併發重複寫入
一、寫在前面: 在整個供應鏈系統中,會有很多種單據(採購單、入庫單、到貨單、運單等等),在涉及寫單據資料的介面時(增刪改操作),即使前端做了相關限制,還是有可能因為網路或異常操作產生併發重複呼叫的情況,導致對相同單據做相同的處理; 為了防止這種情況對系統造成
python實現redis分散式鎖
#!/usr/bin/env python # coding=utf-8 import time import redis class RedisLock(object): def __i
java實現Redis工具類 RedisUtil.java
package shop.javaweb.utils; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; imp
Java實現redis事務
1. 正常執行的事務 @Test public void test() { Jedis jedis = new Jedis("localhost");
基於AOP實現redis分散式鎖
如果你的系統是分散式叢集部署的,那麼傳統的synchorinzed或者jdk1.5提供的Lock都是依賴本地的jvm虛擬機器提供鎖服務,分散式服務中多jvm是無法同享鎖資訊的,故無法提供鎖。 分散式場景中資料一致性問題一直是一個比較重要的話題。分散式的CAP理論告訴我們任何一
java實現redis的哨兵模式的呼叫
1、安裝redis 叢集,1主1從 也可以是多主多從 redis 詳細今後會在以後的文章中寫出 配置redis-master 的配置檔案 redis.conf 配置程式碼 port 6379 daemonize yes #protected-mode
【隨筆】Java 基於Redis分散式鎖
定義介面 public interface IDistributedLock { boolean tryLock(String var1, Object var2); boolean tryLock(String var1, Object var2, i
Java實現Redis的雜湊(Hash)命令
本編文章知識簡單的實現了redis 的增刪改查,指令不是很全還請大家見諒 package com.huadian.Hash; import com.huadian.redisUntil.JedisPoolUntil; import org.junit.After; i
java中redis分散式鎖的工具類
package com.qlchat.redis.cache; import java.util.*; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
JAVA實現redis超時失效key 的監聽觸發
過期事件通過Redis的訂閱與釋出功能(pub/sub)來進行分發。 而對超時的監聽呢,並不需要自己釋出,只有修改配置檔案redis.conf中的:notify-keyspace-events Ex,
Java實現Redis的集合(set)命令
下面測試redis的集合set的型別,註釋裡面的程式碼是linux中redis命令 package com.huadian.set; import com.huadian.redisUntil.JedisPoolUntil; import org.junit.Befo