redis和zk分布式锁实现

分布式锁
场景演示为什么需要分布式锁
场景:一个订单表,库存表,支付表,多个用户对库存操作。当前库存为1
public class Order {
public void createOrder(){
System.out.println(Thread.currentThread().getName()+" 创建订单");
}
}

public class Pay {
public static void pay(){
System.out.println(Thread.currentThread().getName()+" 支付成功!");
}
}
public class Stock {
private static Integer COUNT = 1;
public boolean reduceStock(){
if(COUNT > 0){
COUNT – ;
return true;
}
return false;
}
}

如图所示:

模拟了两个用户对库存只有一时,两个用户都成功减库存成功了,并且支付成功了,所有在分布式系统中,需要有分布式锁控制同一时间只有一个用户进来访问。
分布式系统:表示有多个进程提供服务,完成一件事。

public class Main {
//模拟两个用户同时抢订单
public static void main(String[] args) {
Thread user1 = new Thread(new UserThread(),“user1”);
Thread user2 = new Thread(new UserThread(),“user2”);
user1.start();
user2.start();
}
static class UserThread implements Runnable{
@Override
public void run() {
new Order().createOrder();
Boolean result = new Stock().reduceStock();
if(result){
System.out.println(Thread.currentThread().getName() + " 减库存成功");
new Pay().pay();
}else{
System.out.println(Thread.currentThread().getName()+" 减库存失败");

        }
    }
}

}

redis分布式锁实现
package com.wf.springdemo.locktest;/**

  • Created by wufei on 2018/12/10.
    */

import com.wf.springdemo.locktest.redislock.RedisLock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**

  • @author wufei
  • @create 2018-12-10 9:12
    **/
    public class Main {
    //模拟两个用户同时抢订单
    public static void main(String[] args) {
    Thread user1 = new Thread(new UserThread(),“user1”);
    Thread user2 = new Thread(new UserThread(),“user2”);
    user1.start();
    user2.start();
    }
    //public static Lock lock = new ReentrantLock();
    public static Lock lock = new RedisLock();
    static class UserThread implements Runnable{
    @Override
    public void run() {
    new Order().createOrder();
    lock.lock();
    Boolean result = new Stock().reduceStock();
    lock.unlock();
    if(result){
    System.out.println(Thread.currentThread().getName() + " 减库存成功");
    new Pay().pay();
    }else{
    System.out.println(Thread.currentThread().getName()+" 减库存失败");
    }
    }
    }
    }

package com.wf.springdemo.locktest.redislock;/**

  • Created by wufei on 2018/12/10.
    */

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

import java.util.Collections;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**

  • @author wufei

  • @create 2018-12-10 9:30
    **/
    public class RedisLock implements Lock {
    private static String LOCK_NAME = “redis_lock”;
    private static String REQUEST_ID = “123456”;

    ThreadLocal jedis = new ThreadLocal();

    //加锁
    @Override
    public void lock() {
    init();
    if(tryLock()){//如果没有锁则加锁
    //如果某个应用节点挂了,不能释放锁了也就是不能进入unlock()方法了,这个情况怎么办呢?设置过期时间
    // jedis.set(LOCK_NAME,REQUEST_ID);
    // jedis.expire(LOCK_NAME,3000);//设置过期时间
    //但是这个时间不是原子性,执行到jedis.set方法了,但是应用挂了,没有执行jedis.expire,所有还会导致无法释放锁。
    //怎么设置原子性呢。
    jedis.get().set(LOCK_NAME,REQUEST_ID,“NX”,“PX”,3000);
    }
    }

    /**

    • 获取锁 true 没有锁,false 有锁
    • @return
      */
      @Override
      public boolean tryLock() {
      //不停的获取锁
      while (true){
      //获取锁,怎样保证原子性呢 使用setnx方法
      //key不存在返回1,存在返回0
      //String lock = jedis.get(LOCK_NAME);
      Long lock = jedis.get().setnx(LOCK_NAME,REQUEST_ID);
      if(lock ==1){
      return true;
      }
      }
      }

    /**

    • 释放锁
      */
      @Override
      public void unlock() {
      //释放自己设置的锁,
      // String value = jedis.get().get(LOCK_NAME);
      // if(REQUEST_ID.equals(value)){
      // jedis.get().del(LOCK_NAME);
      // }
      //原子性 使用lua
      // String script = “if redis.call(‘get’,KEYS[1]==ARGV[1]) then return redis.call(‘del’,KEYS[1]) else return 0 end”;
      // jedis.get().eval(script, Collections.singletonList(LOCK_NAME),Collections.singletonList(REQUEST_ID));

      //lua script
      String script = “if redis.call(‘get’, KEYS[1]) == ARGV[1] then return redis.call(‘del’, KEYS[1]) else return 0 end”;
      Object result = jedis.get().eval(script, Collections.singletonList(LOCK_NAME), Collections.singletonList(REQUEST_ID));

    }

    private void init(){
    if(jedis.get() == null){
    jedis.set(new Jedis(“localhost”));
    }
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
    return false;
    }
    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public Condition newCondition() {
    return null;
    }
    }

zk分布式锁实现

猜你喜欢

转载自blog.csdn.net/wflovejava/article/details/84936165