Redission分布式锁应用案例(生成业务单号)

文章介绍了如何使用Redisson客户端和自定义UUIDStorage在分布式系统中生成唯一标识符,同时以项目ID为键,利用Redisson的锁机制确保生成的项目代码序列号唯一且高效。
摘要由CSDN通过智能技术生成
//redission 客户端

@Component
public class RedisUUID {

    @Autowired
    private RedisTemplate redisTemplate ;

    private UUIDStorage defaultUUIDStorage;

    private RedissonClient redissonClient;

    public RedisUUID(UUIDStorage defaultUUIDStorage , RedissonClient redissonClient){
        this.defaultUUIDStorage = defaultUUIDStorage;
        this.redissonClient =redissonClient;
    }

    public String generateUUID(String key , Long expireTime ,TimeUnit timeUnit, UUIDStorage uuidStorage ){

        RedisAtomicLong uuidLong = new RedisAtomicLong(key,redisTemplate.getConnectionFactory());

        Long expire = uuidLong.getExpire();

        if(expire == -1 && expireTime!=null && timeUnit!=null ){
            uuidLong.expire(expireTime,timeUnit);
        }

        return uuidStorage == null ?defaultUUIDStorage.generate(uuidLong):uuidStorage.generate(uuidLong) ;
    }

    public RedissonClient getRedissonClient(){
        return this.redissonClient;
    }
}

应用案例:

    @Override
    public String generateCode(Long projectId) {

        final String projectCode = projectSubinfoMapper.selectProjectCodeById(projectId);

        return redisUUID.generateUUID("pms:projectsubinfo:projectsubinfo:code:" + projectCode, null, null, new UUIDStorage() {

            @Override
            public String generate(RedisAtomicLong uuidLong) {

                Assert.notNull(uuidLong, "生成的ID不能为空");

                //如果redis中不存在则查询数据库
                if (uuidLong.get() == 0) {

                    RedissonClient redissonClient = redisUUID.getRedissonClient();

                    RLock fairLock = redissonClient.getFairLock("pms:pojectsubinfo:code:create" + projectCode);

                    boolean isLock = false;

                    try {

                        isLock = fairLock.tryLock(2, 5, TimeUnit.MILLISECONDS);

                        if (isLock && uuidLong.get() == 0) {

                            String maxProjectSubinfoCode = projectSubinfoMapper.selectMaxProjectSubinfoCode(projectId);

                            //如果数据库中也为空说明是第一次生成
                            if (maxProjectSubinfoCode == null) {

                                return projectCode  +"P"+  String.format("%03d", uuidLong.incrementAndGet());

                                //如果不是则将其加1并存入redis
                            } else {

                                String maxCodeNum = maxProjectSubinfoCode.substring(maxProjectSubinfoCode.length() - 3, maxProjectSubinfoCode.length());
                                //去掉头部的0转成Long型

                                Long maxCode = 0L;
                                try {
                                    //99%的项目都不会有问题,所以干脆try catch得了
                                    maxCode = Long.parseLong(maxCodeNum.replaceFirst("^0*", ""));
                                } catch (Exception e) {
                                    log.warn("项目号:" + maxProjectSubinfoCode);
                                }

                                maxCode++;

                                uuidLong.set(maxCode);

                                return projectCode  +"P"+  String.format("%03d", maxCode);
                            }

                        }

                    } catch (InterruptedException ex) {
                        log.info("捕获到redission锁被打断异常", ex);
                    } finally {
                        fairLock.unlock();
                    }
                }
                return projectCode +"P"+ String.format("%03d", uuidLong.incrementAndGet());
            }
        });
    }

redisson内部类包

package org.redisson.api;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

public interface RLock extends Lock, RLockAsync {
    String getName();

    void lockInterruptibly(long var1, TimeUnit var3) throws InterruptedException;

    boolean tryLock(long var1, long var3, TimeUnit var5) throws InterruptedException;

    void lock(long var1, TimeUnit var3);

    boolean forceUnlock();

    boolean isLocked();

    boolean isHeldByThread(long var1);

    boolean isHeldByCurrentThread();

    int getHoldCount();

    long remainTimeToLive();
}
package org.redisson.api;

import java.util.concurrent.TimeUnit;
import org.redisson.api.redisnode.BaseRedisNodes;
import org.redisson.api.redisnode.RedisNodes;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;

public interface RedissonClient {
    <V> RTimeSeries<V> getTimeSeries(String var1);

    <V> RTimeSeries<V> getTimeSeries(String var1, Codec var2);

    <K, V> RStream<K, V> getStream(String var1);

    <K, V> RStream<K, V> getStream(String var1, Codec var2);

    RRateLimiter getRateLimiter(String var1);

    RBinaryStream getBinaryStream(String var1);

    <V> RGeo<V> getGeo(String var1);

    <V> RGeo<V> getGeo(String var1, Codec var2);

    <V> RSetCache<V> getSetCache(String var1);

    <V> RSetCache<V> getSetCache(String var1, Codec var2);

    <K, V> RMapCache<K, V> getMapCache(String var1, Codec var2);

    <K, V> RMapCache<K, V> getMapCache(String var1, Codec var2, MapOptions<K, V> var3);

    <K, V> RMapCache<K, V> getMapCache(String var1);

    <K, V> RMapCache<K, V> getMapCache(String var1, MapOptions<K, V> var2);

    <V> RBucket<V> getBucket(String var1);

    <V> RBucket<V> getBucket(String var1, Codec var2);

    RBuckets getBuckets();

    RBuckets getBuckets(Codec var1);

    <V> RHyperLogLog<V> getHyperLogLog(String var1);

    <V> RHyperLogLog<V> getHyperLogLog(String var1, Codec var2);

    <V> RList<V> getList(String var1);

    <V> RList<V> getList(String var1, Codec var2);

    <K, V> RListMultimap<K, V> getListMultimap(String var1);

    <K, V> RListMultimap<K, V> getListMultimap(String var1, Codec var2);

    <K, V> RListMultimapCache<K, V> getListMultimapCache(String var1);

    <K, V> RListMultimapCache<K, V> getListMultimapCache(String var1, Codec var2);

    <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String var1, LocalCachedMapOptions<K, V> var2);

    <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String var1, Codec var2, LocalCachedMapOptions<K, V> var3);

    <K, V> RMap<K, V> getMap(String var1);

    <K, V> RMap<K, V> getMap(String var1, MapOptions<K, V> var2);

    <K, V> RMap<K, V> getMap(String var1, Codec var2);

    <K, V> RMap<K, V> getMap(String var1, Codec var2, MapOptions<K, V> var3);

    <K, V> RSetMultimap<K, V> getSetMultimap(String var1);

    <K, V> RSetMultimap<K, V> getSetMultimap(String var1, Codec var2);

    <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String var1);

    <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String var1, Codec var2);

    RSemaphore getSemaphore(String var1);

    RPermitExpirableSemaphore getPermitExpirableSemaphore(String var1);

    RLock getLock(String var1);

    RLock getSpinLock(String var1);

    RLock getSpinLock(String var1, LockOptions.BackOff var2);

    RLock getMultiLock(RLock... var1);

    /** @deprecated */
    @Deprecated
    RLock getRedLock(RLock... var1);

    RLock getFairLock(String var1);

    RReadWriteLock getReadWriteLock(String var1);

    <V> RSet<V> getSet(String var1);

    <V> RSet<V> getSet(String var1, Codec var2);

    <V> RSortedSet<V> getSortedSet(String var1);

    <V> RSortedSet<V> getSortedSet(String var1, Codec var2);

    <V> RScoredSortedSet<V> getScoredSortedSet(String var1);

    <V> RScoredSortedSet<V> getScoredSortedSet(String var1, Codec var2);

    RLexSortedSet getLexSortedSet(String var1);

    RTopic getTopic(String var1);

    RTopic getTopic(String var1, Codec var2);

    RReliableTopic getReliableTopic(String var1);

    RReliableTopic getReliableTopic(String var1, Codec var2);

    RPatternTopic getPatternTopic(String var1);

    RPatternTopic getPatternTopic(String var1, Codec var2);

    <V> RQueue<V> getQueue(String var1);

    <V> RTransferQueue<V> getTransferQueue(String var1);

    <V> RTransferQueue<V> getTransferQueue(String var1, Codec var2);

    <V> RDelayedQueue<V> getDelayedQueue(RQueue<V> var1);

    <V> RQueue<V> getQueue(String var1, Codec var2);

    <V> RRingBuffer<V> getRingBuffer(String var1);

    <V> RRingBuffer<V> getRingBuffer(String var1, Codec var2);

    <V> RPriorityQueue<V> getPriorityQueue(String var1);

    <V> RPriorityQueue<V> getPriorityQueue(String var1, Codec var2);

    <V> RPriorityBlockingQueue<V> getPriorityBlockingQueue(String var1);

    <V> RPriorityBlockingQueue<V> getPriorityBlockingQueue(String var1, Codec var2);

    <V> RPriorityBlockingDeque<V> getPriorityBlockingDeque(String var1);

    <V> RPriorityBlockingDeque<V> getPriorityBlockingDeque(String var1, Codec var2);

    <V> RPriorityDeque<V> getPriorityDeque(String var1);

    <V> RPriorityDeque<V> getPriorityDeque(String var1, Codec var2);

    <V> RBlockingQueue<V> getBlockingQueue(String var1);

    <V> RBlockingQueue<V> getBlockingQueue(String var1, Codec var2);

    <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String var1);

    <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String var1, Codec var2);

    <V> RDeque<V> getDeque(String var1);

    <V> RDeque<V> getDeque(String var1, Codec var2);

    <V> RBlockingDeque<V> getBlockingDeque(String var1);

    <V> RBlockingDeque<V> getBlockingDeque(String var1, Codec var2);

    RAtomicLong getAtomicLong(String var1);

    RAtomicDouble getAtomicDouble(String var1);

    RLongAdder getLongAdder(String var1);

    RDoubleAdder getDoubleAdder(String var1);

    RCountDownLatch getCountDownLatch(String var1);

    RBitSet getBitSet(String var1);

    <V> RBloomFilter<V> getBloomFilter(String var1);

    <V> RBloomFilter<V> getBloomFilter(String var1, Codec var2);

    RIdGenerator getIdGenerator(String var1);

    RFunction getFunction();

    RFunction getFunction(Codec var1);

    RScript getScript();

    RScript getScript(Codec var1);

    RScheduledExecutorService getExecutorService(String var1);

    RScheduledExecutorService getExecutorService(String var1, ExecutorOptions var2);

    RScheduledExecutorService getExecutorService(String var1, Codec var2);

    RScheduledExecutorService getExecutorService(String var1, Codec var2, ExecutorOptions var3);

    RRemoteService getRemoteService();

    RRemoteService getRemoteService(Codec var1);

    RRemoteService getRemoteService(String var1);

    RRemoteService getRemoteService(String var1, Codec var2);

    RTransaction createTransaction(TransactionOptions var1);

    RBatch createBatch(BatchOptions var1);

    RBatch createBatch();

    RKeys getKeys();

    RLiveObjectService getLiveObjectService();

    RedissonRxClient rxJava();

    RedissonReactiveClient reactive();

    void shutdown();

    void shutdown(long var1, long var3, TimeUnit var5);

    Config getConfig();

    <T extends BaseRedisNodes> T getRedisNodes(RedisNodes<T> var1);

    /** @deprecated */
    @Deprecated
    NodesGroup<Node> getNodesGroup();

    /** @deprecated */
    @Deprecated
    ClusterNodesGroup getClusterNodesGroup();

    boolean isShutdown();

    boolean isShuttingDown();

    String getId();
}
public interface UUIDStorage {
    String generate(RedisAtomicLong uuidLong);
}
@Component("defaultUUIDStorage")
public class DefaultUUIDStorage implements UUIDStorage {

    @Override
    public String generate(RedisAtomicLong uuidLong) {
        return uuidLong == null ? null : uuidLong.incrementAndGet()+"";
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值