springboot redisson分布式锁

synchronized是jvm级别的线程同步,当项目使用分布式、集群,就需要使用分布式锁

  1. 引入依赖
    
        org.redisson
        redisson-spring-boot-starter
        3.9.0
    
  1. 添加一个redisson的配置文件
#更多配置详情查看 https://github.com/redisson/redisson/wiki/2.-Configuration
singleServerConfig:
  idleConnectionTimeout: 10000
  pingTimeout: 1000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  reconnectionTimeout: 3000
  failedAttempts: 3
  #密码
  password:
  subscriptionsPerConnection: 5
  clientName: null
  #redis地址
  address: "redis://localhost:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 50
  connectionMinimumIdleSize: 32
  connectionPoolSize: 64
  #索引库
  database: 0
  #不注释会注入bean失败
#  dnsMonitoring: false
#  dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: ! {}
transportMode: NIO
  1. 修改application.yml
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    password:
    timeout: 3000ms
    redisson:
      #指定redisson配置文件的位置
      config: classpath:redisson.yml
      
  #使用数据库进行测试
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/admin?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: root
  1. service
@Service
public class UserService {
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private RedissonClient redissonClient;

    public String addUser(SysUser user){
        // 获取锁,以username为锁名称。这样用户名相同的数据添加时,无法并行处理。
        // 第二次的请求需要等到第一次请求的锁释放后才可以继续执行
        RLock lock = redissonClient.getLock(user.getUsername());
        // 默认锁30秒,如果当前线程处理时间过长。
        // redisson会在锁时间过了三分之二的时候将锁的时间重新设置为30秒
        lock.lock();
        //将需要锁住的代码try起来,并在finally中释放锁
        try {
            // 判断用户账号是否重复
            SysUser sysUser = userMapper.selectByUsername(user.getUsername());
            // 如果用户存在,抛出异常
            if (sysUser != null) {
                throw new RuntimeException("用户已经存在");
            }
            // 模拟线程不安全的情况
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 不重复则添加用户
            userMapper.insert(user);
        }finally {
            // 释放锁
            lock.unlock();
        }
        return "success";
    }
}
  1. controller
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("addUser")
    public String addUser(@RequestBody SysUser user){
        return userService.addUser(user);
    }
}
  1. 测试
    开启两个不同端口的服务,使用nginx配置集群,轮询访问。
    当然分布式锁在一个应用中也是可以使用的,测试也可以只启动一个服务,请求两次。
    也可以将锁去除测试一下未上锁的情况。

项目地址


作者博客

作者公众号


在这里插入图片描述

你可能感兴趣的:(springboot redisson分布式锁)