使用Redisson测试分布式锁

2020-04-27  本文已影响0人  司展超

一、需要工具

1)nginx
2)JMeter

二、dockers安装Nginx

1.  docker pull nginx:stable-perl
2.  docker run -p 80:80 --name nginx \
           -v /mydata/nginx/html:/usr/share/nginx/html \
           -v /mydata/nginx/logs:/var/log/nginx \
           -d nginx:stable-perl
3.  #目的:复制出内部的配置文件
    docker container cp nginx:/etc/nginx . 
4.  docker   run -p 80:80 --name nginx \
            -v /mydata/nginx/html:/usr/share/nginx/html \
            -v /mydata/nginx/logs:/var/log/nginx \
            -v /mydata/nginx/conf:/etc/nginx \
            -d nginx:stable-perl

三、配置Nginx

在nginx.conf中加入如下配置:


1.png
    upstream tomcat{
    server win10的IP:8080 weight=10;
    server win10的IP:8081 weight=10;
    server win10的IP:8082 weight=10;
    }

在config.d目录下修改default.conf

location / {
       # root   /usr/share/nginx/html;
       # index  index.html index.htm;
        proxy_pass http://tomcat;
    }
2.png

四、创建一个springboot应用引入redisson的依赖

1)加入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zhan</groupId>
    <artifactId>sync-in-detail</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SyncInDetail</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.11.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.9</version>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.11.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2)创建redisson.yml文件配置相关属性
可参考redisss官网

#Redisson配置
singleServerConfig:
  idleConnectionTimeout: 10000
  pingTimeout: 1000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  reconnectionTimeout: 3000
  failedAttempts: 3
  password: null
  subscriptionsPerConnection: 5
  clientName: null
  address: "redis://192.168.1.101:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 50
  connectionMinimumIdleSize: 32
  connectionPoolSize: 64
  database: 0
  #在最新版本中dns的检查操作会直接报错 所以直接注释掉
  #dnsMonitoring: false
  dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
"transportMode": "NIO"

==注:这里有个坑,就是左后一行需要在冒号后加一个空格==

五、编写测试代码

package com.zhan.syncindetail.service;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

/**
 * @author zhan
 * @since 2020-04-27 15:26
 */
@Service
public class RedissonService {
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void tryLockOnce() {
        String key = "lock_";
        //1. 获取锁
        RLock lock = redissonClient.getLock(key);
        try {
            //加锁,此处使用和java的ReentrantLock类似
            lock.lock();
            //2.执行业务逻辑
            String num = redisTemplate.opsForValue().get("num");
            Integer i = Integer.parseInt(num);
            i = i + 1;
            redisTemplate.opsForValue().set("num",i.toString());
        } finally {
            //3.释放锁
            lock.unlock();
            System.out.println("-----------------释放锁OK==>"+Thread.currentThread().getName());
        }
    }
}

配置redisson

package com.zhan.syncindetail.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;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;

/**
 * @author zhan
 * @since 2020-04-27 14:30
 */
@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() throws IOException {
        Config config = Config.fromYAML(new ClassPathResource("redisson.yml").getInputStream());
        return Redisson.create(config);
    }
}

编写测试接口

package com.zhan.syncindetail.controller;

import com.zhan.syncindetail.service.RedissonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhan
 * @since 2020-04-27 15:24
 */
@RestController
public class RedissonController {

    @Autowired
    private RedissonService redissonService;

    @RequestMapping("incr")
    @ResponseBody
    public String incr() {
        redissonService.tryLockOnce();
        return "controller测试ok";
    }
}

打包放置左面空文件夹中使用cmd命令同时启动多个窗口分别输入命令:

java -jar sync-in-detail-0.0.1-SNAPSHOT.jar
java -jar sync-in-detail-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar sync-in-detail-0.0.1-SNAPSHOT.jar --server.port=8081

六、启动JMeter

3.png 4.png

点击执行可查看执行结果:如下


5.png

结果树报告


7.png
查看redis中执行结果正确值=10000
6.png

总结:完美解决分布式下多线程竞争资源问题。

上一篇下一篇

猜你喜欢

热点阅读