分布式锁Redisson,完美解决高并发问题

levis
2021-09-13 / 0 评论 / 150 阅读 / 正在检测是否收录...

我们的活动遇到了性能问题,原先的单机锁性能太差,以下单购买商品为例,我们考虑使用分布式锁,但传统的方式为了使用Redis锁,我们需要设置一个定长的key,然后当购买完成后,将key删除。但为了防止key提前过期,我们不得不新增一个线程执行定时任务。现在我们可以使用Redissson框架简化代码。getLock()方法代替了Redis的setIfAbsent(),lock()设置过期时间。最终我们在交易结束后释放锁。延长锁的操作则有Redisson框架替我们完成,它会使用轮询去查看key是否过期,在交易没有完成时,自动重设Redis的key过期时间。

1.引入依赖:

<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson</artifactId>
  <version>3.11.5</version>
</dependency>

2.配置redisson

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * redisson配置
 * 目前使用的是腾讯云的单节点redis,因此暂时配置单服务
 *
 *
 */
@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private String port;
    @Value("${spring.redis.password}")
    private String password;
    @Bean
    public RedissonClient getRedisson(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
        //添加主从配置
        //config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""});
        return Redisson.create(config);
    }
}

3.示例代码

import org.redisson.api.RedissonClient;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BuyRedissonLock {
    @Autowired
    private RedissonClient redissonClient;
    @GetMapping(value = "buy")
    public String get() {
      RLock ztLock = redissonClient.getLock("ztLock");
      // ztLock.lock(3, TimeUnit.SECONDS); 指定了超时时间的话,使用指定的,
      ztLock.lock(); //没指定的话使用30s,有看门狗,延迟10秒执行,循环延期
      // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
      boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
      if (res) {
        try {
           //TODO... 业务逻辑代码
        } finally {
            ztLock.unlock();
        }
        return "";
    }
}
}

4、几点说明

  • 加锁的时候注意一下锁的粒度,粒度越小性能越好,比如商品的话,可以按照商品id进行锁。
  • 为了保证缓存一致性,可以使用读写锁。
0

评论 (0)

取消