最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版)

 更新時(shí)間:2021年05月12日 10:44:30   作者:總有人想害朕  
這篇文章主要介紹了基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

1、前言

在Java中,我們通過鎖來避免由于競爭而造成的數(shù)據(jù)不一致問題。通常我們使用synchronized 、Lock來實(shí)現(xiàn)。但是Java中的鎖只能保證在同一個(gè)JVM進(jìn)程內(nèi)中可用,在跨JVM進(jìn)程,例如分布式系統(tǒng)上則不可靠了。

2、分布式鎖

分布式鎖,是一種思想,它的實(shí)現(xiàn)方式有很多,如基于數(shù)據(jù)庫實(shí)現(xiàn)、基于緩存(Redis等)實(shí)現(xiàn)、基于Zookeeper實(shí)現(xiàn)等等。為了確保分布式鎖可用,我們至少要確保鎖的實(shí)現(xiàn)同時(shí)滿足以下四個(gè)條件

  • 互斥性:在任意時(shí)刻,只有一個(gè)客戶端能持有鎖。
  • 不會發(fā)生死鎖:即使客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證后續(xù)其他客戶端能加鎖。
  • 具有容錯(cuò)性:只要大部分的Redis節(jié)點(diǎn)正常運(yùn)行,客戶端就可以加鎖和解鎖。
  • 解鈴還須系鈴人:加鎖和解鎖必須是同一個(gè)客戶端,客戶端自己不能把別人加的鎖給解了。

 3、基于Redis實(shí)現(xiàn)分布式鎖

以下代碼實(shí)現(xiàn)了基于redis中間件的分布式鎖。加鎖的過程中為了保障setnx(設(shè)置KEY)和expire(設(shè)置超時(shí)時(shí)間)盡可能在一個(gè)事務(wù)中,使用到了lua腳本的方式,將需要完成的指令一并提交到redis中;

3.1、RedisConfig.java

package com.demo.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // key采用String的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        // value序列化方式采用jackson
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

}

3.2、RedisLockController.java

package com.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;

@RestController
@RequestMapping("/redis")
public class RedisLockController {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @RequestMapping(value = "/lock/{key}/{uid}/{expire}")
    public Long lock(@PathVariable("key") String key, @PathVariable("uid") String uid, @PathVariable("expire") Integer expire) {
        Long result = null;
        try {
            //調(diào)用lua腳本并執(zhí)行
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setResultType(Long.class);//返回類型是Long
            //lua文件存放在resources目錄下的redis文件夾內(nèi)
            redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("redis/redis_lock.lua")));
            result = redisTemplate.execute(redisScript, Arrays.asList(key), uid, expire);
            System.out.println("lock==" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @RequestMapping(value = "/unlock/{key}/{uid}")
    public Long unlock(@PathVariable("key") String key, @PathVariable("uid") String uid) {
        Long result = null;
        try {
            //調(diào)用lua腳本并執(zhí)行
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setResultType(Long.class);//返回類型是Long
            //lua文件存放在resources目錄下的redis文件夾內(nèi)
            redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("redis/redis_unlock.lua")));
            result = redisTemplate.execute(redisScript, Arrays.asList(key), uid);
            System.out.println("unlock==" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}

3.3、redis_lock.lua

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

3.4、redis_unlock.lua

if redis.call("exists",KEYS[1]) == 0 then
    return 1
end

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

4、測試效果

key123為key,thread12345為value標(biāo)識鎖的主人,300為該鎖的超時(shí)時(shí)間

加鎖:鎖主人為thread12345
http://127.0.0.1:8080/redis/lock/key123/thread12345/300

解鎖:解鎖人為thread123456
http://127.0.0.1:8080/redis/unlock/key123/thread123456

解鎖:解鎖人為thread12345
http://127.0.0.1:8080/redis/unlock/key123/thread12345

4.1、加鎖,其他人解鎖

在這里插入圖片描述
在這里插入圖片描述

thread12345加的鎖,thread123456是解不了的,只有等thread12345自己解鎖或者鎖的超時(shí)時(shí)間過期

4.2、加鎖,自己解鎖

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

thread12345加的鎖,thread12345自己隨時(shí)可以解鎖,也可以等鎖的超時(shí)時(shí)間過期

5、總結(jié)

  •  使用Redis鎖,會有業(yè)務(wù)未執(zhí)行完,鎖過期的問題,也就是鎖不具有可重入性的特點(diǎn)。
  • 使用Redis鎖,在嘗試獲取鎖的時(shí)候,是非阻塞的,不滿足在一定期限內(nèi)不斷嘗試獲取鎖的場景。
  • 以上兩點(diǎn),都可以采用Redisson鎖解決。

到此這篇關(guān)于基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版)的文章就介紹到這了,更多相關(guān)Redis實(shí)現(xiàn)分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格詳解

    這篇文章主要給大家介紹了關(guān)于redis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • Redis實(shí)現(xiàn)接口防抖的示例代碼

    Redis實(shí)現(xiàn)接口防抖的示例代碼

    本文介紹了一種通過AOP、自定義注解和Redis實(shí)現(xiàn)的接口防抖技術(shù),這種方法能有效避免因網(wǎng)絡(luò)波動等原因短時(shí)間內(nèi)發(fā)送多個(gè)請求導(dǎo)致的數(shù)據(jù)重復(fù)添加問題,感興趣的可以了解一下
    2024-10-10
  • 生產(chǎn)redisson延時(shí)隊(duì)列不消費(fèi)問題排查解決

    生產(chǎn)redisson延時(shí)隊(duì)列不消費(fèi)問題排查解決

    這篇文章主要為大家介紹了生產(chǎn)redisson延時(shí)隊(duì)列不消費(fèi)問題排查解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Redis三種集群模式詳解

    Redis三種集群模式詳解

    redis有三種集群模式,其中主從是最常見的模式,今天通過本文給大家分享Redis三種集群模式介紹,感興趣的朋友一起看看吧
    2021-10-10
  • 將音頻文件轉(zhuǎn)二進(jìn)制分包存儲到Redis的實(shí)現(xiàn)方法(奇淫技巧操作)

    將音頻文件轉(zhuǎn)二進(jìn)制分包存儲到Redis的實(shí)現(xiàn)方法(奇淫技巧操作)

    這篇文章主要介紹了將音頻文件轉(zhuǎn)二進(jìn)制分包存儲到Redis的實(shí)現(xiàn)方法(奇淫技巧操作),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 命令行清除Redis緩存的實(shí)現(xiàn)

    命令行清除Redis緩存的實(shí)現(xiàn)

    本文主要介紹了命令行清除Redis緩存的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 使用Redis實(shí)現(xiàn)實(shí)時(shí)排行榜的示例

    使用Redis實(shí)現(xiàn)實(shí)時(shí)排行榜的示例

    為了實(shí)現(xiàn)一個(gè)實(shí)時(shí)排行榜系統(tǒng),我們可以使用Redis的有序集合,本文主要介紹了使用Redis實(shí)現(xiàn)實(shí)時(shí)排行榜的示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • 詳解Redis數(shù)據(jù)類型實(shí)現(xiàn)原理

    詳解Redis數(shù)據(jù)類型實(shí)現(xiàn)原理

    這篇文章主要介紹了Redis數(shù)據(jù)類型實(shí)現(xiàn)原理,在工作中或?qū)W習(xí)中有需要的小伙伴可以參考一下這篇文章
    2021-08-08
  • redis中紅鎖的使用小結(jié)

    redis中紅鎖的使用小結(jié)

    RedLock 是 Redis 官方提出的一種用于在分布式環(huán)境下實(shí)現(xiàn)強(qiáng)一致性分布式鎖的算法,本文就來詳細(xì)的介紹一下redis中紅鎖的使用小結(jié),感興趣的可以了解一下
    2025-10-10
  • Redis實(shí)現(xiàn)Session持久化的示例代碼

    Redis實(shí)現(xiàn)Session持久化的示例代碼

    Redis是內(nèi)存數(shù)據(jù)庫,數(shù)據(jù)都是存儲在內(nèi)存中,為了避免服務(wù)器斷電等原因?qū)е翿edis進(jìn)程異常退出后數(shù)據(jù)的永久丟失,本文主要介紹了Redis實(shí)現(xiàn)Session持久化的示例代碼,感興趣的可以了解一下
    2023-09-09

最新評論

佛冈县| 平顶山市| 宁河县| 东乡县| 五莲县| 临漳县| 绵竹市| 上饶县| 江达县| 峨山| 墨竹工卡县| 铜陵市| 水富县| 黄石市| 邓州市| 钟山县| 临沧市| 绵阳市| 山东省| 衡山县| 郎溪县| 汝南县| 沂源县| 彭山县| 綦江县| 郧西县| 安陆市| 沈丘县| 鄂托克前旗| 道孚县| 新密市| 博野县| 会泽县| 来凤县| 弥勒县| 石狮市| 台中市| 崇州市| 博乐市| 手游| 富民县|