Redis实现分布式锁和等待序列

package com.test
    import redis.clients.jedis.Jedis;
    import java.util.Collections;
    import java.util.List;
    /**
     * @desc redis队列实现方式
     * @anthor 
     * @date 
     **/
    public class RedisUcUitl {
        private static final String LOCK_SUCCESS = "OK";
        private static final String SET_IF_NOT_EXIST = "NX";
        private static final String SET_WITH_EXPIRE_TIME = "PX";
        private static final Long RELEASE_SUCCESS = 1L;
        private RedisUcUitl() {
        }
        
        /**
         * 存储redis队列顺序存储 在队列首部存入
         * @param key   字节类型
         * @param value 字节类型
         */
        public static Long lpush(Jedis jedis, final byte[] key, final byte[] value) {
            return jedis.lpush(key, value);
        }
    
        /**
         * 移除列表中最后一个元素 并将改元素添加入另一个列表中 ,当列表为空时 将阻塞连接 直到等待超时
         * @param srckey
         * @param dstkey
         * @param timeout 0 表示永不超时
         * @return
         */
        public static byte[] brpoplpush(Jedis jedis,final byte[] srckey, final byte[] dstkey, final int timeout) {
            return jedis.brpoplpush(srckey, dstkey, timeout);
        }
        /**
         * 返回制定的key,起始位置的redis数据
         * @param redisKey
         * @param start
         * @param end -1 表示到最后
         * @return
         */
        public static List lrange(Jedis jedis,final byte[] redisKey, final long start, final long end) {
            return jedis.lrange(redisKey, start, end);
        }
        /**
         * 删除key
         * @param redisKey
         */
        public static void delete(Jedis jedis, final byte[] redisKey) {
             return jedis.del(redisKey);
        }
        /**
         * 尝试加锁
         * @param lockKey key名称
         * @param requestId 身份标识
         * @param expireTime 过期时间
         * @return
         */
        public static boolean tryGetDistributedLock(Jedis jedis,final String lockKey, final String requestId, final int expireTime) {
            String result =  jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
            return LOCK_SUCCESS.equals(result);
        }
    
        /**
         * 释放锁
         * @param lockKey key名称
         * @param requestId 身份标识
         * @return
         */
        public static boolean releaseDistributedLock(Jedis jedis,final String lockKey, final String requestId) {
            final String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
            return RELEASE_SUCCESS.equals(result);
        }
    }

业务逻辑主要代码如下

// 1.先消耗队列中的
    while(true){
        // 消费队列
        try{
            // 被放入redis队列的数据 序列化后的
            byte[] bytes = RedisUcUitl.brpoplpush(keyStr.getBytes(UTF_8), dstKeyStr.getBytes(UTF_8), 1);
            if(bytes == null || bytes.isEmpty()){
               // 队列中没数据时退出
                break;
            }
            // 反序列化对象
            Map singleMap = (Map) ObjectSerialUtil.bytesToObject(bytes);
            // 塞入唯一的值 防止被其他线程误解锁
            String requestId = UUID.randomUUID().toString();
            boolean lockGetFlag = RedisUcUitl.tryGetDistributedLock(keyStr,requestId, 100);
            if(lockGetFlag){
                // 成功获取锁 进行业务处理
                //TODO
                // 处理完毕释放锁 
                boolean freeLock = RedisUcUitl.releaseDistributedLock(keyStr, requestId);
            }else{
                // 未能获得锁放入等待队列
              RedisUcUitl.lpush(keyStr.getBytes(UTF_8), ObjectSerialUtil.objectToBytes(param));
        }
        }catch(Exception e){
            break;
        }
    }

你可能感兴趣的:(Redis实现分布式锁和等待序列)