成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

單實(shí)例redis分布式鎖的簡(jiǎn)單實(shí)現(xiàn)

單實(shí)例redis分布式鎖的簡(jiǎn)單實(shí)現(xiàn)

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的潼南網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

redis分布式鎖的基本功能包括, 同一刻只能有一個(gè)人占有鎖, 當(dāng)鎖被其他人占用時(shí), 獲取者可以等待他人釋放鎖, 此外鎖本身必須能超時(shí)自動(dòng)釋放.

直接上java代碼, 如下:

package com.test;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * 簡(jiǎn)單的單實(shí)例redis分布式鎖
 * 沒有實(shí)現(xiàn)的高級(jí)功能:鎖的重入、鎖的續(xù)約等
 *
 * @Author:tt
 * @Description:
 * @CreateTime:2019/6/12
 */
public class SingleRedisLock {

    private JedisPool jedisPool;

    /**
     * 獲取鎖
     *
     * @param lockKey          鎖的key
     * @param lockVal          鎖的val,可以利用來(lái)實(shí)現(xiàn)"避免誤刪別人鎖"、"鎖的重入"等功能
     * @param lockMaxLifeTime  鎖的最大生命時(shí)長(zhǎng),到期自動(dòng)銷毀,單位:毫秒
     * @param tryWaitingTime   等待獲取鎖的超時(shí)時(shí)間,單位:毫秒
     * @param waitingSleepTime 等待獲取鎖的阻塞周期,單位:毫秒,設(shè)置過短會(huì)造成cpu競(jìng)爭(zhēng),設(shè)置過長(zhǎng)會(huì)造成浪費(fèi),需依賴于'具體業(yè)務(wù)平均的執(zhí)行時(shí)長(zhǎng)'
     * @return
     */
    public Boolean tryLock(String lockKey, String lockVal, int lockMaxLifeTime, int tryWaitingTime, int waitingSleepTime) {

        //lua腳本,讓邏輯簡(jiǎn)單清晰,同時(shí)保證原子性
        //setNX:成功-1,失敗-0
        String lua = " if redis.call('set',KEYS[1],ARGV[1],'PX',ARGV[2],'NX') then return 1 else return 0 end ";

        //獲取鎖的開始時(shí)間
        Long tryBeginTime = System.currentTimeMillis();

        //輪詢
        while (true) {

            Long result = null;
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                result = (Long) jedis.eval(lua, Arrays.asList(lockKey), Arrays.asList(lockVal, String.valueOf(lockMaxLifeTime)));
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (jedis != null) {
                    try {
                        jedis.close();
                    } catch (Exception e) {
                    }
                }
            }

            //獲取鎖成功
            if (Long.valueOf(1).equals(result)) {
                return true;
            }

            //當(dāng)前時(shí)間
            Long now = System.currentTimeMillis();
            //獲取等待超時(shí),就不用獲取了
            if (now - tryBeginTime >= tryWaitingTime) {
                return false;
            }

            try {
                //阻塞等一會(huì)兒再重新去獲取
                TimeUnit.MILLISECONDS.sleep(waitingSleepTime);
            } catch (InterruptedException e) {
            }

        }

    }

    /**
     * 釋放鎖
     *
     * @param lockKey
     * @param lockVal
     * @return
     */
    public void releaseLock(String lockKey, String lockVal) {

        //如果lockVal是自己的再刪除,防止誤刪,場(chǎng)景來(lái)源:當(dāng)前鎖的持有者操作時(shí)間太長(zhǎng),鎖已經(jīng)自動(dòng)釋放并被別人占有了
        String lua = "if redis.call('get', KEYS[1]) == ARGV[1] then redis.call('del', KEYS[1]) end ";

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.eval(lua, Arrays.asList(lockKey), Arrays.asList(lockVal));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                try {
                    jedis.close();
                } catch (Exception e) {
                }
            }
        }

    }

    //測(cè)試
    public static void main(String[] args) {
        //連接池
        JedisPool jedisPool = new JedisPool(new GenericObjectPoolConfig(), "127.0.0.1", 6379, 2000, "test123");
        SingleRedisLock simpleRedisLock = new SingleRedisLock();
        simpleRedisLock.jedisPool = jedisPool;

        //模擬10個(gè)并發(fā)
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {

                String lockKey = "TEST_LOCK_KEY";
                String threadName = Thread.currentThread().getName();

                //獲取鎖
                Boolean locked = simpleRedisLock.tryLock(lockKey, threadName,
                        30000, 5000, 200);

                //獲取鎖失敗
                if (!locked) {
                    System.err.println(">>> " + threadName + " 獲取鎖失敗");
                    return;
                }

                //獲取鎖成功,模擬執(zhí)行業(yè)務(wù)操作
                System.out.println(">>> " + threadName + " 獲取鎖成功");
                doShortBusiness();
                //doLongBusiness();

                //釋放鎖
                simpleRedisLock.releaseLock(lockKey, threadName);

            }).start();
        }

        try {
            TimeUnit.MILLISECONDS.sleep(60000);
        } catch (InterruptedException e) {
        }
    }

    //短任務(wù):100毫秒
    static void doShortBusiness() {
        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
        }
    }

    //長(zhǎng)任務(wù):3秒
    static void doLongBusiness() {
        try {
            TimeUnit.MILLISECONDS.sleep(3000);
        } catch (InterruptedException e) {
        }
    }

}

鎖的高級(jí)功能包含鎖的重入、鎖的續(xù)約等, 當(dāng)然為了保證鎖的高可用, redis還有主從、集群等部署方式, 對(duì)應(yīng)的鎖的實(shí)現(xiàn)也有區(qū)別, 略微復(fù)雜, 不過有現(xiàn)成的框架可供我們參考使用, 比較知名的如Redisson, 一個(gè)強(qiáng)大的redis客戶端, 當(dāng)然包括對(duì)“分布式鎖”的完美實(shí)現(xiàn), 其支持redis單實(shí)例、哨兵、集群等模式。

寫在最后

單實(shí)例redis分布式鎖的簡(jiǎn)單實(shí)現(xiàn)

文章題目:單實(shí)例redis分布式鎖的簡(jiǎn)單實(shí)現(xiàn)
分享地址:http://jinyejixie.com/article18/pdsogp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣、用戶體驗(yàn)、關(guān)鍵詞優(yōu)化品牌網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
大邑县| 仁化县| 南澳县| 桃江县| 大厂| 海淀区| 临沭县| 兴文县| 横山县| 札达县| 河北省| 河北省| 大宁县| 甘肃省| 光山县| 喀喇沁旗| 彰化县| 绿春县| 公主岭市| 手游| 浦江县| 平昌县| 若羌县| 嘉祥县| 东城区| 大同县| 福建省| 大埔区| 平泉县| 抚松县| 安龙县| 道孚县| 登封市| 秭归县| 明水县| 牡丹江市| 新安县| 镇赉县| 柯坪县| 镇巴县| 郁南县|