簡介
在分布式環境下,為了防止多個服務同時修改同一個值,出現數據同步問題,通常用redis和zookeeper做分布式鎖,在這里我們用zookeeper做分布式鎖,並和單點環境中ReenTranLock鎖相比較
1、ReenTranLock
package bjsxt.curator.lock; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.ReentrantLock; public class Lock1 { static ReentrantLock reentrantLock = new ReentrantLock(); static int count = 10; public static void genarNo(){ try { reentrantLock.lock(); count--; System.out.println(count); } finally { reentrantLock.unlock(); } } public static void main(String[] args) throws Exception{ final CountDownLatch countdown = new CountDownLatch(1); for(int i = 0; i < 10; i++){ new Thread(new Runnable() { @Override public void run() { try { countdown.await(); genarNo(); } catch (Exception e) { e.printStackTrace(); } finally { } } },"t" + i).start(); } Thread.sleep(50); countdown.countDown(); } }
- 結果
9 8 7 6 5 4 3 2 1 0
- 說明
- 本類開啟了十個線程,來操作count值,從結果可以看出是線程安全的
2、zookeeper分布鎖InterProcessMutex
package bjsxt.curator.lock; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch; 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; public class Lock2 { /** zookeeper地址 */ static final String CONNECT_ADDR = "192.168.0.4:2181,192.168.0.9:2181,192.168.0.6:2181"; /** session超時時間 */ static final int SESSION_OUTTIME = 5000; static int count = 10; public static void genarNo(){ try { count--; System.out.println(count); } finally { } } public static void main(String[] args) throws Exception { //1 重試策略:初試時間為1s 重試10次 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10); //2 通過工廠創建連接 CuratorFramework cf = CuratorFrameworkFactory.builder() .connectString(CONNECT_ADDR) .sessionTimeoutMs(SESSION_OUTTIME) .retryPolicy(retryPolicy) // .namespace("super") .build(); //3 開啟連接 cf.start(); //4 分布式鎖 final InterProcessMutex lock = new InterProcessMutex(cf, "/super"); final CountDownLatch countdown = new CountDownLatch(1); for(int i = 0; i < 10; i++){ new Thread(new Runnable() { @Override public void run() { try { countdown.await(); //加鎖 lock.acquire(); //-------------業務處理開始 genarNo(); //-------------業務處理結束 } catch (Exception e) { e.printStackTrace(); } finally { try { //釋放 lock.release(); } catch (Exception e) { e.printStackTrace(); } } } },"t" + i).start(); } Thread.sleep(100); countdown.countDown(); } }
- 結果
-
9 8 7 6 5 4 3 2 1 0
說明:
- 本類用InterProcessMutex做分布式鎖,通過zookeeper節點不能重復的原理來讓分布式環境的服務排隊處理同一個數據