用redis实现分布式锁

分布式部署中不可避免用到分布式锁,目前比较常用的实现方式一般有基于数据库的乐观锁、基于redis的分布式锁和基于zookeeper的分布式锁。本文只说redis的实现方式,使用jedis作为连接器。

比较简单,直接上代码吧。

public class PaasLock {
    private static final String KEY_NNXX = "NX";
    private static final String KEY_EXPX = "PX";
    private static final String KEY_SUCCESS = "OK";
    private static final String KEY_PREFIX = "paas.lock.";
    private static final Long KEY_RELEASE_NUM = 1L;  //影响redis行数
    private static Random RANDOM = new Random(100);
    private static final String REDIS_SCRIPT = "if redis.call(‘get‘, KEYS[1]) == ARGV[1] then return redis.call(‘del‘, KEYS[1]) else return 0 end";

    private RedisDao redisDao; //封装jedis
    private String lockKey;

    public PaasLock() {
        //使用uuid生成不重复的key
        this(KEY_PREFIX + UUID.randomUUID().toString().replaceAll("-", ""));
    }

    //自定义key
    public PaasLock(String lockKey) {
        assert (lockKey == null || lockKey.isEmpty());
        this.lockKey = KEY_PREFIX + lockKey;
        this.redisDao = SpringContexts.getBean(RedisDao.class);
    }

    /**
     * 获取锁
     *
     * @param requestId
     * @param expireTime 毫秒,锁本身的超时时间
     * @param waitTime   毫秒,获取锁等待时间
     * @return true获取成功,false获取失败
     */
    public boolean tryGetDistributedLock(String requestId, long expireTime, long waitTime) {
        long nanoTime = System.nanoTime();
        long timeOut = waitTime * 1000000; //纳秒10^6 = 1毫秒

        try {
            //循环等待锁释放
            while (System.nanoTime() - nanoTime < timeOut) {
                String res = redisDao.set(this.lockKey, requestId, KEY_NNXX, KEY_EXPX, expireTime);
                if (KEY_SUCCESS.equals(res)) {
                    return true;// this.lock;
                }
                Thread.currentThread().sleep(5L, RANDOM.nextInt(30));
            }

        } catch (Exception ex) {
            throw new RuntimeException("locking error", ex);
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @param requestId
     * @return
     */
    public boolean releaseDistributedLock(String requestId) {
        Object result = redisDao.eval(REDIS_SCRIPT, Collections.singletonList(this.lockKey), Collections.singletonList(requestId));
        if (KEY_RELEASE_NUM.equals(result)) { //只能释放自己的锁,防止被别的线程释放
            System.out.println("release lock..,res=" + requestId);
            return true;
        }
        return false;

    }

}

调用方法

PaasLock lock = new PaasLock();
if (lock.tryGetDistributedLock(resId, 3000, 30000)) {
            try {
                do  .....
            } finally {
                lock.releaseDistributedLock(resId);
            }
   }
   else{
    ..... 其他处理
   }

参考网上一些资料改造一下,比较简单,供大家参考。。。

原文地址:https://www.cnblogs.com/freeton/p/8295893.html

时间: 2024-11-01 20:16:45

用redis实现分布式锁的相关文章

基于Redis的分布式锁到底安全吗(上)?

网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现算法也看似合乎逻辑,但当我们着手去实现它们的时候,却发现如果你越是仔细推敲,疑虑也就越来越多. 实际上,大概在一年以前,关于Redis分布式锁的安全性问题,在分布式系统专家Martin Kleppmann和Redis的作者antirez之间就发生过一场争论.由于对这个问题一直以来比较关注,所以我前些日子仔细阅读了与这场争

基于Redis实现分布式锁(转载)

原文地址:http://blog.csdn.net/ugg/article/details/41894947 Redis命令介绍使用Redis实现分布式锁,有两个重要函数需要介绍 SETNX命令(SET if Not eXists)语法:SETNX key value功能:当且仅当 key 不存在,将 key 的值设为 value ,并返回1:若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0. GETSET命令语法:GETSET key value功能:将给定 key 的值设为

利用多写Redis实现分布式锁原理与实现分析

在我写这篇文章的时候,其实我还是挺纠结的,因为我这个方案本身也是雕虫小技拿出来显眼肯定会被贻笑大方,但是我最终还是拿出来与大家分享,我本着学习的态度和精神,希望大家能够给与我指导和改进方案. 一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子: 场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能在某一个时刻会有二笔一样的单子同时到达系统后台. 场景二:在App中下订单的时候,点击确认之后,没反应,就又点击了几次.在这种情况下,如果无法保证该接口的幂

Redis实现分布式锁

http://redis.io/topics/distlock 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增加一点复杂的设计就可以获得更好的可靠性. 这篇文章的目的就是尝试提出一种官方权威的用Redis实现分布式锁管理器的算法,我们把这个算法称为RedLock,我们相信这个算法会比一般的普通方法更加安全可靠.我们也希望社区能一起分析这个算法,

基于redis的分布式锁

<?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * https://gist.github.com/nickyleach/3694555 */ pc_base::load_sys_class('cache_redis', '', 0); class dist_key_redis { //锁的超时时间 const TIMEOUT = 20; const SL

转载:基于Redis实现分布式锁

转载:基于Redis实现分布式锁  ,出处: http://blog.csdn.net/ugg/article/details/41894947 背景在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等.大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系.其次Redis提供一些命令SETNX,GETSET,可以方便实现分布式锁机制. Redis命令介绍使用Redis实现分

基于Redis实现分布式锁

http://blog.csdn.net/ugg/article/details/41894947 背景在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等.大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系.其次Redis提供一些命令SETNX,GETSET,可以方便实现分布式锁机制. Redis命令介绍使用Redis实现分布式锁,有两个重要函数需要介绍 SETNX命令

基于Redis实现分布式锁-Redisson使用及源码分析

在分布式场景下,有很多种情况都需要实现最终一致性.在设计远程上下文的领域事件的时候,为了保证最终一致性,在通过领域事件进行通讯的方式中,可以共享存储(领域模型和消息的持久化数据源),或者做全局XA事务(两阶段提交,数据源可分开),也可以借助消息中间件(消费者处理需要能幂等).通过Observer模式来发布领域事件可以提供很好的高并发性能,并且事件存储也能追溯更小粒度的事件数据,使各个应用系统拥有更好的自治性. 本文主要探讨另外一种实现分布式最终一致性的解决方案--采用分布式锁.基于分布式锁的解决

Redis实现分布式锁原理与实现分析

一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子: 场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能在某一个时刻会有二笔一样的单子同时到达系统后台. 场景二:在App中下订单的时候,点击确认之后,没反应,就又点击了几次.在这种情况下,如果无法保证该接口的幂等性,那么将会出现重复下单问题. 在接收消息的时候,消息推送重复.如果处理消息的接口无法保证幂等,那么重复消费消息产生的影响可能会非常大. 类似这种场景,我们有很多种方法,可以使用幂等操作,也