国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

2、基于redis實現(xiàn)分布式鎖

這篇具有很好參考價值的文章主要介紹了2、基于redis實現(xiàn)分布式鎖。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

2.1. 基本實現(xiàn)

借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同時有多個客戶端發(fā)送setnx命令,只有一個客戶端可以成功,返回1(true);其他的客戶端返回0(false)。
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

  1. 多個客戶端同時獲取鎖(setnx)
  2. 獲取成功,執(zhí)行業(yè)務邏輯,執(zhí)行完成釋放鎖(del)
  3. 其他客戶端等待重試

改造StockService方法:

 /**
     * redis setnx實現(xiàn)分布式鎖,最基本的哪一種 !??!
     */
    public void deduct() {
        // 加鎖setnx
        Boolean lock = this.redisTemplate.opsForValue().setIfAbsent("lock", "111");
        if (!lock) {
            // 沒有獲取到鎖,進行重試!!
            try {
                Thread.sleep(50);
                this.deduct();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            try {
                // 1. 查詢庫存信息
                String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
                // 2. 判斷庫存是否充足
                if (stockStr != null && stockStr.length() != 0) {
                    Long stock = Long.parseLong(stockStr);
                    if (stock > 0) {
                        redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                    }
                }
            } finally {
                // 解鎖
                this.redisTemplate.delete("lock");
            }
        }
    }

使用 jmeter 進行壓測
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖
查看庫存數(shù)量
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

上述代碼優(yōu)化,不斷重試的過程中一直進行遞歸,最終導致棧的溢出。

解決


    /**
     *  while循環(huán)代替遞歸,解決不斷重試可能導致的棧溢出的問題
     */
    public void deduct() {
        // 加鎖setnx
        while (this.redisTemplate.opsForValue().setIfAbsent("lock1", "1")) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                // 1. 查詢庫存信息
                String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
                // 2. 判斷庫存是否充足
                if (stockStr != null && stockStr.length() != 0) {
                    Long stock = Long.parseLong(stockStr);
                    if (stock > 0) {
                        redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                    }
                }
            } finally {
                // 解鎖
                this.redisTemplate.delete("lock1");
            }
        }
    }

2.2. 防死鎖

問題:setnx剛剛獲取到鎖,當前服務器宕機,導致del釋放鎖無法執(zhí)行,進而導致鎖無法鎖無法釋放(死鎖)
解決:給鎖設置過期時間,自動釋放鎖。

設置過期時間兩種方式:

  • 通過expire設置過期時間(缺乏原子性:如果在setnx和expire之間出現(xiàn)異常,鎖也無法釋放)
  • 使用set指令設置過期時間:set key value ex 3 nx(既達到setnx的效果,又設置了過期時間)

2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

2.3. 防誤刪

持有鎖的線程在鎖的內(nèi)部出現(xiàn)了阻塞,導致他的鎖自動釋放,這時其他線程,線程2來嘗試獲得鎖,就拿到了這把鎖,然后線程2在持有鎖執(zhí)行過程中,線程1反應過來,繼續(xù)執(zhí)行,而線程1執(zhí)行過程中,走到了刪除鎖邏輯,此時就會把本應該屬于線程2的鎖進行刪除,這就是誤刪別人鎖的情況說明

解決: setnx獲取鎖時,設置一個指定的唯一值(例如:uuid);釋放前獲取這個值,判斷是否自己的鎖
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

問題:刪除操作缺乏原子性。
場景:

  1. index1執(zhí)行刪除時,查詢到的lock值確實和uuid相等
  2. index1執(zhí)行刪除前,lock剛好過期時間已到,被redis自動釋放
  3. index2獲取了lock
  4. index1執(zhí)行刪除,此時會把index2的lock刪除

解決方案:沒有一個命令可以同時做到判斷 + 刪除,所有只能通過其他方式實現(xiàn)(LUA腳本

2.4. redis中的lua腳本

2.4.1 redis 并不能保證一組命令的原子性

redis采用單線程架構,可以保證單個命令的原子性,但是無法保證一組命令在高并發(fā)場景下的原子性。

如果redis客戶端通過lua腳本把3個命令一次性發(fā)送給redis服務器,那么這三個指令就不會被其他客戶端指令打斷。Redis 也保證腳本會以原子性的方式執(zhí)行: 當某個腳本正在運行的時候,不會有其他腳本或 Redis 命令被執(zhí)行。 這和使用 MULTI/ EXEC 包圍的事務很類似。

2.4.2 lua介紹

Lua 是一種輕量小巧的腳本語言,用標準C語言編寫并以源代碼形式開放, 其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。

2.4.3. lua基本語法

a = 5               -- 全局變量
local b = 5         -- 局部變量, redis只支持局部變量
a, b = 10, 2*x      -- 等價于       a=10; b=2*x

流程控制:
if( 布爾表達式 1)
then
   --[ 在布爾表達式 1 為 true 時執(zhí)行該語句塊 --]
elseif( 布爾表達式 2)
then
   --[ 在布爾表達式 2 為 true 時執(zhí)行該語句塊 --]
else 
   --[ 如果以上布爾表達式都不為 true 則執(zhí)行該語句塊 --]
end

2.4.4. redis執(zhí)行l(wèi)ua腳本 - EVAL指令

在redis中需要通過eval命令執(zhí)行l(wèi)ua腳本。

格式:

EVAL script numkeys key [key ...] arg [arg ...]
script:lua腳本字符串,這段Lua腳本不需要(也不應該)定義函數(shù)。
numkeys:lua腳本中KEYS數(shù)組的大小
key [key ...]:KEYS數(shù)組中的元素
arg [arg ...]:ARGV數(shù)組中的元素

案例1:基本案例

EVAL "return 10" 0

輸出:(integer) 10


案例2:動態(tài)傳參
EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 5 10 20 30 40 50 60 70 80 90
# 輸出:10 20 60 70

EVAL "if KEYS[1] > ARGV[1] then return 1 else return 0 end" 1 10 20
# 輸出:0

EVAL "if KEYS[1] > ARGV[1] then return 1 else return 0 end" 1 20 10
# 輸出:1

傳入了兩個參數(shù)10和20,KEYS的長度是1,所以KEYS中有一個元素10,剩余的一個20就是ARGV數(shù)組的元素。


案例3:執(zhí)行redis類庫方法
redis.call()中的redis是redis中提供的lua腳本類庫,僅在redis環(huán)境中可以使用該類庫

set aaa 10  -- 設置一個aaa值為10
EVAL "return redis.call('get', 'aaa')" 0
# 通過return把call方法返回給redis客戶端,打?。?10"

注意:**腳本里使用的所有鍵都應該由 KEYS 數(shù)組來傳遞。**但并不是強制性的,代價是這樣寫出的腳本不能被 Redis 集群所兼容


案例4:給redis類庫方法動態(tài)傳參 ```shell EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 bbb 20 ``` 2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖 學到這里基本可以應付redis分布式鎖所需要的腳本知識了。

2.5. 使用lua保證刪除原子性

刪除LUA腳本:

if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end

2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

代碼實現(xiàn) StockService:

    /**
     *  解決鎖的誤刪問題
     */
    public void deduct() {
        String uuid = UUID.randomUUID().toString();
        // 加鎖setnx
        while (this.redisTemplate.opsForValue().setIfAbsent("lock1", uuid, 20,TimeUnit.SECONDS)) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                // 1. 查詢庫存信息
                String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
                // 2. 判斷庫存是否充足
                if (stockStr != null && stockStr.length() != 0) {
                    Long stock = Long.parseLong(stockStr);
                    if (stock > 0) {
                        redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                    }
                }
            } finally {
                // 判斷鎖是不是被當前線程所持有,是的話,則刪除鎖
                /*if(uuid.equals(redisTemplate.opsForValue().get("lock1"))) {
                    // 解鎖
                    this.redisTemplate.delete("lock1");
                }*/

                // 通過lua腳本來釋放鎖
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
                        "then " +
                        "   return redis.call('del', KEYS[1]) " +
                        "else " +
                        "   return 0 " +
                        "end";
                this.redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Arrays.asList("lock"), uuid);
            }
        }
    }

2.6. 可重入鎖

由于上述加鎖命令使用了 SETNX ,一旦鍵存在就無法再設置成功,這就導致后續(xù)同一線程內(nèi)繼續(xù)加鎖,將會加鎖失敗。

用一段 Java 代碼解釋可重入:

public synchronized void a() {
    b();
}

public synchronized void b() {
    // pass
}

假設 X 線程在 a 方法獲取鎖之后,繼續(xù)執(zhí)行 b 方法,如果此時不可重入,線程就必須等待鎖釋放,再次爭搶鎖。
鎖明明是被 X 線程擁有,卻還需要等待自己釋放鎖,然后再去搶鎖,這看起來就很奇怪,我釋放我自己~

可重入性就可以解決這個尷尬的問題,當線程擁有鎖之后,往后再遇到加鎖方法,直接將加鎖次數(shù)加 1,然后再執(zhí)行方法輯。退出加鎖方法之后,加鎖次數(shù)再減 1,當加鎖次數(shù)為 0 時,鎖才被真正的釋放。

2.6.1. 加鎖腳本

參照 ReentrantLock 中的非公平可重入鎖實現(xiàn)分布式可重入鎖: hash + lua腳本

加鎖:
1、判斷鎖是否存在(exists), 不存在則直接獲取鎖,hset key filed value
2、如果鎖存在則判斷是否是自己的鎖(hexists)
如果是自己的鎖則重入:hincrby key field increment
如果不是自己的鎖,則重試

// 當鎖不存在 或者 持有鎖的線程是當前線程時
if (redis.call('exists', KEYS[1]) == 0 or redis.call('hexists', KEYS[1], ARGV[1]) == 1) 
then
    redis.call('hincrby', KEYS[1], ARGV[1], 1);
    redis.call('expire', KEYS[1], ARGV[2]);
    return 1;
else
	return 0;
end

2.6.2. 解鎖腳本

解鎖
1、判斷自己的鎖是否存在,不存在則返回nil
2、如果自己的鎖存在,則減1(hincrby -1 ),判斷減1后的值是否為0
為0則del key并且返回1,表示解鎖成功
不為0,則返回0表示解鎖失敗

if(redis.call('hexists', KEYS[1], ARGV[1]) == 0) then 
    return nil; 
elseif(redis.call('hincrby', KEYS[1], ARGV[1], -1) > 0) then 
    return 0; 
else 
    redis.call('del', KEYS[1]); 
    return 1; 
end;

2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

2.6.3. 代碼實現(xiàn)

由于加解鎖代碼量相對較多,這里可以封裝成一個工具類:
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

// 生成鎖的工廠
@Component
public class DistributedLockClient {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private String uuid;

    public DistributedLockClient() {
        this.uuid = UUID.randomUUID().toString();
    }

    public DistributedRedisLock getRedisLock(String lockName){
        return new DistributedRedisLock(redisTemplate, lockName, uuid);
    }
}

// 鎖具體實現(xiàn)
public class DistributedRedisLock implements Lock {

    private StringRedisTemplate redisTemplate;

    private String lockName;

    private String uuid;

    private long expire = 30;

    public DistributedRedisLock(StringRedisTemplate redisTemplate, String lockName, String uuid) {
        this.redisTemplate = redisTemplate;
        this.lockName = lockName;
        this.uuid = uuid;
    }

    @Override
    public void lock() {
        this.tryLock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        try {
            return this.tryLock(-1L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit timeUnit) throws InterruptedException {
        if (time != -1){
            this.expire = timeUnit.toSeconds(time);
        }
        String script = "if (redis.call('exists', KEYS[1]) == 0 or redis.call('hexists', KEYS[1], ARGV[1]) == 1) " +
                "then" +
                "    redis.call('hincrby', KEYS[1], ARGV[1], 1);" +
                "    redis.call('expire', KEYS[1], ARGV[2]);" +
                "    return 1;" +
                "else" +
                "    return 0;" +
                "end";
        while (!this.redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Arrays.asList(lockName), getId(), String.valueOf(expire))) {
            Thread.sleep(50);
        }
        return true;
    }

    @Override
    public void unlock() {
        String script = "if redis.call('hexists', KEYS[1], ARGV[1]) == 0 " +
                "then " +
                "   return nil " +
                "elseif redis.call('hincrby', KEYS[1], ARGV[1], -1) == 0 " +
                "then " +
                "   return redis.call('del', KEYS[1]) " +
                "else " +
                "   return 0 " +
                "end";
        Long flag = this.redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(lockName), getId());
        if (flag == null) {
            throw new IllegalMonitorStateException("this lock doesn't belong to you!");
        }
    }

    @Override
    public Condition newCondition() {
        return null;
    }


    /**
     * 給線程拼接唯一標識
     *
     * @return
     */
    String getId() {
        return uuid + ":" + Thread.currentThread().getId();
    }
}

2.6.4. 使用及測試

在業(yè)務代碼中進行使用:

    public void deduct() {
        DistributedRedisLock lock = distributedLockClient.getRedisLock("lock");
        try {
            lock.lock();
            // 1. 查詢庫存信息
            String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
            // 2. 判斷庫存是否充足
            if (stockStr != null && stockStr.length() != 0) {
                Long stock = Long.parseLong(stockStr);
                if (stock > 0) {
                    redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                }
            }
        } finally {
            lock.unlock();
        }
    }

測試可重入性:

  public void deduct() {
        DistributedRedisLock lock = distributedLockClient.getRedisLock("lock");
        try {
            lock.lock();
            // 1. 查詢庫存信息
            String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
            // 2. 判斷庫存是否充足
            if (stockStr != null && stockStr.length() != 0) {
                Long stock = Long.parseLong(stockStr);
                if (stock > 0) {
                    redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                }
            }
            this.test();
        } finally {
            lock.unlock();
        }
    }

    private void test() {
        DistributedRedisLock lock = distributedLockClient.getRedisLock("lock");
        lock.lock();
        System.out.println("獲取到可重入鎖");
        System.out.println("執(zhí)行其他業(yè)務代碼......");
        lock.unlock();
    }

2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖

2.7. 自動續(xù)期

自動續(xù)期: 定時任務 (Time 定時器 ) + Lua腳本

判斷自己的鎖是否存在(hexists),如果存在則重置過期時間

if(redis.call('hexists', KEYS[1], ARGV[1]) == 1) then 
    redis.call('expire', KEYS[1], ARGV[2]); 
    return 1; 
else 
    return 0; 
end

DistributedRedisLock 實現(xiàn)

public class DistributedRedisLock implements Lock {

    private StringRedisTemplate redisTemplate;

    private String lockName;

    private String uuid;

    private long expire = 30;

    public DistributedRedisLock(StringRedisTemplate redisTemplate, String lockName, String uuid) {
        this.redisTemplate = redisTemplate;
        this.lockName = lockName;
        this.uuid = uuid + ":" + Thread.currentThread().getId();
    }

    @Override
    public void lock() {
        this.tryLock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        try {
            return this.tryLock(-1L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit timeUnit) throws InterruptedException {
        if (time != -1) {
            this.expire = timeUnit.toSeconds(time);
        }
        String script = "if (redis.call('exists', KEYS[1]) == 0 or redis.call('hexists', KEYS[1], ARGV[1]) == 1) " +
                "then" +
                "    redis.call('hincrby', KEYS[1], ARGV[1], 1);" +
                "    redis.call('expire', KEYS[1], ARGV[2]);" +
                "    return 1;" +
                "else" +
                "    return 0;" +
                "end";
        while (!this.redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Arrays.asList(lockName), uuid, String.valueOf(expire))) {
            Thread.sleep(50);
        }
        // 加鎖成功返回之前,開啟自動續(xù)期
        this.renewExpire();
        return true;
    }

    @Override
    public void unlock() {
        String script = "if redis.call('hexists', KEYS[1], ARGV[1]) == 0 " +
                "then " +
                "   return nil " +
                "elseif redis.call('hincrby', KEYS[1], ARGV[1], -1) == 0 " +
                "then " +
                "   return redis.call('del', KEYS[1]) " +
                "else " +
                "   return 0 " +
                "end";
        Long flag = this.redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(lockName), uuid);
        if (flag == null) {
            throw new IllegalMonitorStateException("this lock doesn't belong to you!");
        }
    }

    @Override
    public Condition newCondition() {
        return null;
    }



    private void renewExpire() {
        String script = "if redis.call('hexists', KEYS[1], ARGV[1]) == 1 " +
                "then " +
                "   return redis.call('expire', KEYS[1], ARGV[2]) " +
                "else " +
                "   return 0 " +
                "end";
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Arrays.asList(lockName), uuid, String.valueOf(expire))) {
                    // 當續(xù)期成功了,重新開啟一個定時任務
                    renewExpire();
                }
            }
        }, this.expire * 1000 / 3);
    }
}

測試 ,改造stockService

    public void deduct() {
        DistributedRedisLock lock = distributedLockClient.getRedisLock("lock");
        try {
            lock.lock();
            // 1. 查詢庫存信息
            try {
                Thread.sleep(300000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");
            // 2. 判斷庫存是否充足
            if (stockStr != null && stockStr.length() != 0) {
                Long stock = Long.parseLong(stockStr);
                if (stock > 0) {
                    redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));
                }
            }
            this.test();
        } finally {
            lock.unlock();
        }
    }

可以看到加鎖 10s后,鎖過期時間重置為30s
2、基于redis實現(xiàn)分布式鎖,分布式鎖,分布式鎖
【注意】
鎖的自動續(xù)期和鎖的過期釋放是不是沖突的?

鎖的自動續(xù)期和鎖的過期釋放并不沖突,它們是為了解決不同場景下的問題而設計的。

鎖的自動續(xù)期:這個機制主要用于處理持有鎖的客戶端在執(zhí)行任務時可能因為某些原因導致任務執(zhí)行時間超過預設值。通過自動續(xù)期,可以確保在客戶端仍在執(zhí)行任務時,其他客戶端無法獲取到該鎖。這樣就避免了多個客戶端同時操作共享資源造成數(shù)據(jù)混亂或者錯誤。

鎖的過期釋放:這個機制主要用于處理持有鎖的客戶端異常退出(比如崩潰、斷電等)導致無法正常釋放鎖。通過設置一個合理的過期時間,在發(fā)生異常情況后一段時間內(nèi)其他客戶端依然可以獲取到該鎖,并且進行相應操作。

總之,兩者都是為了確保分布式系統(tǒng)中對共享資源訪問互斥性以及容錯性而設計,并不存在沖突關系。文章來源地址http://www.zghlxwxcb.cn/news/detail-617374.html

到了這里,關于2、基于redis實現(xiàn)分布式鎖的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 一種基于springboot、redis的分布式任務引擎的實現(xiàn)(一)

    ?總體思路是,主節(jié)點接收到任務請求,將根據(jù)任務情況拆分成多個任務塊,將任務塊標識的主鍵放入redis。發(fā)送redis消息,等待其他節(jié)點運行完畢,結束處理。接收到信息的節(jié)點注冊本節(jié)點信息到redis、開啟多線程、獲取任務塊、執(zhí)行任務、結束處理。 1、主節(jié)點接收任務請求

    2024年02月11日
    瀏覽(20)
  • 基于 Redis + Lua 腳本實現(xiàn)分布式鎖,確保操作的原子性

    基于 Redis + Lua 腳本實現(xiàn)分布式鎖,確保操作的原子性

    1.加鎖的Lua腳本: lock.lua 2.解鎖的Lua腳本: unLock.lua 3.將資源文件放在資源文件夾下 4.Java中調用lua腳本 1)獲取文件方式 2)lua字符串方式 5.jedis調用Lua腳本實現(xiàn)分布式重試鎖 1)引入jedis依賴 2)jedis調用lua

    2024年02月07日
    瀏覽(28)
  • Zookeeper 和 Redis 哪種更好? 為什么使用分布式鎖? 1. 利用 Redis 提供的 第二種,基于 ZK 實現(xiàn)分布式鎖的落地方案 對于 redis 的分布式鎖而言,它有以下缺點:

    關于這個問題,我們 可以從 3 個方面來說: 為什么使用分布式鎖? 使用分布式鎖的目的,是為了保證同一時間只有一個 JVM 進程可以對共享資源進行操作。 根據(jù)鎖的用途可以細分為以下兩類: 允許多個客戶端操作共享資源,我們稱為共享鎖 這種鎖的一般是對共享資源具有

    2024年01月16日
    瀏覽(23)
  • Redis實戰(zhàn)案例14-分布式鎖的基本原理、不同實現(xiàn)方法對比以及基于Redis進行實現(xiàn)思路

    Redis實戰(zhàn)案例14-分布式鎖的基本原理、不同實現(xiàn)方法對比以及基于Redis進行實現(xiàn)思路

    基于數(shù)據(jù)庫的分布式鎖:這種方式使用數(shù)據(jù)庫的特性來實現(xiàn)分布式鎖。具體流程如下: 獲取鎖:當一個節(jié)點需要獲得鎖時,它嘗試在數(shù)據(jù)庫中插入一個特定的唯一鍵值(如唯一約束的主鍵),如果插入成功,則表示獲得了鎖。 釋放鎖:當節(jié)點完成任務后,通過刪除該唯一鍵

    2024年02月13日
    瀏覽(49)
  • Asynq: 基于Redis實現(xiàn)的Go生態(tài)分布式任務隊列和異步處理庫

    Asynq: 基于Redis實現(xiàn)的Go生態(tài)分布式任務隊列和異步處理庫

    Asynq [1] 是一個Go實現(xiàn)的分布式任務隊列和異步處理庫,基于redis,類似Ruby的 sidekiq [2] 和Python的 celery [3] 。Go生態(tài)類似的還有 machinery [4] 和goworker 同時提供一個WebUI asynqmon [5] ,可以源碼形式安裝或使用Docker image, 還可以和Prometheus集成 docker run --rm --name asynqmon -p 8080:8080 hibiken/as

    2024年02月14日
    瀏覽(22)
  • 在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等

    在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等

    在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等。下面是兩種常見的實現(xiàn)方式: 使用Redis實現(xiàn)分布式鎖: 使用自定義注解實現(xiàn)本地鎖: 以上是兩種常見的在Spring中實現(xiàn)分布式鎖的方式。第一種方式使用Redis作為分布式鎖的存儲介質,通過

    2024年03月17日
    瀏覽(24)
  • 基于Redis的分布式限流詳解

    基于Redis的分布式限流詳解

    Redis除了能用作緩存外,還有很多其他用途,比如分布式鎖,分布式限流,分布式唯一主鍵等,本文將和大家分享下基于Redis分布式限流的各種實現(xiàn)方案。 用最簡單的話來說: 外部請求是不可控的,而我們系統(tǒng)的負載是有限的,如果沒有限流機制,一旦外部請求超過系統(tǒng)承載

    2024年02月04日
    瀏覽(28)
  • 分布式鎖實現(xiàn)(mysql,以及redis)以及分布式的概念

    分布式鎖實現(xiàn)(mysql,以及redis)以及分布式的概念

    我旁邊的一位老哥跟我說,你知道分布式是是用來干什么的嘛?一句話給我干懵了,我能隱含知道,大概是用來做分壓處理的,并增加系統(tǒng)穩(wěn)定性的。但是具體如何,我卻道不出個1,2,3?,F(xiàn)在就將這些做一個詳細的總結。至少以后碰到面試官可以說上個123。 那么就正式進入

    2024年01月21日
    瀏覽(37)
  • 基于Redis的分布式鎖到底安全嗎(下)

    原文鏈接跳轉 - 張鐵蕾 今天,我們就繼續(xù)探討這個話題的后半部分。本文中,我們將從antirez反駁Martin Kleppmann的觀點開始講起,然后會涉及到Hacker News上出現(xiàn)的一些討論內(nèi)容,接下來我們還會討論到基于Zookeeper和Chubby的分布式鎖是怎樣的,并和Redlock進行一些對比。最后,我們

    2024年04月10日
    瀏覽(26)
  • Redis——》實現(xiàn)分布式鎖

    推薦鏈接: ????總結——》【Java】 ????總結——》【Mysql】 ????總結——》【Redis】 ????總結——》【Kafka】 ????總結——》【Spring】 ????總結——》【SpringBoot】 ????總結——》【MyBatis、MyBatis-Plus】 ????總結——》【Linux】 ????總結——》【MongoDB】 ???

    2024年02月10日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包