亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

準(zhǔn)備工作:

導(dǎo)入依賴(lài)

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

編寫(xiě)RedisConfig類(lèi)

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

1.在SpringBootTest中編寫(xiě)測(cè)試模塊

1.1:使用占位符加鎖:

占位符加鎖問(wèn)題:出現(xiàn)異常時(shí)無(wú)法釋放鎖,導(dǎo)致后繼進(jìn)入的線(xià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("有線(xiàn)程在用,請(qǐng)稍后在試");
	        }
	}
}

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


之后所有線(xiàn)程都無(wú)法訪(fǎng)問(wèn):

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

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

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

	@Test
    public void testLock02()  {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //如果key不存在才可以設(shè)置成功,設(shè)置一個(gè)有效時(shí)間防止線(xiàn)程異常出現(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("有線(xiàn)程在用,請(qǐng)稍后在試");
        }
    }

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

1.3:使用lua腳本解決線(xiàn)程不安全問(wèn)題:

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

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

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

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

1.3.1:編寫(xiě)lua腳本

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

1.3.2:修改ReidsConfig類(lèi)

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

1.3.3:編寫(xiě)測(cè)試模塊

@Test
    public void testLock03(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String value = UUID.randomUUID().toString();
        //如果key不存在才可以設(shè)置成功,設(shè)置一個(gè)value為隨機(jī)數(shù)的值,防止出現(xiàn)線(xiàn)程太多 導(dǎo)致線(xiàn)程不安全
        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腳本刪除鎖對(duì)應(yīng)的value
            Boolean aBoolean = (Boolean) redisTemplate.execute(redisScript, Collections.singletonList("k1"), value);
            System.out.println(aBoolean);
        }else{
            System.out.println("有線(xiàn)程在用,請(qǐng)稍后在試");
        }
    }

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

鎖會(huì)被正常刪除只留下name:

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

相關(guān)文章

  • 從一個(gè)小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))

    從一個(gè)小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))

    Redis在實(shí)際應(yīng)用中使用的非常廣泛,本篇文章就從一個(gè)簡(jiǎn)單的需求說(shuō)起,為你講述一個(gè)需求是如何從頭到尾開(kāi)始做的,又是如何一步步完善的
    2019-12-12
  • 淺談Redis緩存有哪些淘汰策略

    淺談Redis緩存有哪些淘汰策略

    redis用做緩存是一種非常常見(jiàn)的手段,然而由于內(nèi)存大小的限制,會(huì)導(dǎo)致redis在內(nèi)存空間滿(mǎn)了以后需要處理繼續(xù)存入的數(shù)據(jù),所以就需要淘汰策略,本文就詳細(xì)的介紹一下
    2021-08-08
  • redis如何設(shè)置key的有效期

    redis如何設(shè)置key的有效期

    這篇文章主要介紹了redis如何設(shè)置key的有效期方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn)

    Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn)

    本文主要介紹了Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Redis過(guò)期鍵與內(nèi)存淘汰策略深入分析講解

    Redis過(guò)期鍵與內(nèi)存淘汰策略深入分析講解

    因?yàn)閞edis數(shù)據(jù)是基于內(nèi)存的,然而內(nèi)存是非常寶貴的資源,然后我們就會(huì)對(duì)一些不常用或者只用一次的數(shù)據(jù)進(jìn)行存活時(shí)間設(shè)置,這樣才能提高內(nèi)存的使用效率,下面這篇文章主要給大家介紹了關(guān)于Redis中過(guò)期鍵與內(nèi)存淘汰策略,需要的朋友可以參考下
    2022-11-11
  • 利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線(xiàn)程安全問(wèn)題

    利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線(xiàn)程安全問(wèn)題

    這篇文章主要介紹了利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線(xiàn)程安全問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • Windows中redis設(shè)置密碼的兩種方法

    Windows中redis設(shè)置密碼的兩種方法

    之前寫(xiě)的一個(gè)項(xiàng)目,有項(xiàng)目代碼,有數(shù)據(jù)庫(kù),但是本地沒(méi)redis,沒(méi)法跑此項(xiàng)目,故思考在本地安裝一個(gè)redis做登錄session存儲(chǔ),所以開(kāi)始動(dòng)手實(shí)踐,下面這篇文章主要給大家介紹了關(guān)于Windows中redis設(shè)置密碼的兩種方法,需要的朋友可以參考下
    2023-04-04
  • Redis模仿發(fā)送手機(jī)驗(yàn)證碼功能

    Redis模仿發(fā)送手機(jī)驗(yàn)證碼功能

    這篇文章主要介紹了Redis模仿手機(jī)驗(yàn)證碼發(fā)送功能,通過(guò)示例代碼給大家講解通過(guò)用戶(hù)輸入手機(jī)號(hào)以及驗(yàn)證碼進(jìn)行校驗(yàn),代碼簡(jiǎn)單易懂,需要的朋友可以參考下
    2021-09-09
  • 將音頻文件轉(zhuǎn)二進(jìn)制分包存儲(chǔ)到Redis的實(shí)現(xiàn)方法(奇淫技巧操作)

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

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

    Redis高性能的原因及說(shuō)明

    這篇文章主要介紹了Redis高性能的原因及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評(píng)論