Redission和Zookeeper分别实现分布式锁

2022年08月20日10:49:04 科技 1195

redission和zookeeper分别实现分布式锁(windows)

1、Redission实现分布式事务

1.1 前提准备

  • 下载好nginx(windows版本)
  • 下载好Jmeter(模仿高并发)
  • 下载好redis(windows版)

1.2 代码

  • pom文件
<?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.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cn.lanqiao</groupId>
    <artifactId>arcdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>arcdemo</name>
    <description>arcdemo</description>


    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>Spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>Redisson-spring-boot-starter</artifactId>
            <version>3.17.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • 配置文件
  • 因为实现分布式事务,所以一会再启动一个9000端口的该项目
# 应用名称
spring.application.name=arcdemo
# 应用服务 WEB 访问端口
server.port=8000


# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000
  • 在主启动类注入Redisson
package com.example;

import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@SpringBootApplication
@EnableRedisHttpSession
public class ArcdemoApplication {
 

    public static void main(String[] args) {
 
        SpringApplication.run(ArcdemoApplication.class, args);
    }
    @Bean
    public Redisson redission() {
 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(0);
        return (Redisson) Redisson.create(config);
    }

}
  • controller类
package com.example.controller;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.RetryNTimes;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

/**
 * @Author Devere19
 * @Date 2022/8/17 10:41
 * @Version 1.0
 */
@RestController
public class BiSheController {
 

    // private static final String ZK_ADDRESS = "127.0.0.1:2181";
    //
    // private static final String ZK_LOCK_PATH = "/zkLock";
    //
    // static CuratorFramework client = null;
    //
    // static {
 
    //     //连接zk
    //     client = CuratorFrameworkFactory.newClient(ZK_ADDRESS,
    //             new RetryNTimes(10, 5000));
    //     client.start();
    // }

    // 分布式锁
    @Autowired
    private Redisson redisson;

    @Resource
    private StringRedisTemplate StringRedisTemplate;


    @GetMapping("/login")
    public String login(String username, HttpSession session, HttpServletRequest request) {
 
        session.setAttribute("username", username);
        return username + ",端口" + request.getLocalPort();
    }

    @GetMapping("/getUser")
    public String getUser(HttpSession session, HttpServletRequest request) {
 
        String username = (String) session.getAttribute("username");
        return session.getId() + "," + username + ",端口" + request.getLocalPort();
    }

    @PostMapping("/checkTeacher")
    public String checkteacher(String teacherName) {
 
        // SpringBoot操作Redis
        String lockKey = "lockKey";
        RLock redissonLock = null;
        String num = "";
        try {
 
            redissonLock = redisson.getLock("lockKey");//加锁
            redissonLock.tryLock(30, TimeUnit.SECONDS);//超时时间:每间隔10秒(1/3)
            num = stringRedisTemplate.opsForValue().get(teacherName);
            int n = Integer.parseInt(num);

            if (n > 0) {
 
                n = n - 1;
                stringRedisTemplate.opsForValue().set("lkz", n + "");
                //正常选择老师
                System.out.println("当前名额:" + n);
            } else {
 
                return "名额已满";
            }
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        } finally {
 
            redissonLock.unlock();//释放锁
        }
        return num;
    }
    // @PostMapping("/checkTeacher")
    // public String checkteacher(String teacherName) {
 
    //     InterProcessMutex lock = new InterProcessMutex(client, ZK_LOCK_PATH);
    //     String num = "";
    //     try {
 
    //         if (lock.acquire(6000, TimeUnit.SECONDS)) {
 
    //             // System.out.println("拿到了锁");
    //             //业务逻辑
    //             num = stringRedisTemplate.opsForValue().get(teacherName);
    //             int n = Integer.parseInt(num);
    //             if (n > 0) {
 
    //                 n = n - 1;
    //                 stringRedisTemplate.opsForValue().set("lkz", n + "");
    //                 //正常选择老师
    //                 System.out.println("当前名额:" + n);
    //             } else {
 
    //                 return "名额已满";
    //             }
    //             // System.out.println("任务完毕,该释放锁了");
    //         }
    //     } catch (Exception e) {
 
    //         System.out.println("业务异常");
    //         e.printStackTrace();
    //     }finally {
 
    //         try {
 
    //             lock.release();
    //         } catch (Exception e) {
 
    //             System.out.println("释放锁异常");
    //             e.printStackTrace();
    //         }
    //     }
    //     return num;
    // }
}
  • redis需要有对应的key
set lkz 6

Redission和Zookeeper分别实现分布式锁 - 天天要闻

1.3 启动项目

  • 第一步:启动redis,并且给lkz赋值
  • 第二步:启动nginx,nginx需要做配置,指向本地的8000和9000端口
upstream testdev{
            server   127.0.0.1:8000 weight=1;
            server   127.0.0.1:9000 weight=1;
   }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://testdev;
            proxy_redirect default;
        }
  • 第三步:idea中启动8000端口,并且再修改配置文件端口,再启动9000端口

Redission和Zookeeper分别实现分布式锁 - 天天要闻

点击这个,然后修改9000即可同时启动8000和9000端口

  • 第三步:启动Jmeter,发请求

Redission和Zookeeper分别实现分布式锁 - 天天要闻

Redission和Zookeeper分别实现分布式锁 - 天天要闻

1.4 结果

Redission的结果自行查看,博主偷懒了在下面的zookeeper实现分布式锁的结果才截图了。

2、Zookeeper实现分布式锁

2.1 前提准备

  • 下载好nginx(windows版本)
  • 下载好Jmeter(模仿高并发)
  • 下载好redis(windows版)
  • 下载好zookeeper(windows版本)和ZooInspector(可视化工具,也可以不下载)

2.2 代码

  • pom文件
<?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.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cn.lanqiao</groupId>
    <artifactId>arcdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>arcdemo</name>
    <description>arcdemo</description>


    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.17.5</version>
        </dependency>
    <!--    zookeeper和curator-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.3.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • controller
package com.example.controller;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.RetryNTimes;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

/**
 * @Author Devere19
 * @Date 2022/8/17 10:41
 * @Version 1.0
 */
@RestController
public class BiSheController {
 

    private static final String ZK_ADDRESS = "127.0.0.1:2181";

    private static final String ZK_LOCK_PATH = "/zkLock";

    static CuratorFramework client = null;

    static {
 
        //连接zk
        client = CuratorFrameworkFactory.newClient(ZK_ADDRESS,
                new RetryNTimes(10, 5000));
        client.start();
    }

    // 分布式锁
    // @Autowired
    // private Redisson redisson;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @GetMapping("/login")
    public String login(String username, HttpSession session, HttpServletRequest request) {
 
        session.setAttribute("username", username);
        return username + ",端口" + request.getLocalPort();
    }

    @GetMapping("/getUser")
    public String getUser(HttpSession session, HttpServletRequest request) {
 
        String username = (String) session.getAttribute("username");
        return session.getId() + "," + username + ",端口" + request.getLocalPort();
    }

    // @PostMapping("/checkTeacher")
    // public String checkteacher(String teacherName) {
 
    //     // SpringBoot操作Redis
    //     String lockKey = "lockKey";
    //     RLock redissonLock = null;
    //     String num = "";
    //     try {
 
    //         redissonLock = redisson.getLock("lockKey");//加锁
    //         redissonLock.tryLock(30, TimeUnit.SECONDS);//超时时间:每间隔10秒(1/3)
    //         num = stringRedisTemplate.opsForValue().get(teacherName);
    //         int n = Integer.parseInt(num);
    //
    //         if (n > 0) {
 
    //             n = n - 1;
    //             stringRedisTemplate.opsForValue().set("lkz", n + "");
    //             //正常选择老师
    //             System.out.println("当前名额:" + n);
    //         } else {
 
    //             return "名额已满";
    //         }
    //     } catch (InterruptedException e) {
 
    //         e.printStackTrace();
    //     } finally {
 
    //         redissonLock.unlock();//释放锁
    //     }
    //     return num;
    // }
    @PostMapping("/checkTeacher")
    public String checkteacher(String teacherName) {
 
        InterProcessMutex lock = new InterProcessMutex(client, ZK_LOCK_PATH);
        String num = "";
        try {
 
            if (lock.acquire(6000, TimeUnit.SECONDS)) {
 
                // System.out.println("拿到了锁");
                //业务逻辑
                num = stringRedisTemplate.opsForValue().get(teacherName);
                int n = Integer.parseInt(num);
                if (n > 0) {
 
                    n = n - 1;
                    stringRedisTemplate.opsForValue().set("lkz", n + "");
                    //正常选择老师
                    System.out.println("当前名额:" + n);
                } else {
 
                    return "名额已满";
                }
                // System.out.println("任务完毕,该释放锁了");
            }
        } catch (Exception e) {
 
            System.out.println("业务异常");
            e.printStackTrace();
        }finally {
 
            try {
 
                lock.release();
            } catch (Exception e) {
 
                System.out.println("释放锁异常");
                e.printStackTrace();
            }
        }
        return num;
    }
}

2.3 启动项目

  • 第一步:启动redis,并且给lkz赋值
  • 第二步:启动nginx,nginx需要做配置,指向本地的8000和9000端口
upstream testdev{
            server   127.0.0.1:8000 weight=1;
            server   127.0.0.1:9000 weight=1;
   }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://testdev;
            proxy_redirect default;
        }
  • 第三步:idea中启动8000端口,并且再修改配置文件端口,再启动9000端口

Redission和Zookeeper分别实现分布式锁 - 天天要闻

点击这个,然后修改9000即可同时启动8000和9000端口

  • 第三步:启动zookeeper,并且启动ZooInspector可视化工具
  • 第四步:启动Jmeter,发请求

Redission和Zookeeper分别实现分布式锁 - 天天要闻

Redission和Zookeeper分别实现分布式锁 - 天天要闻

2.4 结果

Redission和Zookeeper分别实现分布式锁 - 天天要闻

Redission和Zookeeper分别实现分布式锁 - 天天要闻

看到控制台的输出,可以看出来分布式锁起作用了,并且可以观看ZooInspector进行查看

Redission和Zookeeper分别实现分布式锁 - 天天要闻

因为这里采用的是有序临时锁,所以请求发完之后就删除了锁。必须在发起请求的一瞬间去刷新,才可能看到排好序的锁。

3、 案例源码地址

https://github.com/Guoleyuan/arcdemo

科技分类资讯推荐

所谓“大而美”法案或将继续扩大美债规模 - 天天要闻

所谓“大而美”法案或将继续扩大美债规模

美国所谓“大而美”法案7月1日在国会参议院得到通过,当前还需要得到众议院的通过才能提交给美国总统签字。如果该法案最终通过并成为法律,预计将对已创下纪录的美国联邦政府债务增加压力。美国国会预算办公室估....
解码哈药618 突围路径:从产品矩阵到生态构建的行业示范 - 天天要闻

解码哈药618 突围路径:从产品矩阵到生态构建的行业示范

当 2025 年 "618" 电商大促成为检验消费市场韧性的试金石,哈药以国民药企的战略定力与创新突破,构建起一套 "传统赛道筑基 + 新兴领域破局" 的增长模型。在保健品行业竞争白热化的背景下,这家企业通过多品牌协同、产品创新迭代与数字化营销破圈,不仅巩固了细分市场领导地位,更以全链路生态布局为大健康产业提供了可复制...
更快,更强,更纯粹!超薄极致电竞利器ROG绝神OLED显示器 - 天天要闻

更快,更强,更纯粹!超薄极致电竞利器ROG绝神OLED显示器

熟悉鼠鼠我的朋友都知道我是一个游戏爱好者,无论是喊上朋友们一起开黑还是自己沉浸式体验制作精良的3A大作,都能在平时繁重的牛马生活之余带给我放松和快乐。作为重度游戏爱好者,外设的选择自然是马虎不得,这其中我最为看重的就是能够直接影响平时游戏体
坐飞机和高铁分别可以携带什么样的充电宝? - 天天要闻

坐飞机和高铁分别可以携带什么样的充电宝?

来源:【江西发布】近日民航局禁止携带没有3C标识、被召回范围的充电宝上机规定引发关注坐飞机和高铁分别可以携带什么样的充电宝?充电宝上飞机乘坐飞机时,充电宝只能在手提行李中携带或随身携带,严禁在托运行李中携带。
小米YU7“封神” 国产新能源汽车“新王换旧王” - 天天要闻

小米YU7“封神” 国产新能源汽车“新王换旧王”

摘要:新能源的新格局,雏形已现。凤凰网科技 出品2025年6月26日夜晚,小米旗下首款SUV车型小米YU 7正式发布。这款以豪华、高性能、极致体验、先进安全性为特征的SUV车型,犹如一颗重磅核弹投入本就不平静的新能源车市,激起千层浪。
百度前副总裁璩静开医美诊所,人均消费2218元 - 天天要闻

百度前副总裁璩静开医美诊所,人均消费2218元

红星资本局7月2日消息,百度前副总裁璩静在华为总部坂田基地附近开了一家医美诊所。据公开资料,璩静名下新增一家存续企业——深圳大为诊所。该诊所成立于2024年12月23日,璩静持股比例为100%,认缴出资额为100万元,经营范围为诊所服务等。
千里智行,常用常新,传祺向往S7 开启重磅OTA升级 - 天天要闻

千里智行,常用常新,传祺向往S7 开启重磅OTA升级

7月2日,传祺向往S7 OTA如期而至,OTA 2.0版本正式全量推送。本次升级新增16项功能,31项 功能升级和57项体验优化,主要涉及智能座舱、智能辅助驾驶、娱乐系统、车机交互等多个维度,旨在为用户提供常用常新的出行体验,功能强大又好用。
九州风神推出大霜塔棱镜风冷散热器:双塔棱镜顶盖,209 元 - 天天要闻

九州风神推出大霜塔棱镜风冷散热器:双塔棱镜顶盖,209 元

IT之家 7 月 3 日消息,九州风神 DeepCool 现已推出大霜塔棱镜 (AG620 ARGB V2) 风冷散热器。其采用双塔双风扇六热管直触设计,双塔顶部均配有 ARGB 灯效“棱镜顶盖”。大霜塔棱镜长宽高 129×136×162 (mm),支持 45mm 高内存条。其六根 6mm 双向恒定热平衡热管采用 CTT 2.0 核心触控技术在塔体底部并管排