使用Redisson测试分布式锁

一、需要工具

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 第 2 章 SHELL 基础知识2.1 shell脚本我们在上面简单介绍了一下什么是shell脚本,现在我们来进一...
    LiWei_9e4b阅读 1,567评论 0 0
  • Nginx 的配置文件使用的就是一门微型的编程语言,许多真实世界里的 Nginx 配置文件其实就是一个一个的小程序...
    SkTj阅读 4,194评论 0 7
  • 目录结构 一、预先准备工作 1. Linux服务器环境(LAMP)搭建 2. Linux服务器资源监控 ...
    微笑的AK47阅读 1,774评论 0 8
  • 从2009年进入工厂打工,一直到现在,已经有九年的时间了。中间陆陆续续换了几个厂,还做了三年的生意,后来生意经营惨...
    terrywei_0c9e阅读 244评论 0 0
  • 从今天的读书中我了解到一些知识:第一,读书是主动的学习方式。原因很简单,一般人很少随随便便就找本书去读,你所...
    贝字旁的赚阅读 181评论 0 3