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

springboot 集成redission 以及分布式鎖的使用詳解

 更新時間:2021年10月19日 09:59:19   作者:介寒食  
這篇文章主要介紹了springboot 集成redission 以及分布式鎖的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

springboot集成redission及分布式鎖的使用

1、引入jar包

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.4</version>
</dependency>

2、增加Configuration類

@Configuration
public class RedissonConfig { 
    @Value("${spring.redis.host}")
    private String host;
 
    @Value("${spring.redis.port}")
    private String port;
 
    @Value("${spring.redis.password}")
    private String password;
 
    @Bean
    public RedissonClient getRedisson() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
        return Redisson.create(config);
    }
}

3、使用redission分布式鎖

@Autowired
private RedissonClient redissonClient;
 
//方法區(qū)
String key = "aa:bb:cc:01";
RLock rLock =redissonClient.getLock(key);
try{<br>// 嘗試加鎖,最多等待1秒,上鎖以后10秒自動解鎖<br>// 沒有Watch Dog ,10s后自動釋放
boolean res = rLock.tryLock(1,10, TimeUnit.SECONDS);
if(!res){
  return new GeneralVO<>(400, "請勿重復(fù)提交", false);
}
}finally{
    rLock.unlock();
}
private void redissonDoc() throws InterruptedException {
    //1. 普通的可重入鎖
    RLock lock = redissonClient.getLock("generalLock");
 
    // 拿鎖失敗時會不停的重試
    // 具有Watch Dog 自動延期機制 默認續(xù)30s 每隔30/3=10 秒續(xù)到30s
    lock.lock();
 
    // 嘗試拿鎖10s后停止重試,返回false
    // 具有Watch Dog 自動延期機制 默認續(xù)30s
    boolean res1 = lock.tryLock(10, TimeUnit.SECONDS);
 
    // 拿鎖失敗時會不停的重試
    // 沒有Watch Dog ,10s后自動釋放
    lock.lock(10, TimeUnit.SECONDS);
 
    // 嘗試拿鎖100s后停止重試,返回false
    // 沒有Watch Dog ,10s后自動釋放
    boolean res2 = lock.tryLock(100, 10, TimeUnit.SECONDS);
 
    //2. 公平鎖 保證 Redisson 客戶端線程將以其請求的順序獲得鎖
    RLock fairLock = redissonClient.getFairLock("fairLock");
 
    //3. 讀寫鎖 沒錯與JDK中ReentrantLock的讀寫鎖效果一樣
    RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
    readWriteLock.readLock().lock();
    readWriteLock.writeLock().lock();
}

Springboot整合Redisson 鎖

Redisson是一個在Redis的基礎(chǔ)上實現(xiàn)的Java駐內(nèi)存數(shù)據(jù)網(wǎng)格

一、依賴

  <dependency>
      <groupId>org.redisson</groupId>
      <artifactId>redisson</artifactId>
      <version>3.15.4</version>
  </dependency>

二、配置文件

spring:
  redis:
    database: 7
    host: 116.62.178.11
    port: 6379
    password: 1234qwer
    #  spring-boot 1.0默認 jedis;  spring-boot2.0 默認lettuce ,lettuce線程安全
    lettuce:
      pool:
        # 連接池中的最大空閑連接 默認8
        max-idle: 8
        # 連接池中的最小空閑連接 默認0
        min-idle: 500
        # 連接池最大連接數(shù) 默認8 ,負數(shù)表示沒有限制
        max-active: 2000
        # 連接池最大阻塞等待時間(使用負值表示沒有限制) 默認-1
        max-wait: -1
    cache:
      type: redis
@Configuration
public class RedissonConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Bean(destroyMethod = "shutdown")
    RedissonClient redissonClient() throws IOException {
        Config config = new Config();
        config.useSingleServer()
                .setPassword(password)
                .setAddress("redis://" + host + ":" + port).setDatabase(7);
        return Redisson.create(config);
    }
}

三、鎖的使用

讀寫鎖

public class RedissionDemo {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 讀寫鎖 總結(jié)
     *
     * 讀鎖又叫共享鎖
     * 寫鎖又叫排他鎖(互斥鎖)
     * 讀 + 讀 相當(dāng)于無鎖,并發(fā)讀,同時加鎖成功
     * 寫 + 寫 阻塞狀態(tài)
     * 寫 + 讀 等待寫鎖釋放
     * 讀 + 寫 等待讀鎖完,才寫,
     */
    public String writeValue() {
        String str = "";
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("writeLock");
        RLock rLock = readWriteLock.writeLock();
        try {
            rLock.lock();
            str = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set("uuid", str);
            Thread.sleep(30000);
        } catch (Exception e) {
        } finally {
            rLock.unlock();
        }
        return str;
    }
    /**
     * 讀鎖
     *
     * @return
     */
    public String readValue() {
        String str = "";
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("writeLock");
        RLock rLock = readWriteLock.readLock();
        rLock.lock();
        str = (String) redisTemplate.opsForValue().get("uuid");
        rLock.unlock();
        return str;
    }
 
}

信號量

public class RedissionDemo {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 信號量
     *
     * @return
     */
    //停車方法
    @GetMapping("/park")
    public String park() throws InterruptedException {
        //這里是獲取信號量的值,這個信號量的name一定要與你初始化的一致
        RSemaphore park = redissonClient.getSemaphore("park");
        //這里會將信號量里面的值-1,如果為0則一直等待,直到信號量>0
        park.acquire();
        //tryAcquire為非阻塞式等待
        //park.tryAcquire();
        return "ok";
    }
    public String go() throws InterruptedException {
        //這里是獲取信號量的值,這個信號量的name一定要與你初始化的一致
        RSemaphore park = redissonClient.getSemaphore("park");
        //這里會將信號量里面的值+1,也就是釋放信號量
        park.release();
        return "ok";
    }
}

閉鎖

public class RedissionDemo {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate redisTemplate;
 
    /**
     * 閉鎖,限流
     *
     * @return
     * @throws InterruptedException
     */
    //鎖門
    public String lockdoor() throws InterruptedException {
        RCountDownLatch door = redissonClient.getCountDownLatch("door");
        //設(shè)置一個班級有20個同學(xué)
        door.trySetCount(20);
        //需要等到20個同學(xué)全部離開,才鎖門
        door.await();
        return "鎖門了";
    }
    public String leave(Long id) throws InterruptedException {
        RCountDownLatch door = redissonClient.getCountDownLatch("door");
        //表示一個同學(xué)離開
        door.countDown();
        return "" + id + "號同學(xué)離開了";
    }
}

四、分布式秒殺

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

秒殺流程:

在這里插入圖片描述

@Service
@Slf4j
public class DistributedSecKillBiz {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
 
    /**
     * 分布式鎖。唯一缺點 枷鎖失效時間
     * 枷鎖院子操作,
     * 解鎖,刪除鎖也是原子操作 瑕疵沒有續(xù)命
     *
     * @return
     */
    public String doKill() {
        String lock = UUID.randomUUID().toString();
        String goodsId = "10054";
        boolean flag = redisTemplate.opsForValue().setIfAbsent(goodsId, lock, 30, TimeUnit.SECONDS);
        if (flag) {
            // 獲取鎖成功
            try {
                Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
                if (stock > 0) {
                    redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
                    log.info("扣減庫存成功,還剩:" + stock);
                }
                return "庫存不足,該商品已搶購?fù)辏?;
            } catch (Exception e) {
            } finally {
                String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
                redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(goodsId), lock);
            }
        }
        return doKill();
    }
    /**
     * 整合 redission
     * @return
     */
    public String doKillDistributed() {
        String goodsId = "10054";
        RLock lock = redissonClient.getLock(upActivityKey() + SecKillConstant.LOCK + goodsId);
        // 獲取鎖成功
        try {
            //1 阻塞式等待,默認30秒時間
            //2 自動續(xù)期,如果業(yè)務(wù)超長,續(xù)上新的30秒,不用擔(dān)心過期時間,鎖自動刪除掉
            //3 枷鎖的業(yè)務(wù)運行完成,就不會給當(dāng)前的鎖自動續(xù)期,即使沒有手動釋放鎖也會,30秒自動釋放
//            lock.lock(30, TimeUnit.SECONDS); //不會自動續(xù)期需要注意
            lock.lock();
            Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
            if (stock > 0) {
                redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
                log.info("扣減庫存成功,還剩:" + stock);
            }
            return "庫存不足,該商品已搶購?fù)辏?;
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
        return "fail";
    }
    /**
     * 獲取活動
     *
     * @return
     */
    public ActivityBo upActivity() {
        return new ActivityBo("七夕活動", "SEVEN_ACTIVITY", new Date(), new Date());
    }
    /**
     * 活動公共key
     *
     * @return
     */
    public String upActivityKey() {
        return SecKillConstant.SEC_KILL + upActivity().getActivityKey() + ":";
    }
}

五、redis鎖 單機版可用,分布式用Redisson

package com.yang.yimall.seckill.app.seckill.biz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * redis 鎖 集群有瑕疵 不能 續(xù)命
 */
@Service
public class RedisLock {
    @Autowired
    private RedisTemplate redisTemplate;
    private String lockName = "lockName";
    private ThreadLocal<String> threadLocal = new ThreadLocal<>();
    public void lock(String lockName) {
        if (tryLock(lockName)) {
            return;
        }
        lock(lockName);
    }
    public void lock() {
        if (tryLock(lockName)) {
            return;
        }
        lock();
    }
    /**
     * 添加key 并且設(shè)置過期時間 原子操作
     *
     * @param lockName
     * @return
     */
    public boolean tryLock(String lockName) {
        String uuid = UUID.randomUUID().toString();
        threadLocal.set(uuid);
        return redisTemplate.opsForValue().setIfAbsent(lockName, uuid, 30, TimeUnit.SECONDS);
    }
    /**
     * 如果查詢有key,就刪除, 原子操作
     */
    public void unlock() {
        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Collections.singletonList(lockName), threadLocal.get());
    }
}

使用

 public String doKillUp() {
        String goodsId = "10054";
        redisLock.lock(goodsId);
        // 獲取鎖成功
        try {
            Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
            if (stock > 0) {
                redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId);
                log.info("扣減庫存成功,還剩:" + stock);
            }
            return "庫存不足,該商品已搶購?fù)辏?;
        } catch (Exception e) {
        } finally {
            redisLock.unlock();
        }
        return "庫存不足,該商品已搶購?fù)辏?;
    }

在這里插入圖片描述

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java可變參數(shù)當(dāng)做數(shù)組處理的方法示例

    java可變參數(shù)當(dāng)做數(shù)組處理的方法示例

    這篇文章主要介紹了java可變參數(shù)當(dāng)做數(shù)組處理的方法,結(jié)合實例形式分析了java可變參數(shù)當(dāng)做數(shù)組處理相關(guān)原理、步驟與操作注意事項,需要的朋友可以參考下
    2019-09-09
  • Java延時的3種實現(xiàn)方法舉例

    Java延時的3種實現(xiàn)方法舉例

    這篇文章主要給大家介紹了關(guān)于Java延時的3種實現(xiàn)方法舉例,java開發(fā)中常會用到延時任務(wù),文中通過實例代碼介紹的非常詳細,對大家的學(xué)習(xí)具有一定參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • jvm信息jmap使用的基本方法教程

    jvm信息jmap使用的基本方法教程

    JDK本身提供了很多方便的JVM性能調(diào)優(yōu)監(jiān)控工具,除了集成式的VisualVM和jConsole外,還有jps、jstack、jmap、jhat、jstat等小巧的工具,下面這篇文章主要給大家介紹了關(guān)于jvm信息jmap使用的基本方法教程,需要的朋友可以參考下
    2018-08-08
  • java獲取兩個List集合的交集代碼示例

    java獲取兩個List集合的交集代碼示例

    這篇文章主要給大家介紹了關(guān)于java獲取兩個List集合交集的相關(guān)資料,我們可以使用Stream操作來對集合進行一系列的操作,其中包括求交集,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • Java語言中cas指令的無鎖編程實現(xiàn)實例

    Java語言中cas指令的無鎖編程實現(xiàn)實例

    這篇文章主要介紹了Java語言中cas指令的無鎖編程實現(xiàn)實例,具有一定參考價值,需要的朋友可以了解下。
    2017-09-09
  • Java基于redis實現(xiàn)分布式鎖代碼實例

    Java基于redis實現(xiàn)分布式鎖代碼實例

    這篇文章主要介紹了Java基于redis實現(xiàn)分布式鎖代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java實現(xiàn)二分查找算法實例分析

    Java實現(xiàn)二分查找算法實例分析

    這篇文章主要介紹了Java實現(xiàn)二分查找算法,實例分析了二分查找算法的原理與相關(guān)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • 解決Springboot-application.properties中文亂碼問題

    解決Springboot-application.properties中文亂碼問題

    這篇文章主要介紹了解決Springboot-application.properties中文亂碼問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Intellij IDEA基于Springboot的遠程調(diào)試(圖文)

    Intellij IDEA基于Springboot的遠程調(diào)試(圖文)

    這篇文章主要介紹了Intellij IDEA基于Springboot的遠程調(diào)試(圖文),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 詳解springBoot啟動時找不到或無法加載主類解決辦法

    詳解springBoot啟動時找不到或無法加載主類解決辦法

    這篇文章主要介紹了詳解springBoot啟動時找不到或無法加載主類解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評論

望城县| 乌审旗| 循化| 河源市| 贺州市| 囊谦县| 阿尔山市| 潼南县| 乌鲁木齐县| 松原市| 武川县| 斗六市| 融水| 西华县| 桂平市| 丹棱县| 北京市| 手机| 泰来县| 德兴市| 噶尔县| 万年县| 横峰县| 南涧| 绵阳市| 建水县| 尼玛县| 锦屏县| 沅江市| 新和县| 醴陵市| 临洮县| 张家港市| 乐安县| 加查县| 惠水县| 新沂市| 通渭县| 理塘县| 阿瓦提县| 乳山市|