干貨貼】DCS實踐干貨:使用Redis實現分布式鎖

      網友投稿 803 2025-04-03

      場景介紹


      很多互聯網場景(如商品秒殺,論壇回帖蓋樓等),需要用加鎖的方式,以對某種資源進行順序訪問控制。如果應用服務集群部署,則涉及到對分布式應用加鎖。當前分布式加鎖主要有三種方式:(磁盤)數據庫、緩存數據庫、Zookeeper。接下里讓我們一起看看加鎖實踐過程。

      加鎖實現

      package dcsDemo01;

      import java.util.UUID;

      import redis.clients.jedis.Jedis;

      public class DistributedLock {

      private final String host = "192.168.0.220";

      private final int port = 6379;

      private static final String SUCCESS = "OK";

      private static final String SET_IF_NOT_EXIST = "NX";

      private static final String EXPIRE_TIME = "PX";

      public? DistributedLock(){}

      /*

      * @param lockName????? 鎖名

      * @param timeout?????? 獲取鎖的超時時間

      * @param lockTimeout?? 鎖的有效時間

      * @return????????????? 鎖的標識

      */

      public String getLockWithTimeout(String lockName, long timeout, long lockTimeout) {

      String ret = null;

      Jedis jedisClient = new Jedis(host, port);

      try {

      String authMsg = jedisClient.auth("Demo@123");

      if (!SUCCESS.equals(authMsg)) {

      System.out.println("AUTH FAILED: " + authMsg);

      }

      String identifier = UUID.randomUUID().toString();

      String lockKey = "DLock:" + lockName;

      【干貨貼】DCS實踐干貨:使用Redis實現分布式鎖

      long end = System.currentTimeMillis() + timeout;

      while(System.currentTimeMillis() < end) {

      String result = jedisClient.set(lockKey, identifier, SET_IF_NOT_EXIST, EXPIRE_TIME, lockTimeout);

      if(SUCCESS.equals(result)) {

      ret = identifier;

      break;

      }

      try {

      Thread.sleep(2);

      } catch (InterruptedException e) {

      Thread.currentThread().interrupt();

      }

      }

      }

      catch (Exception e) {

      e.printStackTrace();

      }finally {

      jedisClient.quit();

      jedisClient.close();

      }

      return ret;

      }

      /*

      * @param lockName??????? 鎖名

      * @param identifier??? 鎖的標識

      */

      public void releaseLock(String lockName, String identifier) {

      Jedis jedisClient = new Jedis(host, port);

      try {

      String authMsg = jedisClient.auth("Demo@123");

      if (!SUCCESS.equals(authMsg)) {

      System.out.println("AUTH FAILED: " + authMsg);

      }

      String lockKey = "DLock:" + lockName;

      if(identifier.equals(jedisClient.get(lockKey))) {

      jedisClient.del(lockKey);

      }

      }

      catch (Exception e) {

      e.printStackTrace();

      }finally {

      jedisClient.quit();

      jedisClient.close();

      }

      }

      }

      測試代碼

      假設20個線程對10臺mate10手機進行搶購:

      package dcsDemo01;

      import java.util.UUID;

      public class CaseTest {

      public static void main(String[] args) {

      ServiceOrder service = new ServiceOrder();

      for (int i = 0; i < 20; i++) {

      ThreadBuy client = new ThreadBuy(service);

      client.start();

      }

      }

      }

      class ServiceOrder {

      private final int MAX = 10;

      DistributedLock DLock = new DistributedLock();

      int n = 10;

      public void handleOder() {

      String userName = UUID.randomUUID().toString().substring(0,8) + Thread.currentThread().getName();

      String identifier = DLock.getLockWithTimeout("Huawei Mate 10", 10000, 2000);

      System.out.println("正在為用戶:" + userName + " 處理訂單");

      if(n > 0) {

      int num = MAX - n + 1;

      System.out.println("用戶:"+ userName + "購買第" + num + "臺,剩余" + (--n) + "臺");

      }else {

      System.out.println("用戶:"+ userName + "無法購買,已售罄!");

      }

      DLock.releaseLock("Huawei Mate 10", identifier);

      }

      }

      class ThreadBuy extends Thread {

      private ServiceOrder service;

      public ThreadBuy(ServiceOrder service) {

      this.service = service;

      }

      @Override

      public void run() {

      service.handleOder();

      }

      }

      運行結果

      配置好實際的緩存實例連接地址、端口與連接密碼,運行代碼,得到以下結果:

      正在為用戶:eee56fb7Thread-16 處理訂單

      用戶:eee56fb7Thread-16購買第1臺,剩余9臺

      正在為用戶:d6521816Thread-2 處理訂單

      用戶:d6521816Thread-2購買第2臺,剩余8臺

      正在為用戶:d7b3b983Thread-19 處理訂單

      用戶:d7b3b983Thread-19購買第3臺,剩余7臺

      正在為用戶:36a6b97aThread-15 處理訂單

      用戶:36a6b97aThread-15購買第4臺,剩余6臺

      正在為用戶:9a973456Thread-1 處理訂單

      用戶:9a973456Thread-1購買第5臺,剩余5臺

      正在為用戶:03f1de9aThread-14 處理訂單

      用戶:03f1de9aThread-14購買第6臺,剩余4臺

      正在為用戶:2c315ee6Thread-11 處理訂單

      用戶:2c315ee6Thread-11購買第7臺,剩余3臺

      正在為用戶:2b03b7c0Thread-12 處理訂單

      用戶:2b03b7c0Thread-12購買第8臺,剩余2臺

      正在為用戶:75f25749Thread-0 處理訂單

      用戶:75f25749Thread-0購買第9臺,剩余1臺

      正在為用戶:26c71db5Thread-18 處理訂單

      用戶:26c71db5Thread-18購買第10臺,剩余0臺

      正在為用戶:c32654dbThread-17 處理訂單

      用戶:c32654dbThread-17無法購買,已售罄!

      正在為用戶:df94370aThread-7 處理訂單

      用戶:df94370aThread-7無法購買,已售罄!

      正在為用戶:0af94cddThread-5 處理訂單

      用戶:0af94cddThread-5無法購買,已售罄!

      正在為用戶:e52428a4Thread-13 處理訂單

      用戶:e52428a4Thread-13無法購買,已售罄!

      正在為用戶:46f91208Thread-10 處理訂單

      用戶:46f91208Thread-10無法購買,已售罄!

      正在為用戶:e0ca87bbThread-9 處理訂單

      用戶:e0ca87bbThread-9無法購買,已售罄!

      正在為用戶:f385af9aThread-8 處理訂單

      用戶:f385af9aThread-8無法購買,已售罄!

      正在為用戶:46c5f498Thread-6 處理訂單

      用戶:46c5f498Thread-6無法購買,已售罄!

      正在為用戶:935e0f50Thread-3 處理訂單

      用戶:935e0f50Thread-3無法購買,已售罄!

      正在為用戶:d3eaae29Thread-4 處理訂單

      用戶:d3eaae29Thread-4無法購買,已售罄!

      如果注釋掉加鎖代碼,變成無鎖情況,則搶購無序。

      //測試類中注釋兩行用于加鎖的代碼:

      public void handleOder() {

      String userName = UUID.randomUUID().toString().substring(0,8) + Thread.currentThread().getName();

      //加鎖代碼

      //String identifier = DLock.getLockWithTimeout("Huawei Mate 10", 10000, 2000);

      System.out.println("正在為用戶:" + userName + " 處理訂單");

      if(n > 0) {

      int num = MAX - n + 1;

      System.out.println("用戶:"+ userName + "夠買第" + num + "臺,剩余" + (--n) + "臺");

      }else {

      System.out.println("用戶:"+ userName + "無法夠買,已售罄!");

      }

      //加鎖代碼

      //DLock.releaseLock("Huawei Mate 10", identifier);

      }

      注釋加鎖代碼后的運行結果,可以看出處理過程是無序的:

      正在為用戶:e04934ddThread-5 處理訂單

      正在為用戶:a4554180Thread-0 處理訂單

      用戶:a4554180Thread-0購買第2臺,剩余8臺

      正在為用戶:b58eb811Thread-10 處理訂單

      用戶:b58eb811Thread-10購買第3臺,剩余7臺

      正在為用戶:e8391c0eThread-19 處理訂單

      正在為用戶:21fd133aThread-13 處理訂單

      正在為用戶:1dd04ff4Thread-6 處理訂單

      用戶:1dd04ff4Thread-6購買第6臺,剩余4臺

      正在為用戶:e5977112Thread-3 處理訂單

      正在為用戶:4d7a8a2bThread-4 處理訂單

      用戶:e5977112Thread-3購買第7臺,剩余3臺

      正在為用戶:18967410Thread-15 處理訂單

      用戶:18967410Thread-15購買第9臺,剩余1臺

      正在為用戶:e4f51568Thread-14 處理訂單

      用戶:21fd133aThread-13購買第5臺,剩余5臺

      用戶:e8391c0eThread-19購買第4臺,剩余6臺

      正在為用戶:d895d3f1Thread-12 處理訂單

      用戶:d895d3f1Thread-12無法購買,已售罄!

      正在為用戶:7b8d2526Thread-11 處理訂單

      用戶:7b8d2526Thread-11無法購買,已售罄!

      正在為用戶:d7ca1779Thread-8 處理訂單

      用戶:d7ca1779Thread-8無法購買,已售罄!

      正在為用戶:74fca0ecThread-1 處理訂單

      用戶:74fca0ecThread-1無法購買,已售罄!

      用戶:e04934ddThread-5購買第1臺,剩余9臺

      用戶:e4f51568Thread-14購買第10臺,剩余0臺

      正在為用戶:aae76a83Thread-7 處理訂單

      用戶:aae76a83Thread-7無法購買,已售罄!

      正在為用戶:c638d2cfThread-2 處理訂單

      用戶:c638d2cfThread-2無法購買,已售罄!

      正在為用戶:2de29a4eThread-17 處理訂單

      用戶:2de29a4eThread-17無法購買,已售罄!

      正在為用戶:40a46ba0Thread-18 處理訂單

      用戶:40a46ba0Thread-18無法購買,已售罄!

      正在為用戶:211fd9c7Thread-9 處理訂單

      用戶:211fd9c7Thread-9無法購買,已售罄!

      正在為用戶:911b83fcThread-16 處理訂單

      用戶:911b83fcThread-16無法購買,已售罄!

      用戶:4d7a8a2bThread-4購買第8臺,剩余2臺

      總的來說,使用DCS服務中Redis類型的緩存實例實現分布式加鎖,有幾大優勢:

      1、加鎖操作簡單,使用SET、GET、DEL等幾條簡單命令即可實現鎖的獲取和釋放。

      2、性能優越,緩存數據的讀寫優于磁盤數據庫與Zookeeper。

      3、可靠性強,DCS有主備和集群實例類型,避免單點故障。

      以上代碼實現僅展示使用DCS服務進行加鎖訪問的便捷性,具體技術實現需要考慮死鎖、鎖的檢查等情況,歡迎點擊分布式緩存服務DCS了解更多。

      Redis 分布式緩存服務

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何把公司信紙設置成默認的模板(公司信紙樣式)
      下一篇:《Office 2019高效辦公三合一從入門到精通 : 視頻自學版》 —2.2.4查找和替換文本
      相關文章
      亚洲AV无码精品无码麻豆| 亚洲AV无码一区二区大桥未久| 亚洲AV无码不卡在线播放| 亚洲网站在线免费观看| 亚洲va乱码一区二区三区| 国产成人亚洲精品蜜芽影院| 国产成人毛片亚洲精品| 亚洲av日韩av高潮潮喷无码| 亚洲国语精品自产拍在线观看 | 亚洲AV无码专区在线播放中文| 亚洲人成人网站色www| 亚洲伦乱亚洲h视频| 亚洲理论片在线观看| 亚洲精品无码久久千人斩| 国产亚洲色婷婷久久99精品91| 亚洲AV无码国产精品色| 亚洲国产成人爱av在线播放| jizzjizz亚洲日本少妇| 亚洲精品国产自在久久| 亚洲AV无码一区二区二三区入口 | 国产精品亚洲一区二区无码| 亚洲AV永久精品爱情岛论坛| 久久狠狠爱亚洲综合影院| 亚洲人成77777在线播放网站| 国产精品久久久久久亚洲小说| 精品亚洲AV无码一区二区| 久久精品国产亚洲av天美18| 亚洲一区二区三区国产精品无码| 国产精品亚洲片在线花蝴蝶| 亚洲成A∨人片在线观看不卡| 久久久久亚洲国产| 亚洲女久久久噜噜噜熟女| 国产AV无码专区亚洲AVJULIA| 亚洲AV无码专区国产乱码4SE | 国产精品亚洲自在线播放页码| 亚洲AV无码乱码在线观看性色扶| 午夜亚洲AV日韩AV无码大全| 亚洲无码一区二区三区| 亚洲无线电影官网| 亚洲另类少妇17p| 国产av无码专区亚洲av毛片搜 |