导入依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
使用Curator操作API
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.util.List;
@SpringBootTest
class CuratorZkApplicationTests {
private CuratorFramework client;
@Before
public void connection() {
RetryPolicy retry = new ExponentialBackoffRetry(3000, 10);
client = CuratorFrameworkFactory
.builder()
.connectString("192.168.0.110:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retry)
.namespace("molu").build();
client.start();
}
@Test
public void create() throws Exception {
String path = client.create().forPath("molu");
System.out.println("path = " + path);
String forPath = client.create().forPath("molu", "value值".getBytes(StandardCharsets.UTF_8));
System.out.println("forPath = " + forPath);
client.create().forPath("/aaa/ccc");
String s = client.create().creatingParentsIfNeeded().forPath("app/p1");
System.out.println("s = " + s);
}
public void set() throws Exception {
Stat app = client.setData().forPath("app", "hahahahah哈哈哈哈".getBytes(StandardCharsets.UTF_8));
System.out.println("app = " + app);
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("app");
client.setData().withVersion(stat.getVersion()).forPath("app", "嘻嘻嘻".getBytes(StandardCharsets.UTF_8));
System.out.println(client.getData().forPath("app"));
}
public void delete() throws Exception {
client.delete().forPath("app");
client.delete().deletingChildrenIfNeeded().forPath("app");
client.delete().guaranteed().forPath("app");
}
@Test
public void query() throws Exception {
String app = new String(client.getData().forPath("app"));
System.out.println("app = " + app);
List<String> list = client.getChildren().forPath("app");
System.out.println("list = " + list);
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("app");
System.out.println("stat = " + stat);
}
@After
public void close(){
if (client != null) {
client.close();
}
}
}
分布式锁原理
Curator分布式锁API
使用分布式锁模拟卖票
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMultiLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import java.util.concurrent.TimeUnit;
@Slf4j
public class Ticket implements Runnable {
private int ticket = 1000;
private InterProcessMutex lock;
public Ticket(){
RetryPolicy retry = new ExponentialBackoffRetry(3000, 10);
CuratorFramework client = CuratorFrameworkFactory
.builder()
.connectString("192.168.0.110:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retry).build();
client.start();
lock = new InterProcessMutex(client, "/lock");
}
@Override
public void run() {
while (true) {
try {
lock.acquire(10, TimeUnit.SECONDS);
if (ticket > 0) {
log.info("{}-->{}", Thread.currentThread(), ticket);
Thread.sleep(100);
ticket--;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class Consumer {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread t1 = new Thread(ticket, "携程");
Thread t2 = new Thread(ticket, "飞猪");
Thread t3 = new Thread(ticket, "12306");
t1.start();
t2.start();
t3.start();
}
}