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

聊聊使用RedisTemplat實(shí)現(xiàn)簡單的分布式鎖的問題

 更新時(shí)間:2021年11月19日 14:44:56   作者:郝瑞杰  
這篇文章主要介紹了使用RedisTemplat實(shí)現(xiàn)簡單的分布式鎖問題,文中給大家介紹在SpringBootTest中編寫測試模塊的詳細(xì)代碼,需要的朋友可以參考下

不使用redisson框架實(shí)現(xiàn)Redis分布式鎖

準(zhǔn)備工作:

導(dǎo)入依賴

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

編寫RedisConfig類

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String , Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //String類型 key序列器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //String類型 value序列器
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        //Hash類型 key序列器
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //Hash類型 value序列器
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        //將連接工廠注入
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
 }

1.在SpringBootTest中編寫測試模塊

1.1:使用占位符加鎖:

占位符加鎖問題:出現(xiàn)異常時(shí)無法釋放鎖,導(dǎo)致后繼進(jìn)入的線程成為死鎖

@SpringBootTest
class ApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
	@Test
	public void lodsTest01(){
		ValueOperations valueOperations = redisTemplate.opsForValue();
	        //創(chuàng)建一個(gè)占位符,如果key不存在才可以設(shè)置成功
	        Boolean isLock = valueOperations.setIfAbsent("k1", "v1");
	        //如果占位成功,進(jìn)行正常操作
	        if (isLock){
	        	//設(shè)置一個(gè)name存到redis
	            valueOperations.set("name","xxxx");
	            //從redis取出name
	            String name = (String) valueOperations.get("name");
	            System.out.println("name = " + name);
	            //手動(dòng)制造異常
	            Integer.parseInt("xxxx");
	            //操作結(jié)束刪除鎖
	            redisTemplate.delete("k1");
	        }else{
	            System.out.println("有線程在用,請稍后在試");
	        }
	}
}

測試
第一個(gè)線程出現(xiàn)異常無法釋放鎖:


之后所有線程都無法訪問:

解決方案為鎖加一個(gè)有效時(shí)間。

1.2:使用占位符設(shè)置有效時(shí)間解決死鎖問題:

占位符設(shè)置有效時(shí)間問題即使某線程出現(xiàn)異常,但占位符過了有效時(shí)間,鎖就會釋放。但是在大量線程同時(shí)訪問時(shí),如果線程1被外界因素影響(網(wǎng)絡(luò)波動(dòng),服務(wù)器出問題等等),線程1的業(yè)務(wù)還沒完成,但鎖的有效時(shí)間到了的話,下一個(gè)線程就會進(jìn)來,就會出現(xiàn)線程不安全的情況,出現(xiàn)線程互相刪鎖的情況。

	@Test
    public void testLock02()  {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //如果key不存在才可以設(shè)置成功,設(shè)置一個(gè)有效時(shí)間防止線程異常出現(xiàn)死鎖
        Boolean isLock = valueOperations.setIfAbsent("k1", "v1",5, TimeUnit.SECONDS);
        //如果占位成功,進(jìn)行正常操作
        if (isLock){
        	//設(shè)置一個(gè)name存到redis
            valueOperations.set("name","xxxx");
            //從redis取出name
            String str = (String) valueOperations.get("name");
            System.out.println("name = " + str);
            //制造異常
            Integer.parseInt("xxxx");
            //操作結(jié)束刪除鎖
            redisTemplate.delete("k1");
        }else{
            System.out.println("有線程在用,請稍后在試");
        }
    }

解決方案: 使用lua腳本,給每個(gè)鎖的key對應(yīng)的value設(shè)置一個(gè)隨機(jī)數(shù)

1.3:使用lua腳本解決線程不安全問題:

lua腳本可以寫在Redis服務(wù)器上:
優(yōu)點(diǎn): 在服務(wù)器上運(yùn)行速度快

缺點(diǎn): 修改代碼時(shí)比較麻煩

lua腳本可以通過java發(fā)送
優(yōu)點(diǎn): 修改代碼方便

缺點(diǎn): 每次發(fā)送請求時(shí)都需要占用網(wǎng)絡(luò)資源

1.3.1:編寫lua腳本

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

1.3.2:修改ReidsConfig類

	@Bean
    public DefaultRedisScript<Boolean> defaultRedisScript(){
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
        //lock.lua腳本位置和application.yml同級目錄
        redisScript.setLocation(new ClassPathResource("lock.lua"));
        //設(shè)置類型為boolean
        redisScript.setResultType(Boolean.class);
        return redisScript;
    }

1.3.3:編寫測試模塊

@Test
    public void testLock03(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String value = UUID.randomUUID().toString();
        //如果key不存在才可以設(shè)置成功,設(shè)置一個(gè)value為隨機(jī)數(shù)的值,防止出現(xiàn)線程太多 導(dǎo)致線程不安全
        Boolean isLock = valueOperations.setIfAbsent("k1", value, 5, TimeUnit.SECONDS);
        //如果占位成功,進(jìn)行正常操作 
        if (isLock){
        	//設(shè)置一個(gè)name存到redis
            valueOperations.set("name","xxxx");
            //從redis取出name
            String name = (String) valueOperations.get("name");
            System.out.println("name = " + name);
            //為redis發(fā)送lua腳本刪除鎖對應(yīng)的value
            Boolean aBoolean = (Boolean) redisTemplate.execute(redisScript, Collections.singletonList("k1"), value);
            System.out.println(aBoolean);
        }else{
            System.out.println("有線程在用,請稍后在試");
        }
    }

測試結(jié)果:
順利把name值存到redis中并把鎖刪除并返回true

鎖會被正常刪除只留下name:

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

相關(guān)文章

  • Redis報(bào)錯(cuò):無法連接Redis服務(wù)的解決方法

    Redis報(bào)錯(cuò):無法連接Redis服務(wù)的解決方法

    在Linux系統(tǒng)上運(yùn)行Redis服務(wù)時(shí),有時(shí)會遇到“無法連接Redis服務(wù)”的報(bào)錯(cuò),本文就詳細(xì)的介紹一下解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Redis分布式可重入鎖實(shí)現(xiàn)方案

    Redis分布式可重入鎖實(shí)現(xiàn)方案

    在單進(jìn)程環(huán)境下,要保證一個(gè)代碼塊的同步執(zhí)行,直接用synchronized 關(guān)鍵字或ReetrantLock 即可,在分布式環(huán)境下,要保證多個(gè)節(jié)點(diǎn)的線程對代碼塊的同步訪問,就必須要用到分布式鎖方案,本文介紹一下基于 Redis實(shí)現(xiàn)的分布式鎖方案,感興趣的朋友一起看看吧
    2024-02-02
  • 壓縮Redis里的字符串大對象操作

    壓縮Redis里的字符串大對象操作

    這篇文章主要介紹了壓縮Redis里的字符串大對象操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • linux 常見的標(biāo)識與Redis數(shù)據(jù)庫詳解

    linux 常見的標(biāo)識與Redis數(shù)據(jù)庫詳解

    這篇文章主要介紹了linux 常見的標(biāo)識與Redis數(shù)據(jù)庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Redis設(shè)置Hash數(shù)據(jù)類型的過期時(shí)間

    Redis設(shè)置Hash數(shù)據(jù)類型的過期時(shí)間

    在Redis中,我們可以使用Hash數(shù)據(jù)結(jié)構(gòu)來存儲一組鍵值對,而有時(shí)候,我們可能需要設(shè)置這些鍵值對的過期時(shí)間,本文主要介紹了Redis設(shè)置Hash數(shù)據(jù)類型的過期時(shí)間,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Redis中的String類型及使用Redis解決訂單秒殺超賣問題

    Redis中的String類型及使用Redis解決訂單秒殺超賣問題

    這篇文章主要介紹了Redis中的String類型及使用Redis解決訂單秒殺超賣問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 一篇文章揭秘Redis的磁盤持久化機(jī)制

    一篇文章揭秘Redis的磁盤持久化機(jī)制

    這篇文章主要給大家介紹了如何通過一篇文章揭秘Redis的磁盤持久化機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Redis哨兵模式介紹

    Redis哨兵模式介紹

    這篇文章介紹了Redis哨兵模式,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-02-02
  • 關(guān)于Redis的內(nèi)存淘汰策略詳解

    關(guān)于Redis的內(nèi)存淘汰策略詳解

    當(dāng)內(nèi)存空間使用達(dá)到限制時(shí),Redis 會根據(jù)配置策略來選擇不同處理方式,要么返回 errors,要么按照不同的策略算法來清除一些舊數(shù)據(jù),達(dá)到回收內(nèi)存的目的,這就是 Redis 的內(nèi)存淘汰,有些文章中,內(nèi)存淘汰也叫緩存回收,需要的朋友可以參考下
    2023-05-05
  • 使用SpringBoot?+?Redis?實(shí)現(xiàn)接口限流的方式

    使用SpringBoot?+?Redis?實(shí)現(xiàn)接口限流的方式

    這篇文章主要介紹了SpringBoot?+?Redis?實(shí)現(xiàn)接口限流,Redis?除了做緩存,還能干很多很多事情:分布式鎖、限流、處理請求接口冪等,文中給大家提到了限流注解的創(chuàng)建方式,需要的朋友可以參考下
    2022-05-05

最新評論

武义县| 陕西省| 定陶县| 寿阳县| 灌云县| 南澳县| 利辛县| 永昌县| 天柱县| 柳河县| 安仁县| 星子县| 东城区| 香格里拉县| 依安县| 咸宁市| 翼城县| 驻马店市| 翁牛特旗| 临湘市| 瓮安县| 巴南区| 扎囊县| 临城县| 大丰市| 苗栗县| 额济纳旗| 赤峰市| 会宁县| 迁西县| 达日县| 平谷区| 黔西县| 鄂尔多斯市| 开化县| 民乐县| 南京市| 印江| 长乐市| 措美县| 策勒县|