程序员子龙(Java面试 + Java学习) 程序员子龙(Java面试 + Java学习)
首页
学习指南
工具
开源项目
技术书籍

程序员子龙

Java 开发从业者
首页
学习指南
工具
开源项目
技术书籍
  • 基础

  • JVM

  • Spring

  • 并发编程

  • Mybatis

  • 网络编程

  • 数据库

  • 缓存

  • 设计模式

  • 分布式

  • 高并发

  • SpringBoot

    • SpringBoot 整合redis
    • SpringBoot 线程池
    • springboot下整合mybatis
    • spring boot 配置文件的加载顺序
    • springboot启动不加载bootstrap.yml文件的问题解决
    • SpringBoot设置动态定时任务
    • springboot整合hibernate
    • ApplicationRunner、InitializingBean、@PostConstruct使用详解
    • Spring Boot 优雅的参数校验方案
    • ELK处理 SpringBoot 日志,太优雅了!
    • SpringBoot配置数据源
    • Spring Boot 默认数据库连接池 —— HikariCP
    • 数据库连接池Hikari监控
    • Spring Boot中使用AOP统一处理Web请求日志
    • SpringBoot 三大开发工具,你都用过么?
    • Spring Boot 3.2 + CRaC = 王炸!
    • springboot启动的时候排除加载某些bean
    • spring boot中集成swagger
    • springboot项目引入这个包以后把原来的json报文改为了xml格式返回
    • SpringBoot中new对象不能自动注入对象和属性的问题
    • 使用 Spring Boot Actuator 监控应用
    • 记录一次springboot自动任务线上突然不执行问题排查过程
    • SpringBoot定时任务@Scheduled源码解析
    • Spring Boot + Lua = 王炸!
    • Spring Boot 实现定时任务动态管理
    • SpringBoot的@Async注解有什么坑?
    • druid 参数配置详解
    • Spring Boot HandlerMethodArgumentResolver 使用和场景
    • SpringBoot数据加解密
    • 解决controller层注入的service为null
    • 在 Spring Boot 中通过 RequestBodyAdvice 统一解码请求体
    • SpringBoot之使用Redisson实现分布式锁(含完整例子)
      • RedissonConfig配置类 来配置redisson
        • 写一个简单的测试请求
        • 编写一个砍价接口
        • 使用ab做接口测试
        • 测试完成 price 价格减到0 之后就没有在减少了 !img
  • SpringCloudAlibaba

  • Nginx

  • 面试

  • 生产问题

  • 系统设计

  • 消息中间件

  • Java
  • SpringBoot
程序员子龙
2024-09-26
目录

SpringBoot之使用Redisson实现分布式锁(含完整例子)

# SpringBoot之使用Redisson实现分布式锁(含完整例子)

分布式环境有很多问题,比如你前一个请求访问的是服务器A,第二个请求访问到了服务器B,就会发生并发重复插入问题,这个时候需要依赖单点来实现分布锁,而redis就是。   Redisson的分布式锁的实现,一般提及到Redis的分布式锁我们更多的使用的是Redisson的分布式锁,Redis的官方也是建议我们这样去做的。Redisson点我可以直接跳转到Redisson的官方文档

# 引入Maven依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.10.6</version>
</dependency>
1
2
3
4
5

注意:我这里引入的是redisson和springboot的集成包,网上一些教程可能是引入如下配置

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.6.1</version>
</dependency>
1
2
3
4
5

# 配置redis信息

spring:
  redis:
    host: ${
   REDIS_URL:192.168.6.52}
    port: ${
   REDIS_PORT:6379}
    password: ${
   REDIS_PWD:123456}
1
2
3
4
5
6
7
8

# 配置redisson

img   新建一个redisson-single.yml的配置文件 下面是单机配

singleServerConfig:
  idleConnectionTimeout: 10000
  pingTimeout: 1000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  reconnectionTimeout: 3000
  failedAttempts: 3
  password: 123456
  subscriptionsPerConnection: 5
  clientName: null
  address: "redis://192.168.6.52: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> {
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# RedissonConfig配置类 来配置redisson

/**
 * @author tbb
 *
 */
@Configuration
public class RedssonConfig
{
   
	@Bean(destroyMethod = "shutdown")
	public RedissonClient redisson() throws IOException
	{
   
		RedissonClient redisson = Redisson.create(Config.fromYAML(new ClassPathResource("redisson-single.yml").getInputStream()));
		return redisson;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

或者使用如下配置类

/**
 * @author tbb
 *
 */
@Configuration
public class RedssonConfig
{
   
	    @Bean
	    public RedissonClient getRedisson() 
	    {
   
	        Config config = new Config();
	        config.useSingleServer()
	                .setAddress("redis://127.0.0.1:6379").setPassword("123456")
	                .setRetryInterval(5000)
	                .setTimeout(10000)
	                .setConnectTimeout(10000);
	        return Redisson.create(config);
	    }



}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 写一个简单的测试请求

@ApiOperation("分布式锁测试")
@ResponseBody
@GetMapping("test")
public String createOrderTest() 
{

    return entityService.decreasePrice("1234-1234-1234", 1);
}
1
2
3
4
5
6
7
8

# 编写一个砍价接口

@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class ShwzTestService extends CrudService<ShwzTestDao, ShwzTest, String>
{
   

	@Autowired
	private RedissonClient redissonClient;

	public String decreasePrice(String productId, Integer productQuantity)
	{
   
		String key = "dec_store_lock_" + productId;
		RLock lock = redissonClient.getLock(key);
		ShwzTest entity = new ShwzTest();
		entity.setId(productId);
		ShwzTest shwzTest = this.get(entity);
		lock.lock();
		// 加锁 操作很类似Java的ReentrantLock机制
		try
		{
   
			
			// 简单减价操作 没有重新写其他接口了
			if (shwzTest.getPrice() == 0)
			{
   
				return "当前价格为0,不能在减了!!";
			}
			shwzTest.setPrice(shwzTest.getPrice() - 1);
			this.save(shwzTest);
		}
		catch (Exception e)
		{
   
			System.out.println(e.getMessage());
		}
		finally
		{
   
			// 解锁
			lock.unlock();
		}
		String result = "当前价格:" + shwzTest.getPrice();
		return result;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 使用ab做接口测试

ab -c 1000 -n 1000 -H "Authorization:bearer46a2b87f-0f8a-477d-bcaf-dad144860a23" http://192.168.0.6:7001/a/shwz/shwzTest/test
1

img

ab -n 300 -c 300 请求地址
-n 的含义就是你做多少个请求
-c 的含义就是多少个用户并发请求
-H  的含义就是请求的Header头文件
1
2
3
4

# 测试完成 price 价格减到0 之后就没有在减少了 img

上次更新: 2024/10/09, 22:49:20
在 Spring Boot 中通过 RequestBodyAdvice 统一解码请求体
Spring Cloud 入门篇

← 在 Spring Boot 中通过 RequestBodyAdvice 统一解码请求体 Spring Cloud 入门篇→

最近更新
01
一个注解,优雅的实现接口幂等性
11-17
02
MySQL事务(超详细!!!)
10-14
03
阿里二面:Kafka中如何保证消息的顺序性?这周被问到两次了
10-09
更多文章>
Theme by Vdoing | Copyright © 2024-2024

    辽ICP备2023001503号-2

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式