博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis分布式锁逐步完善过程,最后推荐Redisson框架
阅读量:3927 次
发布时间:2019-05-23

本文共 2815 字,大约阅读时间需要 9 分钟。

为什么需要分布式锁?

我们在单机情况下我们可以通过Synchronized或Reentrantlock来实现并发安全,但是现在分布式项目怎么保证并发安全,就要通过分布式锁。

zookeeper和redis能实现分布式锁(推荐redis)

为什么可以通过这两个组件能实现分布式锁?

因为组件是全局的,可以对一个值的有无去判断锁。再加上redis是单线程的

小型互联网公司用下面代码做分布式锁妥妥的~

package com.heyun.stadium.module.stadium.controller;import com.heyun.stadium.common.core.exception.HeyunException;import lombok.extern.slf4j.Slf4j;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.Objects;import java.util.UUID;import java.util.concurrent.TimeUnit;/** * @author zhazhenglin * @date 2021/5/25 18:55 */@RestController@Slf4jpublic class RedisLockController {    @Resource    //注入redisTemplate    private RedisTemplate
redisTemplate; /** * 注意的细节: * 1、过期时间:为了防止程序因为某些原因没有将锁释放掉,造成死锁,如部署的时候,刚好在执行然后没有释放锁 * 2、lockValue:值为uuid,因为有可能有时候代码阻塞住,过期时间过了,另外一个线程获得锁之后。前面的线程把锁删了,这样就循环失效了 */ @PostMapping public void deductStock(){ //建议将lockKey写成常量 String lockKey = "product:deductStock:001"; String lockValue = UUID.randomUUID().toString(); try { //如果redis中有当前key,返回false,如果redis中没有当前key,保存key和value,返回true,并且过期时间为30秒 Boolean result = redisTemplate.opsForValue().setIfPresent(lockKey, lockValue, 30, TimeUnit.SECONDS); //如果result为false则说明没有抢到锁 if (!result){ //这里是我自己包装的异常,这里的逻辑视情况而定 throw new HeyunException("未抢到分布式锁"); } //业务逻辑开始-------------------- int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock")); if (stock > 0){ int currentStock = stock - 1; redisTemplate.opsForValue().set("stock", String.valueOf(currentStock)); log.warn("扣减库存成功~"); }else { log.warn("扣减库存失败~"); } //业务逻辑结束-------------------- }finally { //业务结束后需要释放锁 if (Objects.equals(redisTemplate.opsForValue().get(lockKey), lockValue)){ redisTemplate.delete(lockKey); } } }}

最后还有一个问题是,业务逻辑执行时间过长,不能将锁续命功能,这个情况很少见,小型互联公司基本用不到。

Redisson

在这个框架里基本帮我们完善了分布式锁的功能,而且使用起来就跟Reentrantlock一样简单。

1、引入jar包

1 
2
org.redisson
3
redisson
4
3.11.1
5

2、配置(这里是redis集群) 

    @Configuration

    public static class RedissonConfig{

        @Bean
        RedissonClient redisson() throws IOException {
            Config config = new Config();

            //模式可以选择自己的,api还是见名知意的

            config.useClusterServers()
                  .addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
            return Redisson.create(config);
        }
    }

3、使用 

//伪代码,跟Reentrantlock一样,显示使用锁。

//获取一把锁RLock lock = redisson.getLock(lockKey);//加锁lock.lock();//业务逻辑//释放锁lock.unlock();

转载地址:http://oikgn.baihongyu.com/

你可能感兴趣的文章
进程、线程、纤程
查看>>
代码详解のJava面向对象特性之多态
查看>>
互金平台使用redis分布式锁的场景分析
查看>>
代码详解のArrayList
查看>>
代码详解のLinkedList原码分析和ArrayList比较
查看>>
代码详解のTreeMap实现原理
查看>>
缓存架构设计细节之“淘汰缓存”还是“更新缓存”
查看>>
Java实现两个线程交替打印问题
查看>>
Java序列化的几种特殊情景
查看>>
JSP热部署的实现原理
查看>>
class卸载、热替换和Tomcat的热部署的分析
查看>>
精通 Groovy
查看>>
通过注解使用Hystrix
查看>>
实现int转换String的思路
查看>>
Java技术树
查看>>
面试中常见的SQL优化问题
查看>>
代码详解のThread.join()实现多个线程顺序执行
查看>>
vert.x线程安全的线程模型详解
查看>>
vertx框架编程思想
查看>>
你所不知道的TIME_WAIT和CLOSE_WAIT
查看>>