分布式锁功能:
在分布式场景中,我们为了保证数据的一致性,经常在程序运行的某一个点需要进行同步操作(java 可提供synchronized或者Reentrantlock实现)比如我们看一个小示例,这个示例会出现分布式不同步的问题:
因为我们之前所说的是在高并发下访问一个程序,现在我们则是在高并发下访问多个服务器节点(分布式)。
我们使用Curator基于zookeeper的特性提供的分布式锁来处理分布式场景的数据一致性,zookeeper本身的分布式是有写问题的,我以前在实现的时候遇到过...这里强烈推荐使用Curator的分布式锁!
Reentrantlock DEMO
package bjsxt.curator.lock;
import java.text.SimpleDateFormat;
import java.util.Date;
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();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss|SSS");
System.out.println(sdf.format(new Date()));
//System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
},"t" + i).start();
}
Thread.sleep(50);
countdown.countDown();
}
}
理想结果
但是当前是在一个jvm中,假如将当前demo当做一个服务,部署在多台机器上,如果外部群请求量大的话,只能保证一个机器,单节点的同步,如果此时访问另外一台机器,数据就肯定不一致了,分布式锁的本意是在多个节点上保持一个同步。保持一个锁的机制。
package bjsxt.curator.lock;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
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.1.171:2181,192.168.1.172:2181,192.168.1.173:2181";
/** session超时时间 */
static final int SESSION_OUTTIME = 5000;//ms
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 ReentrantLock reentrantLock = new ReentrantLock();
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(); //许可
//reentrantLock.lock();
//-------------业务处理开始
//genarNo();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss|SSS");
System.out.println(sdf.format(new Date()));
//System.out.println(System.currentTimeMillis());
//-------------业务处理结束
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//释放
lock.release();
//reentrantLock.unlock();
} catch (Exception e) {
e.printStackTrace();
}
}
}
},"t" + i).start();
}
Thread.sleep(100);
countdown.countDown();
}
}
执行结果