栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一个简单的(基于redisson的)分布式同步工具类封装

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一个简单的(基于redisson的)分布式同步工具类封装

一个简单的(基于redisson的)分布式同步工具类封装
  • 一个简单的(基于redisson的)分布式同步工具类封装
    • 背景说明
    • 准备工作
      • 第一步:引入redisson依赖
      • 第二步:配置RedissonClient
    • 工具类
      • 工具类接口
      • 工具类接口的默认实现
      • 工具类接口涉及到的两个其它接口
    • 使用示例
背景说明

有些分布式同步逻辑不需要作用于整个方法,只需要作用于指定的业务逻辑代码块即可,类似于synchronized代码块。于是有了下面这个简单的封装类。

准备工作

提示:此同步工具类中的redis分布式锁直接采用redisson实现。

第一步:引入redisson依赖

    org.redisson
    redisson
    3.17.0

第二步:配置RedissonClient

提示:这里的配置以单体redis为例,更多配置详见redisson官网。

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Slf4j
@Configuration
public class RedissonConfig {
    
    @Value("${spring.redis.host}")
    private String host;
    
    @Value("${spring.redis.port}")
    private String port;
    
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        String address = host + ":" + port;
        log.info("redis address -> {}", address);
        config.useSingleServer()
                .setAddress("redis://" + address);
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }
}
工具类 工具类接口
import lombok.Getter;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;


public interface RedisLockSupport {
    
    
     R exec(Function function, P param) throws NotAcquiredRedisLockException;
    
    
     R exec(NoArgFunction function) throws NotAcquiredRedisLockException;
    
    
    

void voidExec(Consumer

consumer, P param) throws NotAcquiredRedisLockException; void voidExec(NoArgConsumer consumer) throws NotAcquiredRedisLockException; @Getter class NotAcquiredRedisLockException extends RuntimeException{ private final String lockKey; private final long waitTime; private final TimeUnit timeUnit; public NotAcquiredRedisLockException(String lockKey, long waitTime, TimeUnit timeUnit) { super(String.format("lockKey=%s, waitTime=%d, timeUnit=%d", lockKey, waitTime, timeUnit)); this.lockKey = lockKey; this.waitTime = waitTime; this.timeUnit = timeUnit; } } }

工具类接口的默认实现
import lombok.Getter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;


@Getter
public class DefaultRedisLockSupport implements RedisLockSupport {
    
    
    private static volatile RedissonClient defaultRedissonClient;
    
    
    protected RedissonClient redissonClient;
    
    
    protected final String lockKey;
    
    
    protected long waitTime = 1L;
    
    
    protected long leaseTime = 3L;
    
    
    protected TimeUnit unit = TimeUnit.SECONDS;
    
    public DefaultRedisLockSupport(String lockKey) {
        this.lockKey = lockKey;
    }
    
    public DefaultRedisLockSupport(RedissonClient redissonClient, String lockKey) {
        this.redissonClient = redissonClient;
        this.lockKey = lockKey;
    }
    
    public DefaultRedisLockSupport(String lockKey, long waitTime, long leaseTime) {
        this.lockKey = lockKey;
        this.waitTime = waitTime;
        this.leaseTime = leaseTime;
    }
    
    public DefaultRedisLockSupport(RedissonClient redissonClient, String lockKey, long waitTime, long leaseTime) {
        this.redissonClient = redissonClient;
        this.lockKey = lockKey;
        this.waitTime = waitTime;
        this.leaseTime = leaseTime;
    }
    
    public DefaultRedisLockSupport(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        this.lockKey = lockKey;
        this.waitTime = waitTime;
        this.leaseTime = leaseTime;
        this.unit = unit;
    }
    
    public DefaultRedisLockSupport(RedissonClient redissonClient, String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        this.redissonClient = redissonClient;
        this.lockKey = lockKey;
        this.waitTime = waitTime;
        this.leaseTime = leaseTime;
        this.unit = unit;
    }
    
    @Override
    public  R exec(Function function, P param) throws NotAcquiredRedisLockException {
        RedissonClient client = redissonClient();
        RLock lock = client.getLock(lockKey);
        boolean obtainLock = false;
        try {
            obtainLock = lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            // ignore
        }
        if (obtainLock) {
            try {
                return function.apply(param);
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        throw new NotAcquiredRedisLockException(lockKey, waitTime, unit);
    }
    
    @Override
    public  R exec(NoArgFunction function) throws NotAcquiredRedisLockException {
        RedissonClient client = redissonClient();
        RLock lock = client.getLock(lockKey);
        boolean obtainLock = false;
        try {
            obtainLock = lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            // ignore
        }
        if (obtainLock) {
            try {
                return function.apply();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        throw new NotAcquiredRedisLockException(lockKey, waitTime, unit);
    }
    
    @Override
    public 

void voidExec(Consumer

consumer, P param) throws NotAcquiredRedisLockException { RedissonClient client = redissonClient(); RLock lock = client.getLock(lockKey); boolean obtainLock = false; try { obtainLock = lock.tryLock(waitTime, leaseTime, unit); } catch (InterruptedException e) { // ignore } if (obtainLock) { try { consumer.accept(param); return; } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } throw new NotAcquiredRedisLockException(lockKey, waitTime, unit); } @Override public void voidExec(NoArgConsumer consumer) throws NotAcquiredRedisLockException { RedissonClient client = redissonClient(); RLock lock = client.getLock(lockKey); boolean obtainLock = false; try { obtainLock = lock.tryLock(waitTime, leaseTime, unit); } catch (InterruptedException e) { // ignore } if (obtainLock) { try { consumer.accept(); return; } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } throw new NotAcquiredRedisLockException(lockKey, waitTime, unit); } protected RedissonClient redissonClient() { if (this.redissonClient != null) { return this.redissonClient; } if (DefaultRedisLockSupport.defaultRedissonClient != null) { return DefaultRedisLockSupport.defaultRedissonClient; } throw new IllegalStateException("There is not redissonClient available."); } public static void initDefaultRedissonClient(RedissonClient redissonClient) { if (DefaultRedisLockSupport.defaultRedissonClient != null && !DefaultRedisLockSupport.defaultRedissonClient.equals(redissonClient)) { throw new IllegalStateException("defaultRedissonClient already been initialized."); } synchronized (DefaultRedisLockSupport.class) { if (DefaultRedisLockSupport.defaultRedissonClient != null) { if (DefaultRedisLockSupport.defaultRedissonClient.equals(redissonClient)) { return; } throw new IllegalStateException("defaultRedissonClient already been initialized."); } DefaultRedisLockSupport.defaultRedissonClient = redissonClient; } } }

工具类接口涉及到的两个其它接口
  • NoArgConsumer

    @FunctionalInterface
    public interface NoArgConsumer {
        
        
        void accept();
    }
    
  • NoArgFunction

    @FunctionalInterface
    public interface NoArgFunction {
        
        
        R apply();
    }
    
使用示例
import com.ideaaedi.heywebuy.srv.config.redisson.DefaultRedisLockSupport;
import com.ideaaedi.heywebuy.srv.config.redisson.NoArgConsumer;
import com.ideaaedi.heywebuy.srv.config.redisson.NoArgFunction;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.redisson.api.RedissonClient;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

@Slf4j
@SpringBootTest
public class RedisLockSupportTest {
    
    @Resource
    private RedissonClient redissonClient;
    
    
    @BeforeEach
    void initMethod() {
        // 在项目启动时注入
        DefaultRedisLockSupport.initDefaultRedissonClient(redissonClient);
    }
    
    @Test
    void test() {
        // 无参数 无返回值 NoArgConsumer
        new DefaultRedisLockSupport("DefaultRedisLockSupport1", 1, 120).voidExec(new NoArgConsumer() {
            @Override
            public void accept() {
                // 我是业务逻辑
                System.out.println("[无参数 无返回值 NoArgConsumer]:ttttt" + 111111);
            }
        });
        
        // 有参数 无返回值 Consumer
        new DefaultRedisLockSupport("DefaultRedisLockSupport1", 1, 120).voidExec(new Consumer() {
            @Override
            public void accept(Integer s) {
                // 我是业务逻辑
                System.out.println("[有参数 无返回值 Consumer]:ttttt" + s);
            }
        }, 2222);
    
    
        // 无参数 有返回值 NoArgFunction
        Map result = new DefaultRedisLockSupport("DefaultRedisLockSupport1", 1, 120)
                .exec(new NoArgFunction>() {
                    @Override
                    public Map apply() {
                        // 我是业务逻辑
                        return Collections.singletonMap("k1", "v1");
                    }
                } );
        System.out.println("[无参数 有返回值 Function]:ttttt" + result);
    
        // 有参数 有返回值 Function
         result = new DefaultRedisLockSupport("DefaultRedisLockSupport1", 1, 120).exec(new Function>() {
            @Override
            public Map apply(String s) {
                // 我是业务逻辑
                return Collections.singletonMap("k2", s);
            }
        }, "v2");
        System.out.println("[有参数 有返回值 Function]:ttttt" + result);
    }
}
相关资料
  • 本文已被收录进《程序员成长笔记》 ,笔者JustryDeng
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820720.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号