先須要下載 curator 的依賴包java
curator-frameworkapache
curator-recipesbash
Guava-14.0.1服務器
在分佈式環境中,爲了保證數據的一致性,常常在程序的某個運行點須要進行同步控制。併發
import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch; 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; import com.google.common.cache.CacheBuilder; class DistributedLock { static String lock_path = "/curator_recipes_lock_path"; static CuratorFramework client = CuratorFrameworkFactory.builder() .connectString("202.201.13.*:2100") .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build(); public static void main(String[] args) throws Exception { client.start(); final InterProcessMutex lock = new InterProcessMutex(client, lock_path); final CountDownLatch down = new CountDownLatch(1); for(int i = 0; i < 10; i++){ new Thread(new Runnable() { public void run() { try { down.await(); lock.acquire(); } catch ( Exception e ) {} SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss|SSS"); String orderNo = sdf.format(new Date()); System.out.println("生成的訂單號是: " + orderNo); try { lock.release(); } catch ( Exception e ) {} } }).start(); } down.countDown(); } }
CountDownLatch
類是一個同步計數器,每調用一次countDown()方法,計數器減1,計數器大於0 時,await()方法會阻塞程序繼續執行。它是一個倒計數的鎖存器,當計數減至0時觸發特定的事件。利用這種特性,可讓主線程等待子線程的結束。maven
在這裏的做用是讓 10 個子進程先阻塞在一個 down.await()
,以便後面模擬高併發。父進程一旦執行 down.countDown()
,10 個子進程開始搶鎖。分佈式
而爲了讓 10 個子進程不形成資源競爭,須要使用 InterProcessLock
進行同步。高併發
public interface InterProcessLock -public void acquire() throws Exception; -public void release() throws Exception;
打印結果ui
生成的訂單號是: 21:06:29|951 生成的訂單號是: 21:06:29|981 生成的訂單號是: 21:06:30|007 生成的訂單號是: 21:06:30|023 生成的訂單號是: 21:06:30|039 生成的訂單號是: 21:06:30|062 生成的訂單號是: 21:06:30|076 生成的訂單號是: 21:06:30|096 生成的訂單號是: 21:06:30|107 生成的訂單號是: 21:06:30|148
分佈式計數器能夠用來統計系統的在線人數。思路是指定一個 ZooKeeper 節點做爲計數器,多個應用實例在分佈式鎖的控制下,遞增數據節點的計數值。google
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.atomic.AtomicValue; import org.apache.curator.framework.recipes.atomic.DistributedAtomicInteger; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.retry.RetryNTimes; class Recipes_DisAtomicInt { static String distatomicint_path = "/curator_recipes_distatomicint_path"; static CuratorFramework client = CuratorFrameworkFactory.builder() .connectString("202.201.13.*:2100") .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build(); public static void main(String[] args) throws Exception { client.start(); DistributedAtomicInteger atomicInterger = new DistributedAtomicInteger( client, distatomicint_path, new RetryNTimes(3, 1000)); AtomicValue<Integer> rc = atomicInterger.add(1); System.out.println("Result: " + rc.succeeded()); } }
使用客戶端腳原本鏈接服務器查看計數值
bash zkCli.sh -server 127.0.0.1:2100
能夠看到節點數據從 1A 增到 1B。