分布式锁

Redis分布式锁

分布式锁的实现

多进程的架构:

    1.资源共享问题

    2.数据安全性

    分布式锁的解决方案

    1.怎么去获取锁

        数据库

         lock表(

                methodName varchar(1000);

                memo varchar(100);

                modifyTime timestamp;

                unique key mn(method)    ---唯一约束 

        )

          try{  

             exec insert into lock(methodName,memo) values('method','desc');   

               return true;

           }catch(DuplicateException e){

             return false;

    }

    zookeepeer     

        redis

        delete去释放锁

    2.怎么去释放锁

    3.在redis当中使用锁需要使用到redis的命令 setnx这个命令

          setnx这个命令的作用是当redis当中有数据的时候,命令不会执行,直接返回0,如果数据不存在,直接赋值,然后返回1


接下来代码演示在java中使用redis的锁:

首先在pom.xml文件当中增加下面的代码.

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>

然后编写一个redis连接类:

public class RedisManager
{

    private static JedisPool jedisPool;

    static{
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMaxTotal(20);
        jedisPool = new JedisPool(jedisPoolConfig,"192.168.159.136",6379);
    }

    public static Jedis getJedis() throws Exception {
        if(null!=jedisPool){
            return jedisPool.getResource();
        }
        throw new Exception("jedis Pool is not init");
    }
    
}

使用redis的锁,并且测试锁的执行:

public class RedisLock {

    /**
     *
     * @param key  获取的key值
     * @param timeout  获取锁的最大超时时间
     * @return
     */
    public String getLock(String key,int timeout){
        try {
           Jedis jedis = RedisManager.getJedis();
           String value = UUID.randomUUID().toString();

           long end = System.currentTimeMillis() + timeout;
           //
           while(  System.currentTimeMillis()<end ){ //阻塞
               //如果这里redis释放锁出问题了,会导致后续的线程没有办法继续获得锁,这个时候可以实现超时的机制
                if (jedis.setnx(key, value) == 1) {
                    jedis.expire(key,timeout);
                   //锁设置成功,redis操作成功
                   return value;
               }
               //如果redis服务在设置nx的时候宕机了,expire没有办法设置成功
               if(jedis.ttl(key)==-1){//没设置超时时间
                    //设置过期时间
                   jedis.expire(key,timeout);
               }
               Thread.sleep(1000);
           }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //释放锁
    /**
     * @param key
     * @param value
     * @return
     */
    public boolean releaseLock(String key,String value){

        try {
            Jedis jedis = RedisManager.getJedis();

             while(true) {
                 jedis.watch(key);  //用来监控一个或多个键的key,一旦修改删除,后面代码不会执行
                 //判断获得锁的线程和当前redis当中存的锁是同一个
                 if (value.equals(jedis.get(key))) {
                     Transaction trans = jedis.multi();
                     trans.del(key);
                     List<Object> list = trans.exec();
                     if (list == null) {
                         continue;
                     }
                     return true;
                 }
                 jedis.unwatch();
             }

        } catch (Exception e) {
            e.printStackTrace();
        }



        return false;
    }

    public static void main(String[]args){

        RedisLock lock = new RedisLock();

        String lockId = lock.getLock("lock:aaa",10000);

        if(null!=lockId){
            System.out.println("获得锁成功!");
        }

        String lockId2 = lock.getLock("lock:aaa",10000);
        System.out.println(lockId2);



    }



}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值