├── README.md
└── java-lock
├── .classpath
├── .project
├── .settings
├── org.eclipse.jdt.core.prefs
└── org.eclipse.m2e.core.prefs
├── pom.xml
├── src
└── main
│ └── java
│ └── com
│ └── lock
│ ├── OrderNumGenerator.java
│ └── service
│ ├── Lock.java
│ ├── OrderService.java
│ ├── ZookeeperAbstractLock.java
│ └── ZookeeperDistrbuteLock.java
└── target
└── classes
├── META-INF
├── MANIFEST.MF
└── maven
│ └── com.itmayiedu
│ └── java-lock
│ ├── pom.properties
│ └── pom.xml
└── com
└── itmayiedu
├── OrderNumGenerator.class
└── service
├── Lock.class
├── OrderService.class
├── ZookeeperAbstractLock.class
├── ZookeeperDistrbuteLock$1.class
└── ZookeeperDistrbuteLock.class
/README.md:
--------------------------------------------------------------------------------
1 | # java-lock
2 | java版本的用Zookeeper实现的分布式锁
3 |
4 | 代码已经测过,可以直接使用!
5 |
6 | #业务场景
7 |
8 | 在分布式情况,生成全局订单号ID
9 |
10 | 生成订单号方案
11 |
12 | 1. 使用时间戳
13 |
14 | 2. 使用UUID
15 |
16 | 3. 推特 (Twitter) 的 Snowflake 算法——用于生成唯一 ID
17 |
18 | #产生问题
19 |
20 | 在分布式(集群)环境下,每台JVM不能实现同步,在分布式场景下使用时间戳生成订单号可能会重复
21 |
22 | #分布式情况下,怎么解决订单号生成不重复
23 |
24 | 1. 使用分布式锁
25 |
26 | 2. 提前生成好,订单号,存放在redis取。获取订单号,直接从redis中取。
27 |
28 | #使用分布式锁生成订单号技术
29 |
30 | 1.使用数据库实现分布式锁
31 |
32 | 缺点:性能差、线程出现异常时,容易出现死锁
33 |
34 | 2.使用redis实现分布式锁
35 |
36 | 缺点:锁的失效时间难控制、容易产生死锁、非阻塞式、不可重入
37 |
38 | 3.使用zookeeper实现分布式锁
39 |
40 | 实现相对简单、可靠性强、使用临时节点,失效时间容易控制
41 |
42 | 什么是分布式锁
43 |
44 | 分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序。在项目中,部署了多个tomcat应用,在执行定时任务时就会遇到同一任
45 |
46 | 务可能执行多次的情况,我们可以借助分布式锁,保证在同一时间只有一个tomcat应用执行了定时任务
47 |
48 | #使用Zookeeper实现分布式锁
49 |
50 | #Zookeeper实现分布式锁原理
51 |
52 | 使用zookeeper创建临时序列节点来实现分布式锁,适用于顺序执行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获取分布式锁,程序执行完成之后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推……
53 |
54 |
--------------------------------------------------------------------------------
/java-lock/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/java-lock/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | java-lock
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.m2e.core.maven2Nature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/java-lock/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
3 | org.eclipse.jdt.core.compiler.compliance=1.5
4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
5 | org.eclipse.jdt.core.compiler.source=1.5
6 |
--------------------------------------------------------------------------------
/java-lock/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/java-lock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.itmayiedu
4 | java-lock
5 | 0.0.1-SNAPSHOT
6 |
7 |
8 | com.101tec
9 | zkclient
10 | 0.10
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/java-lock/src/main/java/com/lock/OrderNumGenerator.java:
--------------------------------------------------------------------------------
1 | package com.lock;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | //生成订单号规则 使用时间戳+业务id
7 | public class OrderNumGenerator {
8 | // 业务ID
9 | private static int count = 0;
10 |
11 | // 生成订单号
12 | public String getNumber() {
13 | try {
14 | Thread.sleep(200);
15 | } catch (Exception e) {
16 | // TODO: handle exception
17 | }
18 | SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
19 | return simpt.format(new Date()) + "-" + ++count;
20 |
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/java-lock/src/main/java/com/lock/service/Lock.java:
--------------------------------------------------------------------------------
1 | package com.lock.service;
2 |
3 |
4 | // lock 锁 定义分布式锁
5 | public interface Lock {
6 |
7 | //获取锁
8 | public void getLock();
9 | //释放锁
10 | public void unLock();
11 | }
12 |
--------------------------------------------------------------------------------
/java-lock/src/main/java/com/lock/service/OrderService.java:
--------------------------------------------------------------------------------
1 | package com.lock.service;
2 |
3 | import java.util.concurrent.locks.Lock;
4 | import java.util.concurrent.locks.ReentrantLock;
5 |
6 | import com.itmayiedu.OrderNumGenerator;
7 |
8 | // 订单生成调用业务逻辑
9 | public class OrderService implements Runnable {
10 | // 生成订单号
11 | OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
12 | // 重入锁
13 | // private Lock lock = new ReentrantLock();
14 | private com.itmayiedu.service.Lock lock = new ZookeeperDistrbuteLock();
15 |
16 | public void run() {
17 | try {
18 | // 上锁
19 | lock.getLock();
20 | // synchronized (this) {
21 | // 模拟用户生成订单号
22 | getNumber();
23 | } catch (Exception e) {
24 | e.printStackTrace();
25 | } finally {
26 | // 釋放鎖資源
27 | lock.unLock();
28 | }
29 | }
30 |
31 | public void getNumber() {
32 | String number = orderNumGenerator.getNumber();
33 | System.out.println(Thread.currentThread().getName() + ",##number:" + number);
34 | }
35 |
36 | public static void main(String[] args) {
37 | System.out.println("##模拟生成订单号开始...");
38 |
39 | for (int i = 0; i < 100; i++) {
40 | new Thread(new OrderService()).start();
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/java-lock/src/main/java/com/lock/service/ZookeeperAbstractLock.java:
--------------------------------------------------------------------------------
1 | package com.lock.service;
2 |
3 | import java.util.concurrent.CountDownLatch;
4 |
5 | import org.I0Itec.zkclient.ZkClient;
6 |
7 | //重构重复代码,将重复代码交给子类执行
8 | public abstract class ZookeeperAbstractLock implements Lock {
9 | // zk连接地址
10 | private static final String CONNECTSTRING = "127.0.0.1:2181";
11 | // 创建zk连接
12 | protected ZkClient zkClient = new ZkClient(CONNECTSTRING);
13 | protected static final String PATH = "/lock";
14 | protected CountDownLatch countDownLatch = null;
15 |
16 | public void getLock() {
17 | if (tryLock()) {
18 | System.out.println("###获取锁成功#####");
19 | } else {
20 | // 等待
21 | waitLock();
22 | // 重新获取锁
23 | getLock();
24 | }
25 | }
26 |
27 | // 是否获取锁成功,成功返回true 失败返回fasle
28 | abstract Boolean tryLock();
29 |
30 | // 等待
31 | abstract void waitLock();
32 |
33 | public void unLock() {
34 | if (zkClient != null) {
35 | zkClient.close();
36 | System.out.println("释放锁资源");
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/java-lock/src/main/java/com/lock/service/ZookeeperDistrbuteLock.java:
--------------------------------------------------------------------------------
1 | package com.lock.service;
2 |
3 | import java.util.concurrent.CountDownLatch;
4 |
5 | import org.I0Itec.zkclient.IZkDataListener;
6 |
7 | public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock {
8 |
9 | @Override
10 | Boolean tryLock() {
11 | try {
12 | zkClient.createEphemeral(PATH);
13 | return true;
14 | } catch (Exception e) {
15 | return false;
16 | }
17 |
18 | }
19 |
20 | @Override
21 | void waitLock() {
22 |
23 | // 使用事件监听,获取到节点被删除,
24 | IZkDataListener iZkDataListener = new IZkDataListener() {
25 | // 当节点被删除
26 | public void handleDataDeleted(String dataPath) throws Exception {
27 | if (countDownLatch != null) {
28 | // 唤醒
29 | countDownLatch.countDown();
30 | }
31 |
32 | }
33 |
34 | // 当节点发生改变
35 | public void handleDataChange(String dataPath, Object data) throws Exception {
36 |
37 | }
38 | };
39 |
40 | // 注册节点信息
41 | zkClient.subscribeDataChanges(PATH, iZkDataListener);
42 | if (zkClient.exists(PATH)) {
43 | // 创建信号量
44 | countDownLatch = new CountDownLatch(1);
45 | try {
46 | // 等待
47 | countDownLatch.await();
48 | } catch (Exception e) {
49 |
50 | }
51 |
52 | }
53 | // 删除事件通知
54 | zkClient.unsubscribeDataChanges(PATH, iZkDataListener);
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/java-lock/target/classes/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Built-By: Administrator
3 | Build-Jdk: 1.8.0_101
4 | Created-By: Maven Integration for Eclipse
5 |
6 |
--------------------------------------------------------------------------------
/java-lock/target/classes/META-INF/maven/com.itmayiedu/java-lock/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven Integration for Eclipse
2 | #Sat Mar 03 22:27:12 CST 2018
3 | version=0.0.1-SNAPSHOT
4 | groupId=com.itmayiedu
5 | m2e.projectName=java-lock
6 | m2e.projectLocation=F\:\\itmayiedujiangke2018-02-24\\java-lock
7 | artifactId=java-lock
8 |
--------------------------------------------------------------------------------
/java-lock/target/classes/META-INF/maven/com.itmayiedu/java-lock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.itmayiedu
4 | java-lock
5 | 0.0.1-SNAPSHOT
6 |
7 |
8 | com.101tec
9 | zkclient
10 | 0.10
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/OrderNumGenerator.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/OrderNumGenerator.class
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/service/Lock.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/service/Lock.class
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/service/OrderService.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/service/OrderService.class
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/service/ZookeeperAbstractLock.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/service/ZookeeperAbstractLock.class
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/service/ZookeeperDistrbuteLock$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/service/ZookeeperDistrbuteLock$1.class
--------------------------------------------------------------------------------
/java-lock/target/classes/com/itmayiedu/service/ZookeeperDistrbuteLock.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anlijie/java-lock/c46a1151a90e94c9e8f2e835a125b8ff0a8cb421/java-lock/target/classes/com/itmayiedu/service/ZookeeperDistrbuteLock.class
--------------------------------------------------------------------------------