redis实现分布式锁(springboot中测试)

pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- jedis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.2</version>
    </dependency>
</dependencies>

application.properties配置

#redis 配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.252.128
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
#spring-session 使用
spring.session.store-type=none

配置类

package com.example.demoredis.conf;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class RedisConfig {
    private Logger logger = LoggerFactory.getLogger(RedisConfig.class);
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;

    @Bean
    public JedisPool redisPoolFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMinIdle(minIdle);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);

        logger.info("JedisPool注入成功!");
        logger.info("redis地址:" + host + ":" + port);
        return jedisPool;
    }
}

测试代码:

package com.example.demoredis;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.UUID;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoRedisApplicationTests {
    @Resource
    private JedisPool jedisPool;

    /**
     * @description 分布式锁测试
     * @date 14:57 2019/9/17
     **/
    @Test
    public void contextLoads() {
        Jedis jedis = jedisPool.getResource();
        String ping = jedis.ping();
        System.out.println("================================jedis连接:" + ping);
        /*System.out.println(lock(jedis, "a", "1", 60L));
        System.out.println(jedis.get("a"));
        System.out.println(unLock(jedis, "a", "2"));*/
        String key = "aaa";
        String value = UUID.randomUUID().toString().replaceAll("-", "");
        // 锁定过期时间 s
        Long lockTime = 60L;
        // 尝试次数
        Integer tryCount = 20;
        // 每次尝试休闲时间 ms
        Long trySleepTime = 1500L;
        // 业务代码执行时间 s
        Integer serSecond = 30;

        Boolean lock = false;
        try {
            lock = lockRetry(jedis, key, value, lockTime, tryCount, trySleepTime);
            if (lock) {
                System.out.println("锁定成功-------------------------");
                System.out.println("业务代码执行.......................................");
                for (int i = 0; i < serSecond; i++) {
                    System.out.println(" ... " + (i + 1));
                    Thread.sleep(1000L);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (lock) {
                Boolean unLock = unLock(jedis, key, value);
                if (unLock) {
                    System.out.println("解锁成功-------------------------");
                } else {
                    System.out.println("解锁失败-------------------------");
                }
            }
        }
        System.out.println("=================  关闭连接  ==================");
        jedis.close();
    }

    /**
     * @description 重试去获取锁(锁定)
     * 参数:jedis,k,v, 过期时间,重试次数,每次重试休眠时间
     * @date 14:58 2019/9/17
     **/
    public Boolean lockRetry(Jedis jedis, String key, String value, Long timeOut, Integer retry, Long sleepTime) {
        Boolean flag = false;
        try {
            for (int i = 0; i < retry; i++) {
                flag = lock(jedis, key, value, timeOut);
                System.out.println("重试" + (i + 1) + "次....... " + key + " -> " + value);
                if (flag) {
                    System.out.println("成功获取锁--------");
                    break;
                }
                Thread.sleep(sleepTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * @description 加锁
     * 参数:jedis,k,v,过期时间
     * @date 15:05 2019/9/17
     **/
    public Boolean lock(Jedis jedis, String key, String value, Long timeOut) {
        // 保证原子性,同一时间只能一个key,并且不能被覆盖:NX:如果存在不操作(返回null), EX:超时时间单位秒
        String result = jedis.set(key, value, "NX", "EX", timeOut);
        // 操作成功时返回"OK"
        return "OK".equals(result);
    }

    /**
     * @description 解锁
     * 参数:jedis,k,v
     * @date 15:06 2019/9/17
     **/
    public static Boolean unLock(Jedis jedis, String key, String value) {
        // 如果k,v对存在 删除,如果k,v不存在不删除,(使用脚本可以保证操作的原子性)
        String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else  return 0 end";
        Long result = (Long) jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
        return Long.valueOf(1).equals(result);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值