轻松愉快实现Redis分布式锁

前言

相信在互联网公司工作的各位小伙伴都深刻认识到,当不同进程操作同一个对象的时候都要保证原子性,这时候就会用到锁,但是在同一个进程里修改可以用sychronized、LockCondition来加锁。为了能在分布式使用锁,我们一般都是用Redis来实行,当然也有其他解决方案啦。

具体流程可以看下图:
在这里插入图片描述
图中可以看到几个步骤:

  1. 多台主机(这里也可以叫服务器)向Redis申请锁。
  2. 获取锁成功后会返回OK,失败的话就返回null。
  3. 获取锁的进程就可以往下执行业务。

当然可能有些小伙伴就会有疑问,如果同一时间有多个进程申请锁,不会引起并发问题,例如多个进程都获取到同一个锁?这个其实不用担心,因为Redis是单线程的,单线程怎么会出现并发问题?至于为什么单线程,各位可以去上网搜下Redis机制,或者我后期也会出一篇文章来讲解Redis之所快的原因。

其实看上去也不是特别难,难的部分Redis都做好了,所以大家没必要畏惧。

实现

我比较倾向于用set方法,其实我个人不太建议用setnx,.最主要的原因是setnx不能设置有效时间,不能设置有效时间意味着什么,看代码!(提示下,我这里用的Jedis,包括后续的代码)

 public void setnxWithTimeOut(String key, String value, int timeOut) {
        Jedis jedis = getJedis();
        if (0 != jedis.setnx(key, value)) { 
        // 如果运行到这里突然发生宕机,那么锁就永远不会释放
            jedis.expire(key, timeOut);
        }
    }

好了好了,我觉得我扯太多了。接下来是进入正题,还是老规矩,继续看代码:

 	/**
     * 分布式锁
     * @param key
     * @param value
     * @param nx
     * @param expx
     * @param time
     * @return
     */
    public String set(String key, String value, String nx, String expx, int time){
        Jedis jedis = getJedis();
        String result =  jedis.set(key, value, nx, expx, time);
        return result;
    }

这里解释下各个参数的意思:

  1. key是设置锁的key值。
  2. value是这个锁的值,这个value值你可以设置为线程ID。
  3. nx只能取NX或者XX,如果取NX,则只有当key不存在是才进行set,如果取XX,则只有当key已经存在时才进行set。
  4. expx只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒。
  5. time就是过期时间。

实验:

    /**
    * 停滞状态超过两天自动更换为公海状态, 每天晚上1点执行
    */
   private static final String LOCK_NX = "NX";
   private static final String LOCK_EXPRIETYPE = "EX";
   private static final String LOCK_KEY = "LockForChangeState";
   private static final String LOCK_SUCCESS = "OK";
   
   public void changeStatusStopToHighSea() {
        // 加锁成功返回OK字符串,否则返回null
       String lock = jedisUtil.set(LOCK_KEY, String.valueOf(Thread.currentThread().getId()), LOCK_NX, LOCK_EXPRIETYPE, 600);
       if (LOCK_SUCCESS.equals(lock)) {
           // 下面写需要执行的业务流程
           System.out.println("123");
       }
   }

释放锁的话我目前知道有两种:

  1. 等有效期过去,这种一般不太好,感觉这种方式有点别扭,业务流程执行完不释放锁就是占着茅坑不拉屎,这样会影响后面想用厕所的人,可不好。如果人少另说,
  2. 移除对应的key,这个比较简单粗暴。

结论

用的redis越多发现它真是太强大,做什么都可以,分布式锁、缓存数据库、权限认证等等。所以啊,这么强大的组件,我还是建议各位兄弟去看下,虽然是由C语言编写哈哈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值