前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis实现分布式锁

Redis实现分布式锁

作者头像
用户5927264
发布2021-06-08 21:23:50
3370
发布2021-06-08 21:23:50
举报
文章被收录于专栏:OSChinaOSChina

一看就会的超详细教程:SpringBoot整合MybatisPlus!>>>

1.自己实现

代码语言:javascript
复制
    private static String REDIS_LOCK = "redis_lock";

    @Autowired
    private RedissonClient redission;

 

/**
     * 自定redisLock实现分布式锁,
     * 使用 RedisTemplate + lua脚本实现
     * @return
     */
    @GetMapping("/mylock")
    public String redisLock() {
        String resoult = "";

        long value = System.currentTimeMillis() + Thread.currentThread().getId();
        try {
            //1.原子性的设置锁,并且设置超时时间30s(加分布式锁)
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value, 30l, TimeUnit.SECONDS);
            if (!flag) {
                return "抢占锁失败";
            }

            //2.获取库存数量
            Object obj = redisTemplate.opsForValue().get("goods:100");
            int goodsNum = obj == null ? 0 : Integer.parseInt(obj.toString());
            if (goodsNum > 0) {
                goodsNum = goodsNum - 1;
                //3.把库存-1,并且设置会系统中
                redisTemplate.opsForValue().set("goods:100", String.valueOf(goodsNum));

                //模拟超时40秒
                Thread.sleep(40000);

                resoult = "成功购买到商品,剩余库存:" + goodsNum + " 件商品";
            } else {
                resoult = "商品已经售完/活动结束/调用结束,欢迎下次光临";
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //4.消除分布式锁(使用lua脚本实现删除锁)
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            //指定lua脚本
            redisScript.setScriptText("if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
                    "    return redis.call(\"del\",KEYS[1])\n" +
                    "else\n" +
                    "    return 0\n" +
                    "end");
            // 指定返回类型
            redisScript.setResultType(Long.class);
            // 参数一:redisScript,参数二:key列表,参数三:arg(可多个)
            Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(REDIS_LOCK), value);
            if (result == 1) {
                System.out.println("删除 锁 ok");
            } else {
                System.out.println("删除 锁 error");
            }
        }

        System.out.println(resoult);
        return resoult;
    }

2.使用redisson实现

代码语言:javascript
复制
<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.15.0</version>
        </dependency>
代码语言:javascript
复制
@Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.setTransportMode(TransportMode.EPOLL);
        config.useClusterServers()
                .addNodeAddress("redis://192.168.2.13:6379");
        return Redisson.create(config);
    }
代码语言:javascript
复制
package com.un.project.system.controller.app;

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

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * Redis Lock实现分布式锁
 *
 * @author shiye
 * @create 2021-05-28 13:47
 */
@RestController
@RequestMapping("/ws/redis")
public class MyRedisLockController {


    private static String REDIS_LOCK = "redis_lock";

    @Autowired
    private RedissonClient redission;



    @GetMapping("/redissonlock")
    public String redissonLock() {
        String resoult = "";

        long value = System.currentTimeMillis() + Thread.currentThread().getId();
        //1.使用Redisson来加锁
        RLock redissionLock = redission.getLock(REDIS_LOCK);
        redissionLock.lock(30, TimeUnit.SECONDS);
        try {
            //2.获取库存数量
            Object obj = redisTemplate.opsForValue().get("goods:100");
            int goodsNum = obj == null ? 0 : Integer.parseInt(obj.toString());
            if (goodsNum > 0) {
                goodsNum = goodsNum - 1;
                //3.把库存-1,并且设置会系统中
                redisTemplate.opsForValue().set("goods:100", String.valueOf(goodsNum));

                //模拟超时41秒
                Thread.sleep(41000);

                resoult = "成功购买到商品,剩余库存:" + goodsNum + " 件商品";
            } else {
                resoult = "商品已经售完/活动结束/调用结束,欢迎下次光临";
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //4.消除分布式锁(使用lua脚本实现删除锁)
            if (redissionLock.isLocked() && redissionLock.isHeldByCurrentThread()) {
                redissionLock.unlock();
            }
        }

        System.out.println(resoult);
        return resoult;
    }

}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档