Redission作为分布式锁

redisson作为分布式锁能够解决分布式的加锁解锁问题,还能够实现锁的设置存活时间以及自动续期。

一、整合

1、引入依赖


    org.redisson
    redisson
    3.12.5

2、创建redisson配置类实现注入

package com.atguigu.gulimall.product.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyRedisConfig {

//	@Value("${ipAddr}")
//	private String ipAddr;

	@Bean(destroyMethod = "shutdown")
	public RedissonClient redisson() {
		Config config = new Config();
		// 创建单例模式的配置
//		config.useSingleServer().setAddress("redis://" + ipAddr + ":6379");
        config.useSingleServer().setAddress("redis://192.168.116.170:6379");
		return Redisson.create(config);

	}
}

3、测试,能输出结果则说明成功


import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;


@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallProductApplicationTests {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedissonClient redissonClient;

    @Test
    public void redistest() {
        System.out.println(redissonClient);
    }

}

二、说明

lock

  @Test
    public  void  redistest(){

        RLock lock = redissonClient.getLock("mylock");//获取锁
//        lock.lock();//加锁
        lock.lock(10, TimeUnit.SECONDS);//加锁,设置解锁时间
        /**
         * lock有两种方法 一种是空参  另一种是带参
         * 空参方法:会默认调用看门狗的过期时间30*1000(30秒)
         * 然后在正常运行的时候,会启用定时任务调用重置时间的方法(间隔为开门看配置的默认过期时间的三分之一,也就是10秒)
         * 当出现错误的时候就会停止续期,直到到期释放锁或手动释放锁
         * 带参方法:手动设置解锁时间,到期后自动解锁,或者业务完成后手动解锁,不会自动续期
         */

        try{
            System.out.println("加锁成功,开始执行业务");
            Thread.sleep(5000);
        }catch (Exception e){

        }finally {
            lock.unlock();
        }

    }

trylock

  @Test
    public  void  redistest(){

        RLock lock = redissonClient.getLock("mylock");//获取锁

        try {
            lock.tryLock(20,10, TimeUnit.SECONDS);//加锁,设置等待时间,设置解锁时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /**
         * trylock可以设置等待解锁时间,如果是lock的话,会进入阻塞式等待,直到解锁
         * 而trylock方法可以设置等待时间,这里设置了20秒。如果超过20秒则不等待了,取消访问
         */

        try{
            System.out.println("加锁成功,开始执行业务");
            Thread.sleep(20000);
        }catch (Exception e){

        }finally {
            lock.unlock();
        }

    }

fair lock

  @Test
    public  void  redistest(){

        RLock fairLock = redissonClient.getFairLock("mylock");//获取锁公平锁

        
            fairLock.lock();
      
        /**
         * FairLock是公平锁,如果不采取公平锁,当一个锁被释放后,所有的线程又开始抢占锁
         * 如果采取公平锁,当一个锁被释放后,会按照先后顺序优先让先发起请求的线程抢占锁
         */

        try{
            System.out.println("加锁成功,开始执行业务");
            Thread.sleep(20000);
        }catch (Exception e){

        }finally {
            fairLock.unlock();
        }

    }

redlock

 @Test
    public  void  redistest(){

        RLock lock1 = redissonClient.getLock("lock1");
        RLock lock2 = redissonClient.getLock("lock2");
        RLock lock3 = redissonClient.getLock("lock3");
        RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
        // 同时加锁:lock1 lock2 lock3
        // 红锁在大部分节点上加锁成功就算成功。
        lock.lock();
        

        try{
            System.out.println("加锁成功,开始执行业务");
            Thread.sleep(20000);
        }catch (Exception e){

        }finally {
            lock.unlock();
        }

    }

redissonMultiLock

 @Test
    public  void  redistest(){

        RLock lock1 = redissonClient.getLock("lock1");
        RLock lock2 = redissonClient.getLock("lock2");
        RLock lock3 = redissonClient.getLock("lock3");
        RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
        // 同时加锁:lock1 lock2 lock3
        // 所有的锁都上锁成功才算成功。
        lock.lock();


        try{
            System.out.println("加锁成功,开始执行业务");
            Thread.sleep(20000);
        }catch (Exception e){

        }finally {
            lock.unlock();
        }

    }

读写锁(可以保证读到的都是最新的数据,如果在读的同时有写锁存在,则会等待直到写操作完成,然后读取最新的数据)只要有写的存在,都必须等待释放锁。读+读无需等待,redis里会记录下所有的读锁,但是不会限制阻塞。

	@ResponseBody
	@RequestMapping("/write")
	public String write() {
			String s =" ";
		RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
        //添加写锁,写锁是排他锁,当锁住之后,其他线程都要等待,以此保证读到的是最新的数据
		RLock rLock = lock.writeLock();
		rLock.lock();
		try{

					s = UUID.randomUUID().toString();
					Thread.sleep(30000);
					stringRedisTemplate.opsForValue().set("writeValue",s);

			} catch (InterruptedException e) {


			}finally {
			rLock.unlock();
		}

		return s;
	}
@ResponseBody
	@RequestMapping("/read")
	public String read() {
		String s =" ";
		RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
		RLock rLock = lock.readLock();
		rLock.lock();
		try{

			s = stringRedisTemplate.opsForValue().get("writeValue");

		} catch (Exception e) {


		}finally {
			rLock.unlock();
		}

		return s;
	}

闭锁  

设置一个闭锁,设置需要通过的数量,只有当通过的数量达到设定的数量,才解锁,否则会一直等待

	/**
	 * 闭锁 只有设定的人全通过才关门
	 */
	@ResponseBody
	@GetMapping("/index/lockDoor")
	public String lockDoor() throws InterruptedException {
		RCountDownLatch door = redissonClient.getCountDownLatch("door");
		// 设置这里有5个人
		door.trySetCount(5);
		door.await();

		return "5个人全部通过了...";
	}
	@ResponseBody
	@GetMapping("/index/go/{id}")
	public String go(@PathVariable("id") Long id) throws InterruptedException {

		RCountDownLatch door = redissonClient.getCountDownLatch("door");
		// 每访问一次相当于出去一个人,当访问五次的时候解锁
		door.countDown();
		return id + "走了";
	}

信号量

需要现在redis数据库存入一个信号量,假设存入的信号量为park value为3 表示有三个车位,当调用第一个代码时,获取车位,信号量减一,变成2,当信号量为0时,如果调用该方法,则进入阻塞,直到执行第二串代码,释放value

/**
	 * 尝试获取车位 [信号量]
	 * 信号量:也可以用作限流
	 */
	@ResponseBody
	@GetMapping("/index/park")
	public String park() {

		RSemaphore park = redissonClient.getSemaphore("park");
		boolean acquire = park.tryAcquire();
		return "获取车位 =>" + acquire;
	}
	/**
	 * 尝试获取车位
	 */
	@ResponseBody
	@GetMapping("/index/go/park")
	public String goPark() {

		RSemaphore park = redissonClient.getSemaphore("park");
		park.release();
		return "ok => 车位+1";
	}

你可能感兴趣的:(redis,分布式锁,redis,redisson,分布式锁)