應用Redis實現分布式鎖

來源:互聯網
上載者:User

標籤:get   val   mem   exception   client   color   時間   分布式   錯誤   

 

主要參考:

  1. http://blog.csdn.net/fjssharpsword/article/details/52250723#
  2. http://www.yiibai.com/redis/strings_getset.html
  3. https://redis.io/commands/expire
  4. https://www.baidu.com/link?url=kuDPE2uEXfjZO3qCggv2OaDGcd9_Mohb_S2Web1VHiY623cg4IJZRwqb0_tGyan7x0BJuV1I46dh-qGWCPEJsa&wd=&eqid=879de37e00008ea500000004583ef0f8

 

package com.deppon.spring;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import redis.clients.jedis.Jedis;/** *  * @author ganxj * */public class BuildDistributedLockWithRedisDB {    // 鎖名    private static final String lockName = "lock";        // 序列名    private static final String sequenceName = "sequence";        // 資料失效時間    private static final int expired = 1;// 1秒逾時    // 當前線程處理當次快取作業所需時間,(預估值)    private static final int time = 10 * 1000;    // setnx --- 若且唯若 key 不存在,將 key 的值設為 value ,並返回1;若給定的 key 已經存在,則 SETNX不做任何動作,並返回0。     // getSet -- 將給定 key 的值設為 value ,並返回 key 的舊值 (old value),當 key存在但不是字串類型時,返回一個錯誤,當key不存在時,返回nil。    // 上鎖    public static boolean acquireLock(Jedis jedis, String lock) {        try {            // 用於設定成功後的緩衝處理時間長度            long cacheProcessTime = System.currentTimeMillis() + time;            // key為空白時,爭搶鎖            long isSetSuccessWhileKeyIsNil = jedis.setnx(lock, String.valueOf(cacheProcessTime));            // SETNX成功,則成功擷取一個鎖,並設定資料失效時間            if (isSetSuccessWhileKeyIsNil == 1) {                jedis.expire(lock, expired);                return true;            }            // key不為空白,SETNX失敗,說明鎖被其他用戶端保持,檢查其是否已經逾時            String lastLockTimeBySomeThread = jedis.get(lock);            // 如果擷取key為空白,則重走空key時的加鎖流程            if (lastLockTimeBySomeThread == null) {                return false;            }            // 擷取key不為空白,則判斷是否逾時,若未逾時,則迴圈重試            if (Long.valueOf(lastLockTimeBySomeThread) > System.currentTimeMillis()) {                return false;            }            // 若逾時,則進行爭搶加鎖            String getOldIfSet = jedis.getSet(lock, String.valueOf(cacheProcessTime));            // 判斷加鎖是否成功            if (getOldIfSet != null && getOldIfSet.equals(lastLockTimeBySomeThread)) {                return true;            }            // 若加鎖失敗,重頭再來            return false;        } catch (Exception e) {            e.printStackTrace();        }        return false;    }    // 釋放鎖    public static void releaseLock(Jedis jedis, String lock) {        try {                        String lastLockTimeBySomeThread = jedis.get(lock);            if (lastLockTimeBySomeThread == null) {                return;            }            // 避免刪除非自己擷取得到的鎖            if (System.currentTimeMillis() < Long.valueOf(lastLockTimeBySomeThread)) {                jedis.del(lock);            }        } catch (Exception e) {            e.printStackTrace();        }    }    @SuppressWarnings("resource")    public static void main(String[] args) {                // 任務數        int produceTaskMaxNumber = 100;                // 初始化redis中的id序列        Jedis jedis = new Jedis();        jedis.set(sequenceName, String.valueOf(Long.valueOf(1)));                // 初始化線程池        int corePoolSize = 20;        int maximumPoolSize=20;        long keepAliveTime =20;        TimeUnit unit =TimeUnit.SECONDS;        BlockingQueue<Runnable> workQueu = new ArrayBlockingQueue<Runnable>(30);        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(                corePoolSize,                 maximumPoolSize,                 keepAliveTime,                 unit,                workQueu,                handler);        // 建立任務        for (int i = 1; i <= produceTaskMaxNumber; i++) {            try {                threadPool.execute(new BuildDistributedLockWithRedisDB().new RedisLockTestTask());            } catch (Exception e) {                e.printStackTrace();            }        }    }    class RedisLockTestTask implements Runnable {                @Override        public void run() {                        Jedis jedis = new Jedis();            Boolean lockFlag = true;                        // 迴圈等待拿鎖            long startTime = System.currentTimeMillis();            while (lockFlag) {                if (BuildDistributedLockWithRedisDB.acquireLock(jedis, lockName)) {                    // 獲得鎖了,開始執行商務邏輯                    process(jedis, sequenceName);                    lockFlag = false;                }            }            long endTime = System.currentTimeMillis();                                    System.out.println(Thread.currentThread().getName()                     + "線程設定的值:"                     + jedis.get(sequenceName)                     + "  "                     + "共消耗時間長度:" + (endTime - startTime) + "ms");                        // 釋放鎖            BuildDistributedLockWithRedisDB.releaseLock(jedis, lockName);                    }    }            void process(Jedis jedis,String sequenceName){        jedis.set(sequenceName, String.valueOf(Long.valueOf(jedis.get(sequenceName)) + 1));    }} 

 

應用Redis實現分布式鎖

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.