rediSsion 分布式锁使用

rediSsion 分布式锁使用

1场景设定

假定两个不同服务去请求消耗剩余商品库存数(100)
商品库存为100,数目模拟存在redis中。key值number,value100

2存值

存入方式选StringRedisTemplate存储或者jedis存储。

1 StringRedisTemplate存储

引入相关pom文件
  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
         <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>${redisson.version}</version>
        </dependency>
配置yml
spring:
  application:
    name: User
  redis:
    database: 7
    host: *******
    jedis:
      pool:
        max-active: 100
        max-idle: 20
        max-wait: -1ms
    password: *******
    port: 6379
    timeout: 20
    redisjedis:
      pool:
        min-idle: 0
@Autowired注入使用
 @Autowired
    private StringRedisTemplate stringRedisTemplate;//自带的字符串模板类,用于存储字符串
 stringRedisTemplate.opsForValue().set("number","100");

2 jedis存储(使用jedispool)

引入相关pom文件
 <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>${jedis.version}</version>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>${redisson.version}</version>
        </dependency>
配置yml(同上)
添加配置类
/**
 * zbeing
 */
@Configuration
public class RedisUtil {
    private static  Integer maxToal;
    private static  String host;
    private static Integer prot;
    private static Integer timeout;
    private static String password;
    @Value("${spring.redis.jedis.pool.max-active}")
    public  void setMaxToal(Integer maxToal) {
        RedisUtil.maxToal = maxToal;
    }
    @Value("${spring.redis.host}")
    public  void setHost(String host) {
        RedisUtil.host = host;
    }
    @Value("${spring.redis.port}")
    public  void setProt(Integer prot) {
        RedisUtil.prot = prot;
    }
    @Value("${spring.redis.timeout}")
    public  void setTimeout(Integer timeout) {
        RedisUtil.timeout = timeout;
    }
    @Value("${spring.redis.password}")
    public  void setPassword(String password) {
        RedisUtil.password = password;
    }
    public static void saveRedis(String key, String value) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxToal);
        JedisPool pool = new JedisPool(jedisPoolConfig, host, prot,timeout,password,7);
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            jedis.set(key, value);
            System.out.println("已存入的redis值" + jedis.get(key));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //还回pool中
            if (jedis != null) {
                jedis.close();
            }
        }
        pool.close();
    }

}

注:因为JedisPoolpool的util是工具类(静态),所以交由spring管理时,静态属性赋值要采用上述set属性时进行赋值
在这里插入图片描述

使用
 RedisUtil.saveRedis("number","100");

3 redisson

1redisson 配置类

/**
 * zbeing
 */
@Configuration
public class RedissonConfig {

    @Value("${spring.redis.database}")
    private int database;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private String port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.timeout}")
    private int timeout;

    /**
     * RedissonClient,单机模式
     *
     * @return
     * @throws IOException
     */
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() {
        Config config = new Config();
        SingleServerConfig singleServerConfig = config.useSingleServer();
        singleServerConfig.setAddress("redis://" + host + ":" + port);
        singleServerConfig.setTimeout(timeout);
        singleServerConfig.setDatabase(database);
        System.out.println("获取"+JSON.toJSONString(singleServerConfig));
        if (password != null && !"".equals(password)) { //有密码
            singleServerConfig.setPassword(password);
        }
        return Redisson.create(config);
    }
    }

2redisson使用

  static final String KEY = "LOCK_KEY";
@Autowired
    private RedissonClient redissonClient;
    @GetMapping("/test")
    public Object test(){
        for (int i = 0; i <100 ; i++) {
            new Thread(()->{
                redissonClient.getLock(KEY).lock();
                //LockUtil.lock(KEY);
                try {
                    String number = stringRedisTemplate.opsForValue().get("number");
                    int num = Integer.parseInt(number);
                    System.out.println("获取的数目"+num);
                    Thread.sleep(1000);
                    if(num>0&&num<=100){
                        System.out.println(" 处理业务。。。");
                        stringRedisTemplate.opsForValue().set("number",String.valueOf(num- 1));
                    }
                } catch (Exception e) {
                    //异常处理
                }finally{
                    //释放锁
                  //  LockUtil.unlock(KEY);
                    redissonClient.getLock(KEY).unlock();
                }
            }
            ).start();
        }
        //加锁
        return "SUCCESS";
    }

3演示

存入redis值
在这里插入图片描述
进行不同服务调用
在这里插入图片描述
在这里插入图片描述
得到结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4 redisson优化

package com.demo.p.util;

import java.util.concurrent.TimeUnit;

public interface Locker {
    /**
     * 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。
     *
     * @param lockKey
     */
    void lock(String lockKey);

    /**
     * 释放锁
     *
     * @param lockKey
     */
    void unlock(String lockKey);

    /**
     * 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。如果获取到锁后,执行结束后解锁或达到超时时间后会自动释放锁
     *
     * @param lockKey
     * @param timeout
     */
    void lock(String lockKey, int timeout);

    /**
     * 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。如果获取到锁后,执行结束后解锁或达到超时时间后会自动释放锁
     *
     * @param lockKey
     * @param unit
     * @param timeout
     */
    void lock(String lockKey, TimeUnit unit, int timeout);

    /**
     * 尝试获取锁,获取到立即返回true,未获取到立即返回false
     *
     * @param lockKey
     * @return
     */
    boolean tryLock(String lockKey);

    /**
     * 尝试获取锁,在等待时间内获取到锁则返回true,否则返回false,如果获取到锁,则要么执行完后程序释放锁,
     * 要么在给定的超时时间leaseTime后释放锁
     *
     * @param lockKey
     * @param waitTime
     * @param leaseTime
     * @param unit
     * @return
     */
    boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit)
            throws InterruptedException;

    /**
     * 锁是否被任意一个线程锁持有
     *
     * @param lockKey
     * @return
     */
    boolean isLocked(String lockKey);

}

package com.demo.p.util;

import java.util.concurrent.TimeUnit;

public class LockUtil {
    private static Locker locker;

    /**
     * 设置工具类使用的locker
     *
     * @param locker
     */
    public static void setLocker(Locker locker) {
        LockUtil.locker = locker;
    }

    /**
     * 获取锁
     *
     * @param lockKey
     */
    public static void lock(String lockKey) {
        locker.lock(lockKey);
    }

    /**
     * 释放锁
     *
     * @param lockKey
     */
    public static void unlock(String lockKey) {
        locker.unlock(lockKey);
    }

    /**
     * 获取锁,超时释放
     *
     * @param lockKey
     * @param timeout
     */
    public static void lock(String lockKey, int timeout) {
        locker.lock(lockKey, timeout);
    }

    /**
     * 获取锁,超时释放,指定时间单位
     *
     * @param lockKey
     * @param unit
     * @param timeout
     */
    public static void lock(String lockKey, TimeUnit unit, int timeout) {
        locker.lock(lockKey, unit, timeout);
    }

    /**
     * 尝试获取锁,获取到立即返回true,获取失败立即返回false
     *
     * @param lockKey
     * @return
     */
    public static boolean tryLock(String lockKey) {
        return locker.tryLock(lockKey);
    }

    /**
     * 尝试获取锁,在给定的waitTime时间内尝试,获取到返回true,获取失败返回false,获取到后再给定的leaseTime时间超时释放
     *
     * @param lockKey
     * @param waitTime
     * @param leaseTime
     * @param unit
     * @return
     * @throws InterruptedException
     */
    public static boolean tryLock(String lockKey, long waitTime, long leaseTime,
                                  TimeUnit unit) throws InterruptedException {
        return locker.tryLock(lockKey, waitTime, leaseTime, unit);
    }

    /**
     * 锁释放被任意一个线程持有
     *
     * @param lockKey
     * @return
     */
    public static boolean isLocked(String lockKey) {
        return locker.isLocked(lockKey);
    }

}

 @GetMapping("/test")
    public Object test(){
        for (int i = 0; i <100 ; i++) {
            new Thread(()->{
                //redissonClient.getLock(KEY).lock();
                LockUtil.lock(KEY);
                try {
                    String number = stringRedisTemplate.opsForValue().get("number");
                    int num = Integer.parseInt(number);
                    System.out.println("获取的数目"+num);
                    Thread.sleep(1000);
                    if(num>0&&num<=100){
                        System.out.println(" 处理业务。。。");
                        stringRedisTemplate.opsForValue().set("number",String.valueOf(num- 1));
                    }
                } catch (Exception e) {
                    //异常处理
                }finally{
                    //释放锁
                    LockUtil.unlock(KEY);
                   // redissonClient.getLock(KEY).unlock();
                }
            }
            ).start();
        }
        //加锁
        return "SUCCESS";
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值