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

SpringBoot中使用Redis作為全局鎖示例過程

 更新時間:2022年03月23日 17:14:30   作者:KimZing  
這篇文章主要為大家介紹了SpringBoot中使用Redis作為全局鎖示例過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

微服務(wù)的項目中,一個服務(wù)我們啟動多份,在不同的進程中。這些服務(wù)是無狀態(tài)的,而由數(shù)據(jù)存儲容器(mysql/redis/es)進行狀態(tài)數(shù)據(jù)的持久化。這就會導(dǎo)致資源競爭,出現(xiàn)多線程的問題。

一、模擬沒有鎖情況下的資源競爭

public class CommonConsumerService {
    //庫存?zhèn)€數(shù)
    static int goodsCount = 900;
    //賣出個數(shù)
    static int saleCount = 0;
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {Thread.sleep(2);} catch (InterruptedException e) {}
                if (goodsCount > 0) {
                    goodsCount--;
                    System.out.println("剩余庫存:" + goodsCount + " 賣出個數(shù)" + ++saleCount);
                }
            }).start();
        }
        Thread.sleep(3000);
    }
}

運行一次,最后幾行的輸出結(jié)果如下,很明顯出錯了,剩余0個商品卻只賣出了899個商品,很明顯有商品被某個線程私吞了。

...
剩余庫存:5 賣出個數(shù)893
剩余庫存:5 賣出個數(shù)894
剩余庫存:4 賣出個數(shù)895
剩余庫存:2 賣出個數(shù)896
剩余庫存:2 賣出個數(shù)897
剩余庫存:1 賣出個數(shù)898
剩余庫存:0 賣出個數(shù)899

二、使用redis加鎖

redis是單線程的,串行執(zhí)行,那么接下來使用redis為資源進行加鎖。

1.首先引入依賴

compile "org.springframework.boot:spring-boot-starter-data-redis"

2.引入redis加鎖工具類

package com.kingboy.common.utils;
import redis.clients.jedis.Jedis;
import java.util.Collections;
/**
 * @author kingboy--KingBoyWorld@163.com
 * @date 2017/12/29 下午1:57
 * @desc Redis工具.
 */
public class RedisTool {
    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private static final Long RELEASE_SUCCESS = 1L;
    /**
     * 嘗試獲取分布式鎖
     * @param jedis      Redis客戶端
     * @param lockKey    鎖
     * @param requestId  請求標識
     * @param expireTime 超期時間
     * @return 是否獲取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
    /**
     * 釋放分布式鎖
     * @param jedis     Redis客戶端
     * @param lockKey   鎖
     * @param requestId 請求標識
     * @return 是否釋放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
}

3.將上面沒有鎖的示例代碼改編如下:

public class RedisLockConsumerService {
    //庫存?zhèn)€數(shù)
    static int goodsCount = 900;
    //賣出個數(shù)
    static int saleCount = 0;
    @SneakyThrows
    public static void main(String[] args) {
        JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "192.168.0.130", 6379, 1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {Thread.sleep(2);} catch (InterruptedException e) {}
                Jedis jedis = jedisPool.getResource();
                boolean lock = false;
                while (!lock) {
                    lock = RedisTool.tryGetDistributedLock(jedis, "goodsCount", Thread.currentThread().getName(), 10);
                }
                if (lock) {
                    if (goodsCount > 0) {
                        goodsCount--;
                        System.out.println("剩余庫存:" + goodsCount + " 賣出個數(shù)" + ++saleCount);
                    }
                }
                RedisTool.releaseDistributedLock(jedis, "goodsCount", Thread.currentThread().getName());
                jedis.close();
            }).start();
        }
        Thread.sleep(3000);
        jedisPool.close();
    }
}

執(zhí)行幾次程序輸出結(jié)果如下,可以看到結(jié)果是有序,并且正確的。

...
剩余庫存:6 賣出個數(shù)894
剩余庫存:5 賣出個數(shù)895
剩余庫存:4 賣出個數(shù)896
剩余庫存:3 賣出個數(shù)897
剩余庫存:2 賣出個數(shù)898
剩余庫存:1 賣出個數(shù)899
剩余庫存:0 賣出個數(shù)900

以上就是SpringBoot中使用Redis作為全局鎖示例過程的詳細內(nèi)容,更多關(guān)于SpringBoot Redis全局鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JDK8環(huán)境中使用struts2的步驟詳解

    JDK8環(huán)境中使用struts2的步驟詳解

    這篇文章主要給大家介紹了關(guān)于在JDK8環(huán)境中使用struts2的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • SpringCloud zookeeper作為注冊中心使用介紹

    SpringCloud zookeeper作為注冊中心使用介紹

    ZooKeeper由雅虎研究院開發(fā),是Google Chubby的開源實現(xiàn),后來托管到Apache,于2010年11月正式成為Apache的頂級項目。ZooKeeper是一個經(jīng)典的分布式數(shù)據(jù)一致性解決方案,致力于為分布式應(yīng)用提供一個高性能、高可用,且具有嚴格順序訪問控制能力的分布式協(xié)調(diào)服務(wù)
    2022-11-11
  • 解決spring @ControllerAdvice處理異常無法正確匹配自定義異常

    解決spring @ControllerAdvice處理異常無法正確匹配自定義異常

    這篇文章主要介紹了解決spring @ControllerAdvice處理異常無法正確匹配自定義異常的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java 數(shù)據(jù)庫連接池 DBCP 的介紹

    Java 數(shù)據(jù)庫連接池 DBCP 的介紹

    這篇文章主要給大家分享的是 Java 數(shù)據(jù)庫連接池 DBCP 的介紹, 是 Apache 旗下 Commons 項目下的一個子項目,提供連接池功能DBCP,下面來看看文章的具體介紹內(nèi)容吧,需要的朋友可以參考一下
    2021-11-11
  • Java?不同版本的?Switch語句

    Java?不同版本的?Switch語句

    本文主要介紹了Java不同版本的Switch語句,自Java13以來,Switch表達式就被添加到Java核心庫中,下面我們將介紹舊的Java?Switch語句和新的Switch語句的區(qū)別,需要的朋友可以參考一下
    2022-06-06
  • Java數(shù)字圖像處理之圖像灰度處理

    Java數(shù)字圖像處理之圖像灰度處理

    這篇文章主要為大家詳細介紹了Java數(shù)字圖像處理之圖像灰度處理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • jboss配置方法簡明教程

    jboss配置方法簡明教程

    這篇文章主要介紹了jboss配置方法,較為簡明扼要的說明了jboss服務(wù)器所需要的JDK環(huán)境安裝設(shè)置以及jboss的安裝與下載,并分析了配置與使用中的常見問題,需要的朋友可以參考下
    2016-08-08
  • Java中String判斷值為null或空及地址是否相等的問題

    Java中String判斷值為null或空及地址是否相等的問題

    這篇文章主要介紹了Java中String判斷值為null或空及地址是否相等的問題,文中舉了簡單的例子對字符串類型的值和地址問題進行講解,需要的朋友可以參考下
    2016-01-01
  • Java開發(fā)之request對象常用方法整理

    Java開發(fā)之request對象常用方法整理

    這篇文章主要介紹了 Java開發(fā)之request對象常用方法整理的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 前后端分離跨域springBoot跨域有效解決問題

    前后端分離跨域springBoot跨域有效解決問題

    這篇文章主要介紹了前后端分離跨域springBoot跨域有效解決問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評論

资溪县| 杭州市| 宁陵县| 平乐县| 若羌县| 乃东县| 米脂县| 顺昌县| 咸阳市| 图们市| 东乡族自治县| 那坡县| 贵州省| 礼泉县| 达拉特旗| 卢龙县| 宁夏| 高密市| 延庆县| 手游| 衢州市| 杭锦后旗| 扶风县| 获嘉县| 运城市| 汶川县| 松桃| 岱山县| 湾仔区| 丹江口市| 普格县| 澄江县| 长白| 同德县| 历史| 镇宁| 西昌市| 衢州市| 福州市| 靖宇县| 长顺县|