【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀
1. Zookeeper簡述
????我們要了解一樣技術,首先應該要到它的官網,因為官網的信息一般都是最準確的,如下圖是Zookeeper官網對它的介紹。
? ? 從官網的介紹中,可以總結出,Zookeeper是一個集中式服務,它能夠實現高度可靠的分布式協調,可用于開發和維護開源服務器。
? ? 除了官網的解釋外,我的觀點是還可以這樣理解。它也相當于是一個數據庫,具有數據同步和選舉功能,能夠用來存儲一些信息,可用于解決大數據集群的單點故障問題。Zookeeper有leader和follow兩種角色,當leader的節點宕掉之后,會自動選舉出新的leader,如果只剩一個節點活著,就是standalone狀態。Zookeeper各個節點之間的數據會自動同步,比如在Zookeeper集群的A節點存儲數據,那么這份數據也會自動拷貝到集群中另外的節點上。在Hadoop、Storm、Spark集群都可以使用Zookeeper實現高可用(HA),防止出現單點故障。
2. 為什么要加鎖
? ? 在多線程編程中,必須要考慮到線程安全問題,當共享數據被高并發訪問時,會破壞數據的一致性。比如搶購商品,商品數量為1,有兩個用戶(線程)同時對它進行訪問,當第一個線程拿到數據,還沒有對數量執行減1操作的這段時間,第二個線程在這個時間段也拿到了數據,兩個線程都對商品數量進行減1操作的話,就會出現商品數量是 -1 的數據,就違背了實際原則。
????因此,在程序中引入了鎖,在線程訪問共享數據之前,首先要請求鎖,當得到這把鎖的時候,才能夠訪問共享數據,使用完以后再歸還這把鎖。如果鎖已經被一個線程獲取,其它線程就請求不到鎖,就執行重試策略,進入等待狀態,不會訪問共享數據,也就保證了數據的一致性。
3. 編程實戰
?3.1 原理
? 3.2 實現
????3.2.1 代碼
????????(1) 創建Maven項目,并在pom文件中加入以下依賴
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-client</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.6</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>16.0.1</version></dependency> </dependencies>?
? ??????(2) Product.java
package com.nova; /*** * @author Supernova* @date 2018/06/16**/ public class Product {// 商品數量,這里默認共有8件商品private static int number = 5;public static int getNumber() {return number;}public static void setNumber(int number) {Product.number = number;}}?
? ? ? ? (2) Client.java
package com.nova;import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.locks.InterProcessMutex; import org.apache.curator.retry.ExponentialBackoffRetry; /*** * @author Supernova* @date 2018/06/16**/ public class Client {/** 搶購商品的方法 * 作用:訪問共享資源,獲取并更新商品數量*/public static void buy() {System.out.println("--------【"+Thread.currentThread().getName()+"】開始購買-------");//獲取商品數量int currentNumber = Product.getNumber();/** 如果商品數量為0,則不能購買* 如果還有商品,則執行購買操作*/if(currentNumber == 0 ) {System.out.println("商品已被搶空!!!");}else {System.out.println("當前商品數量:"+currentNumber);//購買后商品數量減1currentNumber--;Product.setNumber(currentNumber);//為了便于觀察程序的運行結果,這里使線程在執行購買操作后,停頓3秒try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("--------【"+Thread.currentThread().getName()+"】 購買結束-------");}public static void main(String[] args) {/** 定義重試策略:等待2秒,重試10次* 第一個參數:等待時間* 第二個參數:重試次數*/RetryPolicy policy = new ExponentialBackoffRetry(2000, 10);/** 創建客戶端向zookeeper請求鎖* connectString() : zookeeper地址* retryPolicy() : 重試策略*/CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString("192.168.243.11").retryPolicy(policy).build();//啟用 curatorFramework.start();//獲取zookeeper鎖的信息final InterProcessMutex mutex = new InterProcessMutex(curatorFramework, "/myMutex");/** 創建8個線程模擬8個客戶端并發訪問* */for (int i = 0; i < 8; i++) {new Thread(new Runnable() {public void run() {try {//請求鎖資源,如果沒有得到鎖資源,就會執行重試策略 mutex.acquire();//開始訪問共享資源,這里是訪問商品信息 buy();} catch (Exception e) {e.printStackTrace();}finally {try {//將鎖歸還 mutex.release();} catch (Exception e) {e.printStackTrace();}}}}).start();}} }?
?
????3.2.2 運行測試
?(1) 啟動Zookeeper。通過Putty連接VM的Linux系統,我是在Hadoop偽分布的機器上啟動的Zookeeper,只啟動一個Zookeeper節點,因此是standalone的狀態。?????? ??
? ??????(2) 運行Java程序,程序運行結果如下圖
????????
? ? 可以看到運行的結果是線程安全的,只有在一個線程購買商品操作結束后,另一個線程才能接著購買。保證了數據的一致性。那么,如果去掉鎖的情況是如何的呢?
? ? (3) 將請求鎖的代碼mutex.acquire();和mutex.release();注釋掉之后。運行結果如下:
????????
? ? 從運行結果可以看出,如果沒有鎖的限制,程序運行的結果將會混亂。
??
轉載于:https://www.cnblogs.com/snova/p/9195689.html
總結
以上是生活随笔為你收集整理的【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js中闭包的概念和用法
- 下一篇: 关于一些blog优化