`

spring boot 利用redisson实现redis的分布式锁(二)

 
阅读更多

 接上篇 http://liaoke0123.iteye.com/blog/2375469

 

有的朋友可能会问,如果一个获得一个锁,执行一个耗时任务,耗时任务耗时大于锁默认的放锁时间,那么会怎么样。

 

redisson其实已经自动放锁了,避免饿死锁。

 

在超时上,我们业务也能不允许,所以我添加了fallback策略。

 

同样的分布式锁回调接口

 

 

package com.example.demo.redis2;

import javax.persistence.Transient;

/**
 * 分布式锁回调接口
 *
 * @author lk
 */
public interface DistributedLockCallback<T> {

    /**
     * 调用者必须在此方法中实现需要加分布式锁的业务逻辑
     *
     * @return
     */
    public T process();

    /**
     * 调用者业务
     * 当超时的时候业务降级
     * 与process一同使用
     */
    public T fallback();

    /**
     * 得到分布式锁名称
     *
     * @return
     */
    public String getLockName();
}

 可以看见我新建了fallback接口

 

 

package com.example.demo.redis2.service;

import com.example.demo.redis2.DistributedLockCallback;
import com.example.demo.redis2.DistributedLockTemplate;
import com.example.demo.redis2.dao.TestEntityRepository;
import com.example.demo.redis2.entity.TestEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;

/**
 * Created by LiaoKe on 2017/5/22.
 */
@Service
public class AsyncService {

    @Resource
    TestEntityRepository ts;


    @Resource
    DistributedLockTemplate distributedLockTemplate;

    /**
     * 加锁
     */
    @Async
    @Transactional
    public void addAsync(){
        distributedLockTemplate.lock(new DistributedLockCallback<Object>(){
            @Override
            public Object process() {
                add();
                return null;
            }

            @Override
            public Object fallback() {
                reduce();
                return null;
            }

            @Override
            public String getLockName() {
                return "MyLock";
            }
        });
    }

    /**
     * 未加锁
     */
    @Async
    public void addNoAsync(){
        add();
    }

    /**
     * 测试异步方法
     * 在不加分布式锁的情况下
     * num数目会混乱
     */
    @Async
    public void add(){
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(ts.findAll().size()==0){
            TestEntity  t  =  new TestEntity();
            t.setNum(1);
            ts.saveAndFlush(t);
        }else{
            TestEntity dbt = ts.findAll().get(0);
            dbt.setNum(dbt.getNum()+1);
            ts.saveAndFlush(dbt);
        }
    }

    /**
     * fallback
     */
    @Async
    private void reduce(){
        if(ts.findAll().size()==0){
            TestEntity  t  =  new TestEntity();
            t.setNum(1);
            ts.saveAndFlush(t);
        }else{
            TestEntity dbt = ts.findAll().get(0);
            dbt.setNum(dbt.getNum()-1);
            ts.saveAndFlush(dbt);
        }
    }


}
 

 fallback实现了对业务超时的进行的回退,数目减1,并且在方法上加上了@Transactional 事物注解,以防止在fallback发生异常,但是数目缺+1

 

由于我们使用的默认锁设置,超时是5秒,为了模拟超时,我在add()方法中让线程暂停了6秒。我们来看效果。

 

package com.example.demo.redis2;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import javax.persistence.Transient;
import java.util.concurrent.TimeUnit;

/**
 * Single Instance mode 分布式锁模板
 *
 * @author lk
 */
public class SingleDistributedLockTemplate implements DistributedLockTemplate {
    private static final long     DEFAULT_TIMEOUT   = 5;
    private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;

    private RedissonClient    redisson;

    public SingleDistributedLockTemplate() {
    }

    public SingleDistributedLockTemplate(RedissonClient redisson) {
        this.redisson = redisson;
    }

    @Override
    public <T> T lock(DistributedLockCallback<T> callback) {
        return lock(callback, DEFAULT_TIMEOUT, DEFAULT_TIME_UNIT);
    }

    @Override
    public <T> T lock(DistributedLockCallback<T> callback, long leaseTime, TimeUnit timeUnit) {
        RLock lock = null;
        try {
            System.out.println("获取锁.......");
            lock = redisson.getLock(callback.getLockName());
            lock.lock(leaseTime, timeUnit);
            T d = callback.process();
            return d;
        } finally {
            if (lock != null) {
                if(!lock.isHeldByCurrentThread()){
                    System.out.println("超时自动放锁.......");
                    callback.fallback();
                }else{
                    System.out.println("释放锁.......");
                    lock.unlock();
                }
            }

        }
    }

    public void setRedisson(RedissonClient redisson) {
        this.redisson = redisson;
    }

}

 

 

同样的url(见上篇文章)访问结果如下

 

 可见数据库并未+1 ,fallback策略成功。

 

事物是必须加的,我们现在来模拟fallback失败

 

  /**
     * fallback
     */
    @Async
    private void reduce(){
        int i = 5 /0 ;
        if(ts.findAll().size()==0){
            TestEntity  t  =  new TestEntity();
            t.setNum(1);
            ts.saveAndFlush(t);
        }else{
            TestEntity dbt = ts.findAll().get(0);
            dbt.setNum(dbt.getNum()-1);
            ts.saveAndFlush(dbt);
        }
        
    }

 加上了一个runtimeException

 

并且去掉@Trabsactional

我们来看结果



 

 



 但是数据库中数据却增加了,显示是不行的。

现在我们加上事务注解


可见在事务下,连第一次+1都没有提交,我们事务策略成功

 

下面附上demo
 

 

  • 大小: 12.1 KB
  • 大小: 11.2 KB
  • 大小: 17.3 KB
  • 大小: 11.6 KB
  • 大小: 11.9 KB
分享到:
评论
1 楼 CodeMonkey_Xiong 2017-06-20  
      

相关推荐

    记录redisson实现redis分布式事务锁

    本篇文章将详细探讨如何使用Redisson实现Redis分布式事务锁,以及在Spring Boot环境中如何进行集成。 首先,Redis作为一个内存数据库,其高速读写性能使其成为实现分布式锁的理想选择。分布式锁的主要作用是在多...

    java开发基于SpringBoot+WebSocket+Redis分布式即时通讯群聊系统.zip

    Java开发基于SpringBoot+WebSocket+Redis分布式即时通讯群聊系统。一个基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统。适用于直播间聊天、游戏内聊天、客服聊天等临时性群聊场景。 ...

    springboot基于redis分布式锁

    3. **简单的API**:Redis提供了丰富的命令集,如`SETNX`、`EXPIRE`等,方便实现锁的逻辑。 要在SpringBoot中集成Redis,你需要先在项目中添加对应的依赖。SpringBoot提供了对Redis的自动配置支持,只需在`pom.xml`...

    案例实战-SpringBoot整合Redisson实现RedLock分布式锁同步

    RedLock是Redisson中的一个特性,它由Redis社区提出,旨在提供一种更健壮的分布式锁实现,比单节点Redis的`setnx`命令更可靠。 RedLock的实现基于以下假设: 1. 时钟偏移:所有参与的Redis服务器的时钟大致同步。 2...

    Spring Boot+Redis 分布式锁:模拟抢单.docx

    Spring Boot+Redis 分布式锁:模拟抢单

    Spring Boot+Redis 分布式锁:模拟抢单.pdf

    本次文档将围绕Spring Boot结合Redis实现分布式锁的机制进行详细解读,并通过模拟抢单的场景来展示其实际运用。 首先,了解Redis的分布式锁是如何运作的至关重要。在Redis的诸多操作中,`set`命令的`nx`选项(即`...

    Spring Boot Redis 实现分布式锁的方法详解.docx

    本篇文章将详细讲解如何利用 Spring Boot 结合 Redis 实现分布式锁。 首先,理解分布式锁的基本概念。分布式锁是在分布式系统中用于控制并发访问的机制,它允许只有一台机器或一个线程在任何时候持有锁,从而确保对...

    基于Spring Boot框架的分布式锁服务.zip

    Redis分布式锁利用Redis的SETNX命令实现分布式锁,确保在分布式环境下对资源的互斥访问。 Redisson分布式锁使用Redisson库提供的分布式锁实现,提供更高级的功能,如锁的自动续期和可重入锁。 2. 锁的续期和释放...

    基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统.zip

    基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统.zip 1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、该资源适合计算机相关专业(如计科、人工智能、大数据、数学、电子信息...

    spring-boot-redis-token 分布式锁 redis session

    http://localhost:8080/ass/getUser 测试是否登录 http://localhost:8080/any/user/passLogin 登录测试 http://localhost:8080/lock redis分布式锁测试

    redis分布式锁工具包提供纯Java方式调用

    7. **Spring Boot Starter**:对于Spring Boot应用,工具包提供的Starter可以通过简单的配置,自动将Redis分布式锁集成到应用中,减少手动配置的工作量。 在使用这个工具包时,开发者需要注意以下几点: - **正确...

    redis分布式锁,解决死锁问题

    项目为spring boot实现,maven生成jar包能直接运行 ...三种方式实现redis分布式锁 1.redis incr计数器实现 2.redis setIfAbsent 3.redisson 博客:https://blog.csdn.net/u011974797/article/details/81238079

    spring-boot-distributed-redisson:redis实现分布式锁 Spring Boot core for Redisson RedissonLock

    Redisson实现分布式锁 有关Redisson实现分布式锁前面写了三篇博客作为该项目落地的铺垫。 1、 2、 3、 该项目可以直接运用于实际开发中,作为分布式锁使用。 一、项目概述 1、技术架构 项目总体技术选型 SpringBoot...

    SpringBoot 使用 Redis 分布式锁解决并发问题.docx

    在SpringBoot应用中集成Redis分布式锁,可以创建一个`RedisLock`工具类,包含加锁和解锁的方法。加锁操作需要确保原子性,即同时设置键和过期时间,这在SpringBoot 2.x版本以上可以通过`opsForValue().setIfAbsent()...

    读书笔记:架构实战篇十八Spring Boot Redis实现分布式锁.zip

    读书笔记:架构实战篇十八Spring Boot Redis实现分布式锁

    redisTemplate封装成redisUtils和分布式锁实现

    本篇将深入探讨如何将RedisTemplate封装成RedisUtils工具类,并实现分布式锁功能。 首先,我们需要引入Spring Data Redis的依赖库,这通常在项目的pom.xml或build.gradle文件中完成。添加对应版本的Redis连接器和...

    Spring boot整合分布式缓存RedisSpring-redis-redission.zip

    通过上述步骤,你可以成功地在Spring Boot项目中集成Redis和Redission,实现高效、可靠的分布式缓存方案。记得在实际开发中根据业务需求选择合适的数据结构和功能,以达到最佳性能和可维护性。同时,定期检查和优化...

    spring boot+jpa+redis集群

    总结起来,这个项目展示了如何利用Spring Boot的便捷性、JPA的ORM能力以及Redis的高速缓存特性,构建一个高效且可扩展的分布式系统。通过学习和实践这个项目,开发者可以深入理解这三种技术的协同工作方式,提升自己...

Global site tag (gtag.js) - Google Analytics