【Redis】之 Redisson初探


一、简介


Based on high-performance async and lock-free Java Redis client and Netty framework.

基于高能性异步锁自由Java Redis客户端 和 Netty框架

参数配置:https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95


(1)SpringBoot2.x配置Redisson注意事项

SpringBoot2.x默认使用Lettuce

冲突:

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

// 会与下面这个冲突,二者存一
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.11.2</version>
</dependency>

若加入redisson-spring-boot-starter,里面会排除lettuce

// 此配置会排除 Lettuce,
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

二、Demo 测试


(1)配置 + 代码

  1. pom.xml
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.11.2</version>
</dependency>
  1. RedisConfig.java
@Configuration
public class RedisConfig {

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);

        return Redisson.create(config);
    }
}
  1. Demo
@RestController
@RequestMapping("/redisson")
public class RedissonController {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisDao redisDao;

    @RequestMapping(value = "/sku/init")
    public String initSku() {

        redisDao.setString("product_sku", "4000");

        return "初始化库存成功";
    }

    @RequestMapping("/sku/reduce")
    public void reduce() {
        RLock lock = redissonClient.getLock("product_sku");
        boolean locked = false;
        try {
            locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
            if (locked) {
                System.out.println("获取锁成功。。。");
            } else {

                System.out.println("获取锁失败。。。");
            }

            int sku = Integer.parseInt(redisDao.get("product_sku"));

            if (--sku < 0) {
                System.out.println("库存不足。。。");
                return;
            }

            redisDao.setString("product_sku", Integer.toString(sku));

            System.out.println("减库存成功: " + sku);

        } catch (InterruptedException e) {
            e.printStackTrace();

        } finally {
            if (!locked) {
                System.out.println("获取锁失败。。。");
            }
            lock.unlock();
        }
    }
}

(2)nginx 负载均衡

  1. sudo docker pull nginx

  2. sudo docker run --name=nginx -p 8000:80 -d nginx

访问localhost:8000,即可访问 nginx 页面

  1. 挂载运行
# ro:只读
sudo docker run --name=nginx -p 80:80 \
-v /home/donald/Documents/Docker/Nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-d nginx
    upstream redis {
        server 192.168.0.143:8080;
        server 192.168.0.143:8081;
    }

    server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass   http://redis;
        }
    }
  1. sudo docker exec -it nginx bash 运行

(3)压测

采用 ab 压测

sudo docker run --rm jordi/ab -k -c 200 -n 4000 http://192.168.0.143:8080/redisson/sku/reduce
  1. 使用lock.lock( 10, TimeUnit.SECONDS);
    在此压测情况下,库存可刚好消费完

压测结果如图:

在这里插入图片描述

  1. 使用locked = lock.tryLock(1, 10, TimeUnit.SECONDS);
    在此压测情况下,库存大部分情况下均消费不完

压测结果如图:
在这里插入图片描述

且有如下异常:

在这里插入图片描述



三、问题


如图:
在这里插入图片描述

(1)若获得锁后,业务逻辑长时间没有释放锁?

(2)若获得锁后,业务逻辑没有完成而锁过期(释放)?数据不一致?

(3)若要释放锁时,进程挂了等等?

(4)等待锁时,超时后,还没获得锁,之后业务该怎么办?

发布了404 篇原创文章 · 获赞 270 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/fanfan4569/article/details/101859230