Redisson

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。简单说就是redis在分布式系统上工具的集合,Redission提供了分布式锁的多种多样的功能.

使用redission

自定义redis分布式锁无法自动续期,比如,一个锁设置了1分钟超时释放,如果拿到这个锁的线程在一分钟内没有执行完毕,那么这个锁就会被其他线程拿到,可能会导致严重的线上问题,在秒杀场景下,很容易因为这个缺陷导致的超卖了。

redission 超时时间1m 执行逻辑的时候3m

Redisson 锁加锁流程:

线程去获取锁,获取成功则执行lua脚本,保存数据到redis数据库。如果获取失败: 一直通过while循环尝试获取锁(可自定义等待时间,超时后返回失败)。Redisson提供的分布式锁是支持锁自动续期的,也就是说,如果线程仍旧没有执行完,那么redisson会自动给redis中的目标key延长超时时间,这在Redisson中称之为 Watch Dog 机制。

java中的使用

引入redisson相关jar

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--配置redission-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.12.5</version>
        </dependency>

application文件

# 设置redis的信息
spring.redis.host=192.168.253.16
spring.redis.database=0
spring.redis.password=root
spring.redis.port=6379

配置类:



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;

@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Value("${spring.redis.password}")
    private String redisPassword;

    @Bean
    public RedissonClient getRedisson(){

        Config config = new Config();
// //多节点config.useClusterServers()
        //单机模式  依次设置redis地址和密码
        config.useSingleServer().
                setAddress("redis://" + host + ":" + port).
                setPassword(redisPassword);
        return Redisson.create(config);
    }
}

controller(控制层)

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
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 java.util.Objects;

@RestController
@RequestMapping("/redisLock")
public class RedisLockController {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedissonClient redisson;

    private static final String REDIS_KEY = "redis_test";

    private static final int MAX_SIZE = 10;

    /**
     * 初始化库存
     */
    @PostMapping("/init")
    public void init() {
        stringRedisTemplate.opsForValue().set(REDIS_KEY, String.valueOf(MAX_SIZE));
    }

    /**
     * 扣库存业务
     */
    @PostMapping("/test")
    public void exportInventory() {

        String lockKey = "product001";
        RLock lock = redisson.getLock(lockKey);
        try {
            lock.lock();
            int s = Integer.parseInt(Objects.requireNonNull(stringRedisTemplate.opsForValue().get(REDIS_KEY)));
            System.out.printf("1号服务:库存当前为:" + s + "\n");
            //stringRedisTemplate.opsForValue().set(REDIS_KEY, String.valueOf(s));
            if(s>0) {
                stringRedisTemplate.opsForValue().decrement(REDIS_KEY);
            }
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }
}

使用jmeter测试:

写两个一模一样的项目 通过jmeter访问 redisLock/test

两个服务中的数据不重复即可

Logo

鸿蒙生态一站式服务平台。

更多推荐