redis实现分布式锁

一、分布式锁实现

原理:运用redis string类型存储策略进行实现。同时,设置string过期时间,防止死锁。

**
 * 基于redis的分布式锁实现
 *
 * @author whucke
 * @since 2018/12/12 16:47
 */
public abstract class DistributedLock {

    private static final String LOCK_SUCCESS = "OK"; //返回结果
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 获取分布式锁
     *
     * @param lockKey    锁名
     * @param requestId  锁归属
     * @param expireTime 过期时间
     * @return
     */
    public static boolean getLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        SetParams params = new SetParams()
                .nx() //设置key存储策略,如果key存在则存储失败,仅当key不存在是才能成功保存
                .px(expireTime); //设置key的过期时间
        String ret = jedis.set(lockKey, requestId, params);
        if (LOCK_SUCCESS.equals(ret)) {
            return true;
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @param lockKey   锁名
     * @param requestId 锁归属
     * @return
     */
    public static boolean release(Jedis jedis, String lockKey, String requestId) {
        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        Object ret = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); //执行脚本,保持操作原子性
        if (RELEASE_SUCCESS.equals(ret)) {
            return true;
        }
        return false;
    }

}

二、锁测试

public class DistributedLockTest {

    public static void main(String[] args) {
        Order order = new Order();

        for (int i = 0; i < 100; i++) {
            Business business = new Business(order);
            business.start();
        }

    }

    /**
     * 业务处理类
     */
    static class Order {
        private final int MAX = 100; //总共
        private final String LOCK_KEY = "sale lock key";
        private final int EXPIRE_TIME = 10000;
        private int remain = 100; //剩余
        private  final String REDIS_HOST = "127.0.0.1";

        /**
         * 执行业务操作
         */
        public void process() {

            String user = "user-" + Thread.currentThread().getId();
            //获取锁
            Jedis jedis = new Jedis(REDIS_HOST);
            boolean lock = false;
            int time = 0; //重试次数5次
            while (!lock && time < 50) {
                lock = DistributedLock.getLock(jedis, LOCK_KEY, user, EXPIRE_TIME);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                time++;
            }
            if (lock) {
                System.out.println("用户:【" + user + "】排队成功,校验库存!");
                if (remain > 0) {
                    int num = MAX - remain + 1; //售出第几个商品
                    System.out.println("用户:【" + user + "】购买第" + num + "件商品,剩余 " + --remain + " 件商品!");
                } else {
                    System.out.println("该商品已售罄!");
                }
                //释放锁
                boolean release = DistributedLock.release(jedis, LOCK_KEY, user);
                if (release) {
                    System.out.println("用户:【" + user + "】释放资源成功");
                } else {
                    System.out.println("用户:【" + user + "】释放资源失败");
                }
            } else {
                System.out.println("用户:【" + user + "】排队等待中···········");
            }
            jedis.close();
        }

    }

    /**
     * 模拟商品售卖
     */
    static class Business extends Thread {
        private Order order;

        public Business(Order order) {
            this.order = order;
        }

        @Override
        public void run() {
            order.process();
        }
    }

}

以上测试方法只能测试开启线程进行锁获取,并发测试可以使用同步屏障CyclicBarrier类来实现,示例:http://ifeve.com/concurrency-cyclicbarrier/

你可能感兴趣的:(redis实现分布式锁)