redis 分布式锁 redisson

Redisson

Redisson 是官方文档推荐的,是基于java写的。

对其初步体验:
maven 依赖

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>
<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson</artifactId>
	<version>2.7.0</version>
</dependency>
代码如下

搭建一个简单的springboot demo进行测试:

  1. 分布式锁
public class DistributedRedisLock {
    // 从配置类中获取redisson对象
    private static Redisson redisson = RedissonManager.getRedisson();
    private static final String LOCK_TITLE = "redisLock_";

    // 加锁
    public static boolean acquire(String lockName) {
        // 声明key对象
        String key = LOCK_TITLE + lockName;
        // 获取锁对象
        RLock mylock = redisson.getLock(key);
        // 加锁,并且设置锁过期时间,防止死锁的产生
        mylock.lock(2, TimeUnit.MINUTES);
        System.err.println("======lock======" + Thread.currentThread().getName());
        // 加锁成功
        return true;
    }

    // 锁的释放
    public static void release(String lockName) {
        // 必须是和加锁时的同一个key
        String key = LOCK_TITLE + lockName;
        // 获取所对象
        RLock mylock = redisson.getLock(key);
        // 释放锁(解锁)
        mylock.unlock();
        System.err.println("======unlock======" + Thread.currentThread().getName());
    }
}
  1. 使用 JedisPool 连接 redis

我使用的redis没有设置密码,所以将密码注掉了 。

@Configuration
@PropertySource("classpath:application.properties")
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;

    // @Value("${spring.redis.password}")
    // private String password;

    @Value("${spring.redis.block-when-exhausted}")
    private boolean blockWhenExhausted;

    @Bean
    public JedisPool jedis() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
        // 是否启用pool的jmx管理功能, 默认true
        jedisPoolConfig.setJmxEnabled(true);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, null);
        return jedisPool;
    }

}
  1. 构建 Controller
@Controller
@RequestMapping(value = "/")
public class HelloController {

    private static AtomicInteger count = new AtomicInteger(0);
    private static AtomicInteger count1 = new AtomicInteger(0);

    @Autowired
    RedisUtil redisUtil;

    @RequestMapping(value = "hello", method = RequestMethod.GET)
    @ResponseBody
    public String hello() throws InterruptedException {
        String key = "test_num";
        int num = count.incrementAndGet();
        // 加锁
        DistributedRedisLock.acquire(key);
        // 处理逻辑
        redisUtil.incr("test_num");
        // Thread.sleep(1000);
        System.out.println("===========第 " + num + " 次请求===================" + redisUtil.get("test_num"));
        // 释放锁
        DistributedRedisLock.release(key);
        return "success";
    }

    @RequestMapping(value = "hello1", method = RequestMethod.GET)
    @ResponseBody
    public String hello1() throws InterruptedException {
        int num = count1.incrementAndGet();
        // 处理逻辑
        redisUtil.incr("test_num1");
        // Thread.sleep(1000);
        System.out.println("TEST1===========第 " + num + " 次请求===================" + redisUtil.get("test_num1"));
        return "success";
    }

}
  1. 使用 Junit 模拟并发
		<!-- 包依赖 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
			<scope>test</scope>
			<optional>true</optional>
		</dependency>
		<!-- junit 多线程测试 -->
		<!-- https://mvnrepository.com/artifact/net.sourceforge.groboutils/groboutils-core -->
		<dependency>
			<groupId>net.sourceforge.groboutils</groupId>
			<artifactId>groboutils-core</artifactId>
			<version>5</version>
			<scope>test</scope>
		</dependency>

使用 groboutils 模拟多线程,代码如下:

public class Test {

    @org.junit.Test
    public void test() {

        TestRunnable runner = new TestRunnable() {
            @Override
            public void runTest() throws Throwable {
                String url = "http://localhost:8080/hello";
                HttpGet get = new HttpGet(url);
                CloseableHttpClient client = HttpClientBuilder.create().build();
                CloseableHttpResponse response = client.execute(get);
                response.close();
            }
        };

        int runnerCount = 10;
        // Rnner数组,想当于并发多少个。
        TestRunnable[] trs = new TestRunnable[runnerCount];
        for (int i = 0; i < runnerCount; i++) {
            trs[i] = runner;
        }
        // 用于执行多线程测试用例的Runner,将前面定义的单个Runner组成的数组传入
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);
        try {
            // 开发并发执行数组里定义的内容
            mttr.runTestRunnables();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}
  1. 测试结果

先测试一下没有使用 Redis 分布式锁的接口
http://localhost:8080/hello1

TEST1===========第 5 次请求===================9
TEST1===========第 4 次请求===================9
TEST1===========第 7 次请求===================9
TEST1===========第 10 次请求===================9
TEST1===========第 3 次请求===================10
TEST1===========第 1 次请求===================10
TEST1===========第 9 次请求===================10
TEST1===========第 8 次请求===================10
TEST1===========第 6 次请求===================10
TEST1===========第 2 次请求===================10

使用了分布式锁的接口:
http://localhost:8080/hello

======lock======http-nio-8080-exec-1
===========第 1 次请求===================1
======unlock======http-nio-8080-exec-1
======lock======http-nio-8080-exec-6
===========第 3 次请求===================2
======unlock======http-nio-8080-exec-6
======lock======http-nio-8080-exec-8
===========第 7 次请求===================3
======unlock======http-nio-8080-exec-8
======lock======http-nio-8080-exec-2
===========第 2 次请求===================4
======unlock======http-nio-8080-exec-2
======lock======http-nio-8080-exec-9
===========第 6 次请求===================5
======unlock======http-nio-8080-exec-9
======lock======http-nio-8080-exec-4
===========第 9 次请求===================6
======unlock======http-nio-8080-exec-4
======lock======http-nio-8080-exec-3
===========第 4 次请求===================7
======unlock======http-nio-8080-exec-3
======lock======http-nio-8080-exec-7
===========第 5 次请求===================8
======unlock======http-nio-8080-exec-7
======lock======http-nio-8080-exec-5
===========第 8 次请求===================9
======unlock======http-nio-8080-exec-5
======lock======http-nio-8080-exec-10
===========第 10 次请求===================10
======unlock======http-nio-8080-exec-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值