zookeeper分布式鎖實現秒殺案例(jfinal框架)

ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。

ZooKeeper的架構通過冗余服務實現高可用性。因此,如果第一次無應答,客戶端就可以詢問另一臺ZooKeeper主機。ZooKeeper節點將它們的數據存儲于一個分層的命名空間,非常類似于一個文件系統或一個前綴樹結構。客戶端可以在節點讀寫,從而以這種方式擁有一個共享的配置服務。更新是全序的。

基于ZooKeeper分布式鎖的流程

在zookeeper指定節點(locks)下創建臨時順序節點node_n

獲取locks下所有子節點children

對子節點按節點自增序號從小到大排序

判斷本節點是不是第一個子節點,若是,則獲取鎖;若不是,則監聽比該節點小的那個節點的刪除事件

若監聽事件生效,則回到第二步重新進行判斷,直到獲取到鎖

具體實現

下面就具體使用java和zookeeper實現分布式鎖,操作zookeeper使用的是apache提供的zookeeper的包。


通過實現Watch接口,實現process(WatchedEvent event)方法來實施監控,使CountDownLatch來完成監控,在等待鎖的時候使用CountDownLatch來計數,等到后進行countDown,停止等待,繼續運行。

以下整體流程基本與上述描述流程一致,只是在監聽的時候使用的是CountDownLatch來監聽前一個節點。


下邊來看簡單的實現源碼,不用在乎代碼的質量,這里只是簡單地做個演示!!!

分布式鎖:

import org.apache.zookeeper.*;

import org.apache.zookeeper.data.Stat;

import java.io.IOException;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

/**

* Created by liuyang on 2017/4/20.

*/

public class DistributedLock implements Lock, Watcher {

? ? private ZooKeeper zk = null;

? ? // 根節點

? ? private String ROOT_LOCK = "/locks";

? ? // 競爭的資源

? ? private String lockName;

? ? // 等待的前一個鎖

? ? private String WAIT_LOCK;

? ? // 當前鎖

? ? private String CURRENT_LOCK;

? ? // 計數器

? ? private CountDownLatch countDownLatch;

? ? private int sessionTimeout = 30000;

? ? private List<Exception> exceptionList = new ArrayList<Exception>();

? ? /**

? ? * 配置分布式鎖

? ? * @param config 連接的url

? ? * @param lockName 競爭資源

? ? */

? ? public DistributedLock(String config, String lockName) {

? ? ? ? this.lockName = lockName;

? ? ? ? try {

? ? ? ? ? ? // 連接zookeeper

? ? ? ? ? ? zk = new ZooKeeper(config, sessionTimeout, this);

? ? ? ? ? ? Stat stat = zk.exists(ROOT_LOCK, false);

? ? ? ? ? ? if (stat == null) {

? ? ? ? ? ? ? ? // 如果根節點不存在,則創建根節點

? ? ? ? ? ? ? ? zk.create(ROOT_LOCK, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

? ? ? ? ? ? }

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (KeeperException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

? ? // 節點監視器

? ? public void process(WatchedEvent event) {

? ? ? ? if (this.countDownLatch != null) {

? ? ? ? ? ? this.countDownLatch.countDown();

? ? ? ? }

? ? }

? ? public void lock() {

? ? ? ? if (exceptionList.size() > 0) {

? ? ? ? ? ? throw new LockException(exceptionList.get(0));

? ? ? ? }

? ? ? ? try {

? ? ? ? ? ? if (this.tryLock()) {

? ? ? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + " " + lockName + "獲得了鎖");

? ? ? ? ? ? ? ? return;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? // 等待鎖

? ? ? ? ? ? ? ? waitForLock(WAIT_LOCK, sessionTimeout);

? ? ? ? ? ? }

? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (KeeperException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

? ? public boolean tryLock() {

? ? ? ? try {

? ? ? ? ? ? String splitStr = "_lock_";

? ? ? ? ? ? if (lockName.contains(splitStr)) {

? ? ? ? ? ? ? ? throw new LockException("鎖名有誤");

? ? ? ? ? ? }

? ? ? ? ? ? // 創建臨時有序節點

? ? ? ? ? ? CURRENT_LOCK = zk.create(ROOT_LOCK + "/" + lockName + splitStr, new byte[0],

? ? ? ? ? ? ? ? ? ? ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

? ? ? ? ? ? System.out.println(CURRENT_LOCK + " 已經創建");

? ? ? ? ? ? // 取所有子節點

? ? ? ? ? ? List<String> subNodes = zk.getChildren(ROOT_LOCK, false);

? ? ? ? ? ? // 取出所有lockName的鎖

? ? ? ? ? ? List<String> lockObjects = new ArrayList<String>();

? ? ? ? ? ? for (String node : subNodes) {

? ? ? ? ? ? ? ? String _node = node.split(splitStr)[0];

? ? ? ? ? ? ? ? if (_node.equals(lockName)) {

? ? ? ? ? ? ? ? ? ? lockObjects.add(node);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? Collections.sort(lockObjects);

? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + " 的鎖是 " + CURRENT_LOCK);

? ? ? ? ? ? // 若當前節點為最小節點,則獲取鎖成功

? ? ? ? ? ? if (CURRENT_LOCK.equals(ROOT_LOCK + "/" + lockObjects.get(0))) {

? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? }

? ? ? ? ? ? // 若不是最小節點,則找到自己的前一個節點

? ? ? ? ? ? String prevNode = CURRENT_LOCK.substring(CURRENT_LOCK.lastIndexOf("/") + 1);

? ? ? ? ? ? WAIT_LOCK = lockObjects.get(Collections.binarySearch(lockObjects, prevNode) - 1);

? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (KeeperException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? ? ? return false;

? ? }

? ? public boolean tryLock(long timeout, TimeUnit unit) {

? ? ? ? try {

? ? ? ? ? ? if (this.tryLock()) {

? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? }

? ? ? ? ? ? return waitForLock(WAIT_LOCK, timeout);

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? ? ? return false;

? ? }

? ? // 等待鎖

? ? private boolean waitForLock(String prev, long waitTime) throws KeeperException, InterruptedException {

? ? ? ? Stat stat = zk.exists(ROOT_LOCK + "/" + prev, true);

? ? ? ? if (stat != null) {

? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + "等待鎖 " + ROOT_LOCK + "/" + prev);

? ? ? ? ? ? this.countDownLatch = new CountDownLatch(1);

? ? ? ? ? ? // 計數等待,若等到前一個節點消失,則precess中進行countDown,停止等待,獲取鎖

? ? ? ? ? ? this.countDownLatch.await(waitTime, TimeUnit.MILLISECONDS);

? ? ? ? ? ? this.countDownLatch = null;

? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + " 等到了鎖");

? ? ? ? }

? ? ? ? return true;

? ? }

? ? public void unlock() {

? ? ? ? try {

? ? ? ? ? ? System.out.println("釋放鎖 " + CURRENT_LOCK);

? ? ? ? ? ? zk.delete(CURRENT_LOCK, -1);

? ? ? ? ? ? CURRENT_LOCK = null;

? ? ? ? ? ? zk.close();

? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (KeeperException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

? ? public Condition newCondition() {

? ? ? ? return null;

? ? }

? ? public void lockInterruptibly() throws InterruptedException {

? ? ? ? this.lock();

? ? }

? ? public class LockException extends RuntimeException {

? ? ? ? private static final long serialVersionUID = 1L;

? ? ? ? public LockException(String e){

? ? ? ? ? ? super(e);

? ? ? ? }

? ? ? ? public LockException(Exception e){

? ? ? ? ? ? super(e);

? ? ? ? }

? ? }

}

入口類:

39?號人?獲取鎖:/locks/test1_lock_0000001385?搶到了第1?件商品;

釋放鎖?/locks/test1_lock_0000001385

35?號人?獲取鎖:/locks/test1_lock_0000001386?搶到了第2?件商品;

釋放鎖?/locks/test1_lock_0000001386

25?號人?獲取鎖:/locks/test1_lock_0000001387?搶到了第3?件商品;

釋放鎖?/locks/test1_lock_0000001387

42?號人?獲取鎖:/locks/test1_lock_0000001388?搶到了第4?件商品;

釋放鎖?/locks/test1_lock_0000001388

19?號人?獲取鎖:/locks/test1_lock_0000001389?搶到了第5?件商品;

釋放鎖?/locks/test1_lock_0000001389

38?號人?獲取鎖:/locks/test1_lock_0000001390?搶到了第6?件商品;

釋放鎖?/locks/test1_lock_0000001390

22?號人?獲取鎖:/locks/test1_lock_0000001391?搶到了第7?件商品;

釋放鎖?/locks/test1_lock_0000001391

18?號人?獲取鎖:/locks/test1_lock_0000001392?搶到了第8?件商品;

釋放鎖?/locks/test1_lock_0000001392

27?號人?獲取鎖:/locks/test1_lock_0000001393?搶到了第9?件商品;

釋放鎖?/locks/test1_lock_0000001393

28?號人?獲取鎖:/locks/test1_lock_0000001394?搶到了第10?件商品;

釋放鎖?/locks/test1_lock_0000001394

2?號人?獲取鎖:/locks/test1_lock_0000001395?搶到了第11?件商品;

釋放鎖?/locks/test1_lock_0000001395

14?號人?獲取鎖:/locks/test1_lock_0000001396?搶到了第12?件商品;

釋放鎖?/locks/test1_lock_0000001396

20?號人?獲取鎖:/locks/test1_lock_0000001397?搶到了第13?件商品;

釋放鎖?/locks/test1_lock_0000001397

11?號人?獲取鎖:/locks/test1_lock_0000001398?搶到了第14?件商品;

釋放鎖?/locks/test1_lock_0000001398

6?號人?獲取鎖:/locks/test1_lock_0000001399?搶到了第15?件商品;

釋放鎖?/locks/test1_lock_0000001399

7?號人?獲取鎖:/locks/test1_lock_0000001400?搶到了第16?件商品;

釋放鎖?/locks/test1_lock_0000001400

29?號人?獲取鎖:/locks/test1_lock_0000001401?搶到了第17?件商品;

釋放鎖?/locks/test1_lock_0000001401

3?號人?獲取鎖:/locks/test1_lock_0000001402?搶到了第18?件商品;

釋放鎖?/locks/test1_lock_0000001402

8?號人?獲取鎖:/locks/test1_lock_0000001403?搶到了第19?件商品;

釋放鎖?/locks/test1_lock_0000001403

32?號人?獲取鎖:/locks/test1_lock_0000001404?搶到了第20?件商品;

釋放鎖?/locks/test1_lock_0000001404

33?號人?獲取鎖:/locks/test1_lock_0000001405?搶到了第21?件商品;

釋放鎖?/locks/test1_lock_0000001405

23?號人?獲取鎖:/locks/test1_lock_0000001406?搶到了第22?件商品;

釋放鎖?/locks/test1_lock_0000001406

12?號人?獲取鎖:/locks/test1_lock_0000001407?搶到了第23?件商品;

釋放鎖?/locks/test1_lock_0000001407

15?號人?獲取鎖:/locks/test1_lock_0000001408?搶到了第24?件商品;

釋放鎖?/locks/test1_lock_0000001408

13?號人?獲取鎖:/locks/test1_lock_0000001409?搶到了第25?件商品;

釋放鎖?/locks/test1_lock_0000001409

34?號人?獲取鎖:/locks/test1_lock_0000001410?搶到了第26?件商品;

釋放鎖?/locks/test1_lock_0000001410

41?號人?獲取鎖:/locks/test1_lock_0000001411?搶到了第27?件商品;

釋放鎖?/locks/test1_lock_0000001411

37?號人?獲取鎖:/locks/test1_lock_0000001412?搶到了第28?件商品;

釋放鎖?/locks/test1_lock_0000001412

1?號人?獲取鎖:/locks/test1_lock_0000001413?搶到了第29?件商品;

釋放鎖?/locks/test1_lock_0000001413

52?號人?獲取鎖:/locks/test1_lock_0000001414?搶到了第30?件商品;

釋放鎖?/locks/test1_lock_0000001414

56?號人?獲取鎖:/locks/test1_lock_0000001415?搶到了第31?件商品;

釋放鎖?/locks/test1_lock_0000001415

26?號人?獲取鎖:/locks/test1_lock_0000001416?搶到了第32?件商品;

釋放鎖?/locks/test1_lock_0000001416

17?號人?獲取鎖:/locks/test1_lock_0000001417?搶到了第33?件商品;

釋放鎖?/locks/test1_lock_0000001417

40?號人?獲取鎖:/locks/test1_lock_0000001418?搶到了第34?件商品;

釋放鎖?/locks/test1_lock_0000001418

4?號人?獲取鎖:/locks/test1_lock_0000001419?搶到了第35?件商品;

釋放鎖?/locks/test1_lock_0000001419

46?號人?獲取鎖:/locks/test1_lock_0000001420?搶到了第36?件商品;

釋放鎖?/locks/test1_lock_0000001420

5?號人?獲取鎖:/locks/test1_lock_0000001421?搶到了第37?件商品;

釋放鎖?/locks/test1_lock_0000001421

54?號人?獲取鎖:/locks/test1_lock_0000001422?搶到了第38?件商品;

釋放鎖?/locks/test1_lock_0000001422

24?號人?獲取鎖:/locks/test1_lock_0000001423?搶到了第39?件商品;

釋放鎖?/locks/test1_lock_0000001423

48?號人?獲取鎖:/locks/test1_lock_0000001424?搶到了第40?件商品;

釋放鎖?/locks/test1_lock_0000001424

50?號人?獲取鎖:/locks/test1_lock_0000001425?搶到了第41?件商品;

釋放鎖?/locks/test1_lock_0000001425

21?號人?獲取鎖:/locks/test1_lock_0000001426?搶到了第42?件商品;

釋放鎖?/locks/test1_lock_0000001426

49?號人?獲取鎖:/locks/test1_lock_0000001427?搶到了第43?件商品;

釋放鎖?/locks/test1_lock_0000001427

36?號人?獲取鎖:/locks/test1_lock_0000001428?搶到了第44?件商品;

釋放鎖?/locks/test1_lock_0000001428

43?號人?獲取鎖:/locks/test1_lock_0000001429?搶到了第45?件商品;

釋放鎖?/locks/test1_lock_0000001429

44?號人?獲取鎖:/locks/test1_lock_0000001430?搶到了第46?件商品;

釋放鎖?/locks/test1_lock_0000001430

30?號人?獲取鎖:/locks/test1_lock_0000001431?搶到了第47?件商品;

釋放鎖?/locks/test1_lock_0000001431

47?號人?獲取鎖:/locks/test1_lock_0000001432?搶到了第48?件商品;

釋放鎖?/locks/test1_lock_0000001432

10?號人?獲取鎖:/locks/test1_lock_0000001433?搶到了第49?件商品;

釋放鎖?/locks/test1_lock_0000001433

9?號人?獲取鎖:/locks/test1_lock_0000001434?搶到了第50?件商品;

釋放鎖?/locks/test1_lock_0000001434

51?號人?獲取鎖:/locks/test1_lock_0000001435?搶到了第51?件商品;

釋放鎖?/locks/test1_lock_0000001435

31?號人?獲取鎖:/locks/test1_lock_0000001436?搶到了第52?件商品;

釋放鎖?/locks/test1_lock_0000001436

16?號人?獲取鎖:/locks/test1_lock_0000001437?搶到了第53?件商品;

釋放鎖?/locks/test1_lock_0000001437

45?號人?獲取鎖:/locks/test1_lock_0000001438?搶到了第54?件商品;

釋放鎖?/locks/test1_lock_0000001438

55?號人?獲取鎖:/locks/test1_lock_0000001439?搶到了第55?件商品;

釋放鎖?/locks/test1_lock_0000001439

53?號人?獲取鎖:/locks/test1_lock_0000001440?搶到了第56?件商品;

釋放鎖?/locks/test1_lock_0000001440

61?號人?獲取鎖:/locks/test1_lock_0000001441?搶到了第57?件商品;

釋放鎖?/locks/test1_lock_0000001441

59?號人?獲取鎖:/locks/test1_lock_0000001442?搶到了第58?件商品;

釋放鎖?/locks/test1_lock_0000001442

58?號人?獲取鎖:/locks/test1_lock_0000001443?搶到了第59?件商品;

釋放鎖?/locks/test1_lock_0000001443

57?號人?獲取鎖:/locks/test1_lock_0000001444?搶到了第60?件商品;

釋放鎖?/locks/test1_lock_0000001444

60?號人?獲取鎖:/locks/test1_lock_0000001445?搶到了第61?件商品;

釋放鎖?/locks/test1_lock_0000001445

92?號人?獲取鎖:/locks/test1_lock_0000001446?搶到了第62?件商品;

釋放鎖?/locks/test1_lock_0000001446

95?號人?獲取鎖:/locks/test1_lock_0000001447?搶到了第63?件商品;

釋放鎖?/locks/test1_lock_0000001447

94?號人?獲取鎖:/locks/test1_lock_0000001448?搶到了第64?件商品;

釋放鎖?/locks/test1_lock_0000001448

96?號人?獲取鎖:/locks/test1_lock_0000001449?搶到了第65?件商品;

釋放鎖?/locks/test1_lock_0000001449

98?號人?獲取鎖:/locks/test1_lock_0000001450?搶到了第66?件商品;

釋放鎖?/locks/test1_lock_0000001450

100?號人?獲取鎖:/locks/test1_lock_0000001451?搶到了第67?件商品;

釋放鎖?/locks/test1_lock_0000001451

101?號人?獲取鎖:/locks/test1_lock_0000001452?搶到了第68?件商品;

釋放鎖?/locks/test1_lock_0000001452

102?號人?獲取鎖:/locks/test1_lock_0000001453?搶到了第69?件商品;

釋放鎖?/locks/test1_lock_0000001453

104?號人?獲取鎖:/locks/test1_lock_0000001454?搶到了第70?件商品;

釋放鎖?/locks/test1_lock_0000001454

117?號人?獲取鎖:/locks/test1_lock_0000001455?搶到了第71?件商品;

釋放鎖?/locks/test1_lock_0000001455

116?號人?獲取鎖:/locks/test1_lock_0000001456?搶到了第72?件商品;

釋放鎖?/locks/test1_lock_0000001456

113?號人?獲取鎖:/locks/test1_lock_0000001457?搶到了第73?件商品;

釋放鎖?/locks/test1_lock_0000001457

119?號人?獲取鎖:/locks/test1_lock_0000001458?搶到了第74?件商品;

釋放鎖?/locks/test1_lock_0000001458

120?號人?獲取鎖:/locks/test1_lock_0000001459?搶到了第75?件商品;

釋放鎖?/locks/test1_lock_0000001459

111?號人?獲取鎖:/locks/test1_lock_0000001460?搶到了第76?件商品;

釋放鎖?/locks/test1_lock_0000001460

115?號人?獲取鎖:/locks/test1_lock_0000001461?搶到了第77?件商品;

釋放鎖?/locks/test1_lock_0000001461

107?號人?獲取鎖:/locks/test1_lock_0000001462?搶到了第78?件商品;

釋放鎖?/locks/test1_lock_0000001462

114?號人?獲取鎖:/locks/test1_lock_0000001463?搶到了第79?件商品;

釋放鎖?/locks/test1_lock_0000001463

109?號人?獲取鎖:/locks/test1_lock_0000001464?搶到了第80?件商品;

釋放鎖?/locks/test1_lock_0000001464

63?號人?獲取鎖:/locks/test1_lock_0000001465?搶到了第81?件商品;

釋放鎖?/locks/test1_lock_0000001465

62?號人?獲取鎖:/locks/test1_lock_0000001466?搶到了第82?件商品;

釋放鎖?/locks/test1_lock_0000001466

88?號人?獲取鎖:/locks/test1_lock_0000001467?搶到了第83?件商品;

釋放鎖?/locks/test1_lock_0000001467

81?號人?獲取鎖:/locks/test1_lock_0000001468?搶到了第84?件商品;

釋放鎖?/locks/test1_lock_0000001468

82?號人?獲取鎖:/locks/test1_lock_0000001469?搶到了第85?件商品;

釋放鎖?/locks/test1_lock_0000001469

87?號人?獲取鎖:/locks/test1_lock_0000001470?搶到了第86?件商品;

釋放鎖?/locks/test1_lock_0000001470

64?號人?獲取鎖:/locks/test1_lock_0000001471?搶到了第87?件商品;

釋放鎖?/locks/test1_lock_0000001471

84?號人?獲取鎖:/locks/test1_lock_0000001472?搶到了第88?件商品;

釋放鎖?/locks/test1_lock_0000001472

68?號人?獲取鎖:/locks/test1_lock_0000001473?搶到了第89?件商品;

釋放鎖?/locks/test1_lock_0000001473

67?號人?獲取鎖:/locks/test1_lock_0000001474?搶到了第90?件商品;

釋放鎖?/locks/test1_lock_0000001474

99?號人?獲取鎖:/locks/test1_lock_0000001475?搶到了第91?件商品;

釋放鎖?/locks/test1_lock_0000001475

78?號人?獲取鎖:/locks/test1_lock_0000001476?搶到了第92?件商品;

釋放鎖?/locks/test1_lock_0000001476

73?號人?獲取鎖:/locks/test1_lock_0000001477?搶到了第93?件商品;

釋放鎖?/locks/test1_lock_0000001477

71?號人?獲取鎖:/locks/test1_lock_0000001478?搶到了第94?件商品;

釋放鎖?/locks/test1_lock_0000001478

83?號人?獲取鎖:/locks/test1_lock_0000001479?搶到了第95?件商品;

釋放鎖?/locks/test1_lock_0000001479

91?號人?獲取鎖:/locks/test1_lock_0000001480?搶到了第96?件商品;

釋放鎖?/locks/test1_lock_0000001480

90?號人?獲取鎖:/locks/test1_lock_0000001481?搶到了第97?件商品;

釋放鎖?/locks/test1_lock_0000001481

65?號人?獲取鎖:/locks/test1_lock_0000001482?搶到了第98?件商品;

釋放鎖?/locks/test1_lock_0000001482

77?號人?獲取鎖:/locks/test1_lock_0000001483?搶到了第99?件商品;

釋放鎖?/locks/test1_lock_0000001483

76?號人?獲取鎖:/locks/test1_lock_0000001484?搶到了第100?件商品;

釋放鎖?/locks/test1_lock_0000001484

釋放鎖?/locks/test1_lock_0000001485

75?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001486

69?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001487

89?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001488

105?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001489

85?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001490

74?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001491

66?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001492

112?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001493

釋放鎖?/locks/test1_lock_0000001494

釋放鎖?/locks/test1_lock_0000001495

70?號人?太悲劇了,沒搶到商品...

108?號人?太悲劇了,沒搶到商品...

79?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001496

釋放鎖?/locks/test1_lock_0000001497

93?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001498

106?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001499

103?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001500

釋放鎖?/locks/test1_lock_0000001501

72?號人?太悲劇了,沒搶到商品...

80?號人?太悲劇了,沒搶到商品...

118?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001502

86?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001503

97?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001504

110?號人?太悲劇了,沒搶到商品...

入口類:



package?com.demo.index;


import?com.demo.utils.DistributedLock;

import?com.jfinal.core.Controller;

import?com.jfinal.plugin.activerecord.Db;

import?com.jfinal.plugin.activerecord.Record;


/**

?*?秒殺/zookeeper?分布式鎖

?*?

?*?@author?sun

?*/

public?class?SecKillForZookeeperController?extends?Controller?{


????public?static?int?goodsTotalNum?=?100;


????public?void?index()?{

????????//每一次新的請求都會模擬搶購100件商品,所以先恢復商品的數量,這個可以不要,也可以手動去更新數據庫

????????Db.update("update?t_goods?set?num?=???where?id?=?1",?goodsTotalNum);


????????Record?goods?=?Db.findFirst("select?*?from?t_goods?where?id?=?1");

????????Integer?num?=?0;

????????if(goods!=null){

????????????num?=?goods.getInt("num");

????????}


????????SecKillZookeeper?sk?=?new?SecKillZookeeper(num);

????????//?模擬120個人搶購。?模擬120人分別在不同的服務器進行發起請求

????????for?(int?i?=?1;?i?<=?120;?i++)?{

????????????new?Thread(sk,?i?+?"?號人").start();

????????}


????????renderHtml("<center><h2>搶購成功!</h2></center>");

????}

}


/**

?*?這里我們只是簡單演示實現方式,至于事務等其他的都不添加了。

?*?

?*?@author?sun

?*/

class?SecKillZookeeper?implements?Runnable?{


????private?int?num?=?0;


????public?SecKillZookeeper(int?num)?{

????????this.num?=?num;

????}


????@Override

????public?void?run()?{

????????DistributedLock?lock?=?null;

????????try?{

????????????lock?=?new?DistributedLock("127.0.0.1:2181",?"test1");

????????????lock.lock();

????????????if?(num?>?0)?{

????????????????sale(lock);

????????????????return?;

????????????}

????????}?finally?{

????????????if?(lock?!=?null)?{

????????????????lock.unlock();

????????????}

????????}

????????System.err.println(Thread.currentThread().getName()?+?"?太悲劇了,沒搶到商品...");

????}


????private?void?sale(DistributedLock?lock)?{

????????if(num>0){

????????????Db.update("update?t_goods?set?num=num-1?where?id?=?1");

????????????num--;

????????????System.out.println(Thread.currentThread().getName()+"?獲取鎖:"+lock.CURRENT_LOCK+"?搶到了第"+(SecKillForZookeeperController.goodsTotalNum?-?num)+"?件商品;");

????????}

????}

}

打印結果:?

39?號人?獲取鎖:/locks/test1_lock_0000001385?搶到了第1?件商品;

釋放鎖?/locks/test1_lock_0000001385

35?號人?獲取鎖:/locks/test1_lock_0000001386?搶到了第2?件商品;

釋放鎖?/locks/test1_lock_0000001386

25?號人?獲取鎖:/locks/test1_lock_0000001387?搶到了第3?件商品;

釋放鎖?/locks/test1_lock_0000001387

42?號人?獲取鎖:/locks/test1_lock_0000001388?搶到了第4?件商品;

釋放鎖?/locks/test1_lock_0000001388

19?號人?獲取鎖:/locks/test1_lock_0000001389?搶到了第5?件商品;

釋放鎖?/locks/test1_lock_0000001389

38?號人?獲取鎖:/locks/test1_lock_0000001390?搶到了第6?件商品;

釋放鎖?/locks/test1_lock_0000001390

22?號人?獲取鎖:/locks/test1_lock_0000001391?搶到了第7?件商品;

釋放鎖?/locks/test1_lock_0000001391

18?號人?獲取鎖:/locks/test1_lock_0000001392?搶到了第8?件商品;

釋放鎖?/locks/test1_lock_0000001392

27?號人?獲取鎖:/locks/test1_lock_0000001393?搶到了第9?件商品;

釋放鎖?/locks/test1_lock_0000001393

28?號人?獲取鎖:/locks/test1_lock_0000001394?搶到了第10?件商品;

釋放鎖?/locks/test1_lock_0000001394

2?號人?獲取鎖:/locks/test1_lock_0000001395?搶到了第11?件商品;

釋放鎖?/locks/test1_lock_0000001395

14?號人?獲取鎖:/locks/test1_lock_0000001396?搶到了第12?件商品;

釋放鎖?/locks/test1_lock_0000001396

20?號人?獲取鎖:/locks/test1_lock_0000001397?搶到了第13?件商品;

釋放鎖?/locks/test1_lock_0000001397

11?號人?獲取鎖:/locks/test1_lock_0000001398?搶到了第14?件商品;

釋放鎖?/locks/test1_lock_0000001398

6?號人?獲取鎖:/locks/test1_lock_0000001399?搶到了第15?件商品;

釋放鎖?/locks/test1_lock_0000001399

7?號人?獲取鎖:/locks/test1_lock_0000001400?搶到了第16?件商品;

釋放鎖?/locks/test1_lock_0000001400

29?號人?獲取鎖:/locks/test1_lock_0000001401?搶到了第17?件商品;

釋放鎖?/locks/test1_lock_0000001401

3?號人?獲取鎖:/locks/test1_lock_0000001402?搶到了第18?件商品;

釋放鎖?/locks/test1_lock_0000001402

8?號人?獲取鎖:/locks/test1_lock_0000001403?搶到了第19?件商品;

釋放鎖?/locks/test1_lock_0000001403

32?號人?獲取鎖:/locks/test1_lock_0000001404?搶到了第20?件商品;

釋放鎖?/locks/test1_lock_0000001404

33?號人?獲取鎖:/locks/test1_lock_0000001405?搶到了第21?件商品;

釋放鎖?/locks/test1_lock_0000001405

23?號人?獲取鎖:/locks/test1_lock_0000001406?搶到了第22?件商品;

釋放鎖?/locks/test1_lock_0000001406

12?號人?獲取鎖:/locks/test1_lock_0000001407?搶到了第23?件商品;

釋放鎖?/locks/test1_lock_0000001407

15?號人?獲取鎖:/locks/test1_lock_0000001408?搶到了第24?件商品;

釋放鎖?/locks/test1_lock_0000001408

13?號人?獲取鎖:/locks/test1_lock_0000001409?搶到了第25?件商品;

釋放鎖?/locks/test1_lock_0000001409

34?號人?獲取鎖:/locks/test1_lock_0000001410?搶到了第26?件商品;

釋放鎖?/locks/test1_lock_0000001410

41?號人?獲取鎖:/locks/test1_lock_0000001411?搶到了第27?件商品;

釋放鎖?/locks/test1_lock_0000001411

37?號人?獲取鎖:/locks/test1_lock_0000001412?搶到了第28?件商品;

釋放鎖?/locks/test1_lock_0000001412

1?號人?獲取鎖:/locks/test1_lock_0000001413?搶到了第29?件商品;

釋放鎖?/locks/test1_lock_0000001413

52?號人?獲取鎖:/locks/test1_lock_0000001414?搶到了第30?件商品;

釋放鎖?/locks/test1_lock_0000001414

56?號人?獲取鎖:/locks/test1_lock_0000001415?搶到了第31?件商品;

釋放鎖?/locks/test1_lock_0000001415

26?號人?獲取鎖:/locks/test1_lock_0000001416?搶到了第32?件商品;

釋放鎖?/locks/test1_lock_0000001416

17?號人?獲取鎖:/locks/test1_lock_0000001417?搶到了第33?件商品;

釋放鎖?/locks/test1_lock_0000001417

40?號人?獲取鎖:/locks/test1_lock_0000001418?搶到了第34?件商品;

釋放鎖?/locks/test1_lock_0000001418

4?號人?獲取鎖:/locks/test1_lock_0000001419?搶到了第35?件商品;

釋放鎖?/locks/test1_lock_0000001419

46?號人?獲取鎖:/locks/test1_lock_0000001420?搶到了第36?件商品;

釋放鎖?/locks/test1_lock_0000001420

5?號人?獲取鎖:/locks/test1_lock_0000001421?搶到了第37?件商品;

釋放鎖?/locks/test1_lock_0000001421

54?號人?獲取鎖:/locks/test1_lock_0000001422?搶到了第38?件商品;

釋放鎖?/locks/test1_lock_0000001422

24?號人?獲取鎖:/locks/test1_lock_0000001423?搶到了第39?件商品;

釋放鎖?/locks/test1_lock_0000001423

48?號人?獲取鎖:/locks/test1_lock_0000001424?搶到了第40?件商品;

釋放鎖?/locks/test1_lock_0000001424

50?號人?獲取鎖:/locks/test1_lock_0000001425?搶到了第41?件商品;

釋放鎖?/locks/test1_lock_0000001425

21?號人?獲取鎖:/locks/test1_lock_0000001426?搶到了第42?件商品;

釋放鎖?/locks/test1_lock_0000001426

49?號人?獲取鎖:/locks/test1_lock_0000001427?搶到了第43?件商品;

釋放鎖?/locks/test1_lock_0000001427

36?號人?獲取鎖:/locks/test1_lock_0000001428?搶到了第44?件商品;

釋放鎖?/locks/test1_lock_0000001428

43?號人?獲取鎖:/locks/test1_lock_0000001429?搶到了第45?件商品;

釋放鎖?/locks/test1_lock_0000001429

44?號人?獲取鎖:/locks/test1_lock_0000001430?搶到了第46?件商品;

釋放鎖?/locks/test1_lock_0000001430

30?號人?獲取鎖:/locks/test1_lock_0000001431?搶到了第47?件商品;

釋放鎖?/locks/test1_lock_0000001431

47?號人?獲取鎖:/locks/test1_lock_0000001432?搶到了第48?件商品;

釋放鎖?/locks/test1_lock_0000001432

10?號人?獲取鎖:/locks/test1_lock_0000001433?搶到了第49?件商品;

釋放鎖?/locks/test1_lock_0000001433

9?號人?獲取鎖:/locks/test1_lock_0000001434?搶到了第50?件商品;

釋放鎖?/locks/test1_lock_0000001434

51?號人?獲取鎖:/locks/test1_lock_0000001435?搶到了第51?件商品;

釋放鎖?/locks/test1_lock_0000001435

31?號人?獲取鎖:/locks/test1_lock_0000001436?搶到了第52?件商品;

釋放鎖?/locks/test1_lock_0000001436

16?號人?獲取鎖:/locks/test1_lock_0000001437?搶到了第53?件商品;

釋放鎖?/locks/test1_lock_0000001437

45?號人?獲取鎖:/locks/test1_lock_0000001438?搶到了第54?件商品;

釋放鎖?/locks/test1_lock_0000001438

55?號人?獲取鎖:/locks/test1_lock_0000001439?搶到了第55?件商品;

釋放鎖?/locks/test1_lock_0000001439

53?號人?獲取鎖:/locks/test1_lock_0000001440?搶到了第56?件商品;

釋放鎖?/locks/test1_lock_0000001440

61?號人?獲取鎖:/locks/test1_lock_0000001441?搶到了第57?件商品;

釋放鎖?/locks/test1_lock_0000001441

59?號人?獲取鎖:/locks/test1_lock_0000001442?搶到了第58?件商品;

釋放鎖?/locks/test1_lock_0000001442

58?號人?獲取鎖:/locks/test1_lock_0000001443?搶到了第59?件商品;

釋放鎖?/locks/test1_lock_0000001443

57?號人?獲取鎖:/locks/test1_lock_0000001444?搶到了第60?件商品;

釋放鎖?/locks/test1_lock_0000001444

60?號人?獲取鎖:/locks/test1_lock_0000001445?搶到了第61?件商品;

釋放鎖?/locks/test1_lock_0000001445

92?號人?獲取鎖:/locks/test1_lock_0000001446?搶到了第62?件商品;

釋放鎖?/locks/test1_lock_0000001446

95?號人?獲取鎖:/locks/test1_lock_0000001447?搶到了第63?件商品;

釋放鎖?/locks/test1_lock_0000001447

94?號人?獲取鎖:/locks/test1_lock_0000001448?搶到了第64?件商品;

釋放鎖?/locks/test1_lock_0000001448

96?號人?獲取鎖:/locks/test1_lock_0000001449?搶到了第65?件商品;

釋放鎖?/locks/test1_lock_0000001449

98?號人?獲取鎖:/locks/test1_lock_0000001450?搶到了第66?件商品;

釋放鎖?/locks/test1_lock_0000001450

100?號人?獲取鎖:/locks/test1_lock_0000001451?搶到了第67?件商品;

釋放鎖?/locks/test1_lock_0000001451

101?號人?獲取鎖:/locks/test1_lock_0000001452?搶到了第68?件商品;

釋放鎖?/locks/test1_lock_0000001452

102?號人?獲取鎖:/locks/test1_lock_0000001453?搶到了第69?件商品;

釋放鎖?/locks/test1_lock_0000001453

104?號人?獲取鎖:/locks/test1_lock_0000001454?搶到了第70?件商品;

釋放鎖?/locks/test1_lock_0000001454

117?號人?獲取鎖:/locks/test1_lock_0000001455?搶到了第71?件商品;

釋放鎖?/locks/test1_lock_0000001455

116?號人?獲取鎖:/locks/test1_lock_0000001456?搶到了第72?件商品;

釋放鎖?/locks/test1_lock_0000001456

113?號人?獲取鎖:/locks/test1_lock_0000001457?搶到了第73?件商品;

釋放鎖?/locks/test1_lock_0000001457

119?號人?獲取鎖:/locks/test1_lock_0000001458?搶到了第74?件商品;

釋放鎖?/locks/test1_lock_0000001458

120?號人?獲取鎖:/locks/test1_lock_0000001459?搶到了第75?件商品;

釋放鎖?/locks/test1_lock_0000001459

111?號人?獲取鎖:/locks/test1_lock_0000001460?搶到了第76?件商品;

釋放鎖?/locks/test1_lock_0000001460

115?號人?獲取鎖:/locks/test1_lock_0000001461?搶到了第77?件商品;

釋放鎖?/locks/test1_lock_0000001461

107?號人?獲取鎖:/locks/test1_lock_0000001462?搶到了第78?件商品;

釋放鎖?/locks/test1_lock_0000001462

114?號人?獲取鎖:/locks/test1_lock_0000001463?搶到了第79?件商品;

釋放鎖?/locks/test1_lock_0000001463

109?號人?獲取鎖:/locks/test1_lock_0000001464?搶到了第80?件商品;

釋放鎖?/locks/test1_lock_0000001464

63?號人?獲取鎖:/locks/test1_lock_0000001465?搶到了第81?件商品;

釋放鎖?/locks/test1_lock_0000001465

62?號人?獲取鎖:/locks/test1_lock_0000001466?搶到了第82?件商品;

釋放鎖?/locks/test1_lock_0000001466

88?號人?獲取鎖:/locks/test1_lock_0000001467?搶到了第83?件商品;

釋放鎖?/locks/test1_lock_0000001467

81?號人?獲取鎖:/locks/test1_lock_0000001468?搶到了第84?件商品;

釋放鎖?/locks/test1_lock_0000001468

82?號人?獲取鎖:/locks/test1_lock_0000001469?搶到了第85?件商品;

釋放鎖?/locks/test1_lock_0000001469

87?號人?獲取鎖:/locks/test1_lock_0000001470?搶到了第86?件商品;

釋放鎖?/locks/test1_lock_0000001470

64?號人?獲取鎖:/locks/test1_lock_0000001471?搶到了第87?件商品;

釋放鎖?/locks/test1_lock_0000001471

84?號人?獲取鎖:/locks/test1_lock_0000001472?搶到了第88?件商品;

釋放鎖?/locks/test1_lock_0000001472

68?號人?獲取鎖:/locks/test1_lock_0000001473?搶到了第89?件商品;

釋放鎖?/locks/test1_lock_0000001473

67?號人?獲取鎖:/locks/test1_lock_0000001474?搶到了第90?件商品;

釋放鎖?/locks/test1_lock_0000001474

99?號人?獲取鎖:/locks/test1_lock_0000001475?搶到了第91?件商品;

釋放鎖?/locks/test1_lock_0000001475

78?號人?獲取鎖:/locks/test1_lock_0000001476?搶到了第92?件商品;

釋放鎖?/locks/test1_lock_0000001476

73?號人?獲取鎖:/locks/test1_lock_0000001477?搶到了第93?件商品;

釋放鎖?/locks/test1_lock_0000001477

71?號人?獲取鎖:/locks/test1_lock_0000001478?搶到了第94?件商品;

釋放鎖?/locks/test1_lock_0000001478

83?號人?獲取鎖:/locks/test1_lock_0000001479?搶到了第95?件商品;

釋放鎖?/locks/test1_lock_0000001479

91?號人?獲取鎖:/locks/test1_lock_0000001480?搶到了第96?件商品;

釋放鎖?/locks/test1_lock_0000001480

90?號人?獲取鎖:/locks/test1_lock_0000001481?搶到了第97?件商品;

釋放鎖?/locks/test1_lock_0000001481

65?號人?獲取鎖:/locks/test1_lock_0000001482?搶到了第98?件商品;

釋放鎖?/locks/test1_lock_0000001482

77?號人?獲取鎖:/locks/test1_lock_0000001483?搶到了第99?件商品;

釋放鎖?/locks/test1_lock_0000001483

76?號人?獲取鎖:/locks/test1_lock_0000001484?搶到了第100?件商品;

釋放鎖?/locks/test1_lock_0000001484

釋放鎖?/locks/test1_lock_0000001485

75?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001486

69?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001487

89?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001488

105?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001489

85?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001490

74?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001491

66?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001492

112?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001493

釋放鎖?/locks/test1_lock_0000001494

釋放鎖?/locks/test1_lock_0000001495

70?號人?太悲劇了,沒搶到商品...

108?號人?太悲劇了,沒搶到商品...

79?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001496

釋放鎖?/locks/test1_lock_0000001497

93?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001498

106?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001499

103?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001500

釋放鎖?/locks/test1_lock_0000001501

72?號人?太悲劇了,沒搶到商品...

80?號人?太悲劇了,沒搶到商品...

118?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001502

86?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001503

97?號人?太悲劇了,沒搶到商品...

釋放鎖?/locks/test1_lock_0000001504

110?號人?太悲劇了,沒搶到商品...

總體來說,如果了解到整個實現流程,使用zookeeper實現分布式鎖并不是很困難,不過這也只是一個簡單的實現,與前面實現Redis實現相比,本實現的穩定性更強,這是因為zookeeper的特性所致,在外界看來,zookeeper集群中每一個節點都是一致的。

在此我向大家推薦一個架構學習交流群。交流學習群號:897889510 加群獲得以上學習視頻,群里面還會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發、高性能、分布式、微服務架構的原理,JVM性能優化、分布式架構等這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多

t_goods表結構:

CREATE?TABLE?`d_sunjs_test`.`t_goods`??(

??`id`?int(11)?NOT?NULL?AUTO_INCREMENT,

??`name`?varchar(255)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL,

??`num`?int(11)?NULL?DEFAULT?NULL,

??`version`?int(11)?NULL?DEFAULT?1?COMMENT?'樂觀鎖',

??PRIMARY?KEY?(`id`)?USING?BTREE

)?ENGINE?=?InnoDB?AUTO_INCREMENT?=?2?CHARACTER?SET?=?utf8?COLLATE?=?utf8_general_ci?ROW_FORMAT?=?Dynamic;

測試的時候記得啟動zookeeper服務!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 飛哥薦讀本文從redis分布式鎖的官方實現,討論了分布式鎖需要的考慮的問題,并分析了RedLock、zookeep...
    Fi的學習筆記閱讀 5,720評論 0 39
  • 最近碰到幾個業務場景,會遇到并發的問題。在單實例情況下,我們會通過java.util.concurrent包...
    菜鳥小玄閱讀 2,277評論 0 5
  • 賓陽中學 溫海玉 這篇文章是我受一個家長的觸動寫的。 家長在我做飯的時候打來電話跟我說,你要批一下我...
    賓中溫海玉閱讀 650評論 0 0
  • 列車在通向遠方的鐵軌上飛馳著,車上載滿了無數游子以及他們關于家鄉的夢。我也在車上,背著背包,在過道上穿行尋找一個適...
    Chosing_春幸閱讀 292評論 0 1
  • 人終其一生都在詢問一個問題:“我是誰?”年輕人更愛問一個問題:“我要成為誰?”庸庸碌碌的我們每日在既定的軌道上踽踽...
    芳名楊小邪閱讀 739評論 1 0