美文网首页
使用Redisson测试分布式锁

使用Redisson测试分布式锁

作者: 司展超 | 来源:发表于2020-04-27 18:26 被阅读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

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

    相关文章

      网友评论

          本文标题:使用Redisson测试分布式锁

          本文链接:https://www.haomeiwen.com/subject/bouuwhtx.html