Redis项目实战:分布式锁+微服务自旋

Redis项目实战测试

1.在分布式系统下如何控制缓存

Redis项目实战:分布式锁+微服务自旋_第1张图片

2.rides锁环境搭建测试

1.在service新建service-test模块

Redis项目实战:分布式锁+微服务自旋_第2张图片

2.配置application.properties

Redis项目实战:分布式锁+微服务自旋_第3张图片

启动win版本的redis

3.启动类配置

Redis项目实战:分布式锁+微服务自旋_第4张图片

4.controller测试

@RestController
public class TestRedis {
    @Autowired
    private RedisTemplate redisTemplate;
    //测试redis缓存
    @GetMapping("/testLock")
    public String testLock(){
        System.out.println("正在请求微服务");
        //获取缓存中的值
        String stock = redisTemplate.opsForValue().get("stock").toString();
        int i = Integer.parseInt(stock);
        if (i>0){
            i--;
            //算术运算后,设置剩余数
            redisTemplate.opsForValue().set("stock", i);
            System.out.println("商品目前剩余数量:"+i);
        }else {
            System.out.println("商品已抢完");
        }
        return "快快抢购吧";
    }
}

初始化redis中的key的值

Redis项目实战:分布式锁+微服务自旋_第5张图片

5.配置nginx负载均衡

Redis项目实战:分布式锁+微服务自旋_第6张图片

proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for nginx转发请求的真实ip

6.启动三个微服务

在这里插入图片描述
Redis项目实战:分布式锁+微服务自旋_第7张图片
Redis项目实战:分布式锁+微服务自旋_第8张图片
Redis项目实战:分布式锁+微服务自旋_第9张图片
Redis项目实战:分布式锁+微服务自旋_第10张图片
然后修改端口号,启动服务
Redis项目实战:分布式锁+微服务自旋_第11张图片

7.使用压力测试工具测试

下载https://www.apachehaus.com/cgi-bin/download.plx

解压后,找到安装目录下的httpd.conf,修改为自己的安装目录
Redis项目实战:分布式锁+微服务自旋_第12张图片
apacheab压测工具 ,运行bin下的httpd.exe

在这里插入图片描述

再打开一个cmd进入bin目录

输入压测命令

ab -c 20 -n 100 http:nginx负载均衡/压力方法

具体命令ab -c 10 -n 100 http://localhost/testLock

8测试结果,节点存在并发

Redis项目实战:分布式锁+微服务自旋_第13张图片

2. redis自带的分布式锁setnx + 微服务方法自旋处理

1.方案一:是用分布式锁加方法自旋

使用redis分布式锁,主要使用了redis中的setnx,这个方法在redisTemplate是setIfAbsent;

redis中的setnx设置相同的key只能一个,被设置了就不能被别人设置,在redisTemplate中如果设置成功会返回true,没有设置成功返回false
Redis项目实战:分布式锁+微服务自旋_第14张图片

@RestController
public class TestRedis {
    @Autowired
    private RedisTemplate redisTemplate;

    //测试redis缓存中使用分布式锁
    @GetMapping("/testLockNx")
    public String testLock(){
        System.out.println("正在请求微服务");
        //设置分布式锁
        Boolean stcokLock = redisTemplate.opsForValue().setIfAbsent("stcokLock", 1, 3, TimeUnit.SECONDS);//3秒钟分布式锁过期
        //判断是否获取分布式锁的key,拿到锁就可以操作数据库(缓存)
        if (stcokLock){
            //获取缓存中的值(这边也可以是查数据库)
            String stock = redisTemplate.opsForValue().get("stock").toString();
            int i = Integer.parseInt(stock);
            if (i>0){
                i--;
                //算术运算后,设置剩余数
                redisTemplate.opsForValue().set("stock", i);
                System.out.println("商品目前剩余数量:"+i);
            }else {
                System.out.println("商品已抢完");
            }
            redisTemplate.delete("stcokLock");//操作完成后,释放分布式锁
        }else{
            //没有分布式锁,等待,进入自旋
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return testLock();//自旋
        }
        return "快快抢购吧";
    }
}

2.问题一:在当前线程删除分布式锁的同时如果正好分布式锁过期,则会删除其他线程的锁,造成并发

3.方案二:使用uuid作为值,当线程要删除时先获取值,看是否是自己的锁

在这里插入图片描述
Redis项目实战:分布式锁+微服务自旋_第15张图片

你可能感兴趣的:(Redis,redis,分布式,缓存)