redis锁-注解版

Redis实现分布式锁利用 SETNX 和 SETEX
基本命令主要有:
SETNX(SET If Not Exists):
当且仅当 Key 不存在时,则可以设置,否则不做任何动作。
当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0。
SETEX:
基于SETNX功能外,还可以设置超时时间,防止死锁。
项目图 在这里插入图片描述
代码实现
application.yml

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.196.129
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000

RedisLock

/**
 * @author lihaozhen
 * 互斥性,安全性,可用性,对称性
 */
@Component
@Slf4j
public class RedisLock {

    @Autowired
    private StringRedisTemplate redisTemplate;
    //设置锁的过期时间
    private static final long exprise = 5000L;

    /**
     * @Description 加锁
     */
    public boolean lock(String remark, String key, long exprise) {
        if (redisTemplate.opsForValue().setIfAbsent(key, "lock", exprise, TimeUnit.MILLISECONDS)) {
            log.info("loger加锁:" + remark + "-" + key);
//            System.out.println("loger加锁:" + remark + "-" + key);
            return true;
        }
        log.error("加锁失败!");
        return false;
    }

    /**
     * @Description 释放锁
     */
    public void unlock(String remark, String key) {
        redisTemplate.delete(key);
        System.out.println("logger释放锁了:" + remark + ":" + key);
    }
}

RedisLockAnn

import java.lang.annotation.*;

/**
 * @author lihaozhen
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface RedisLockAnn {
    String menthodName() default "";
    long  expireTime() default 5000L;
}

RedisLockAspect

/**
 * @author lihaozhen
 * @title: RedisLockAspect
 */
@Aspect
@Component
@Slf4j
public class RedisLockAspect {

    @Autowired(required = false)
    private HttpServletRequest request;

    @Autowired
    RedisLock redisLock;

    Logger logger;

    @Pointcut("@annotation(com.example.demo.lock.RedisLockAnn)")
    public void redisLockAnnotation() {
    }

    @Around(value = "redisLockAnnotation()")
    public Object methodsAnnotationWithRedisLock(final ProceedingJoinPoint joinPoint) throws Throwable {
        Object re = null;
        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
        Method method = sign.getMethod();
        String key = method.getName();
        long expireTime = method.getAnnotation(RedisLockAnn.class).expireTime();
        if (!"".equals(method.getAnnotation(RedisLockAnn.class).menthodName())) {
            key = method.getAnnotation(RedisLockAnn.class).menthodName();
        }
        try {
            if (redisLock.lock("", key, expireTime)) {
                re = joinPoint.proceed();
                redisLock.unlock("", key);
            }
        } catch (Exception e) {
            logger.error("redis锁:"+e.getMessage());
        }finally {
            redisLock.unlock("", key);
        }
        return re;
    }
}

RedisUtil

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 李大本事
 * @Date: 2020/6/5 17:09
 */
@Slf4j
@Component
public class RedisUtil {

    private StringRedisTemplate redisTemplate;

    @Autowired
    public RedisUtil(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // 通用操作

    /**
     * 为给定[key]设置生存时间, 当[key]过期时(生存时间为0), 它会被自动删除
     *
     * @param key      键
     * @param timeout  失效时间
     * @param timeUnit 时间粒度
     * @return 设置成功为true
     */
    public Boolean setExpire(String key, long timeout, TimeUnit timeUnit) {
        try {
            redisTemplate.expire(key, timeout, timeUnit);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setExpire} with parameter {key={},timeout={},timeUnit={}} has error {}", key, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 删除[key]的值
     *
     * @param key 键
     * @return 删除成功为true, 失败为false
     */
    public Boolean remove(String key) {
        try {
            return redisTemplate.delete(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {remove} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }


    // String相关操作

    /**
     * 将字符串[value]关联到[key]
     *
     * @param key   键
     * @param value 值
     * @return 赋值成功为true
     */
    public Boolean set(String key, String value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {set} with parameter {key={},value={}} has error {}", key, value, e);
        }
        return null;
    }

    /**
     * 将字符串[value]关联到[key], 并设置TTL
     *
     * @param key      键
     * @param value    值
     * @param timeout  失效时间
     * @param timeUnit 时间粒度
     * @return 赋值成功为true
     */
    public Boolean set(String key, String value, long timeout, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {set} with parameter {key={},value={},timeout={},timeUnit={}} has error {}", key, value, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 在键[key]不存在的情况下, 将键[key]的值设置为[value]
     *
     * @param key   键
     * @param value 值
     * @return 赋值成功为true, 失败为false
     */
    public Boolean setIfNotExist(String key, String value) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(key, value);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setIfNotExist} with parameter {key={},value={}} has error {}", key, value, e);
        }
        return null;
    }

    /**
     * 在键[key]不存在的情况下, 将键[key]的值设置为[value], 并设置TTL
     *
     * @param key      键
     * @param value    值
     * @param timeout  失效时间
     * @param timeUnit 时间粒度
     * @return 赋值成功为true, 失败为false
     */
    public Boolean setIfNotExist(String key, String value, long timeout, TimeUnit timeUnit) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, timeUnit);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setIfNotExist} with parameter {key={},value={},timeout={},timeUnit={}} has error {}", key, value, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 键值自增
     *
     * @param key 键的名称
     * @return 自增后的值
     */
    public Long increment(String key) {
        Long length = -1L;
        try {
            length = redisTemplate.opsForValue().increment(key);
            redisTemplate.expire(key, 3, TimeUnit.DAYS);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {increment} has error ", e);
        }
        return length;
    }

    /**
     * 返回与键[key]相关联的字符串值
     *
     * @param key 键
     * @return 返回key的值
     */
    public String get(String key) {
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {set} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }


    // Hash相关操作

    /**
     * 将哈希表[key]中域[field]的值设置为[value]
     *
     * @param key   键
     * @param field 域
     * @param value 值
     * @return 赋值成功为true
     */
    public Boolean setHash(String key, Object field, Object value) {
        try {
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            redisTemplate.opsForHash().put(key, field, value);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHash} with parameter {key={},field={},value={}} has error {}", key, field, value, e);
        }
        return null;
    }

    /**
     * 将哈希表[key]中域[field]的值设置为[value], 并设置TTL
     *
     * @param key      键
     * @param field    域
     * @param value    值
     * @param timeout  失效时间
     * @param timeUnit 时间粒度
     * @return 赋值成功为true
     */
    public Boolean setHash(String key, Object field, Object value, long timeout, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForHash().put(key, field, value);
            setExpire(key, timeout, timeUnit);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHash} with parameter {key={},field={},value={},timeout={},timeUnit={}} has error {}", key, field, value, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 当且仅当域[field]尚未存在于哈希表[key]的情况下, 将它的值设置为[value]
     *
     * @param key   键
     * @param field 值
     * @param value 域
     * @return 赋值成功为true, 失败为false
     */
    public Boolean setHashIfNotExist(String key, Object field, Object value) {
        try {
            return redisTemplate.opsForHash().putIfAbsent(key, field, value);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHashIfNotExist} with parameter {key={},field={},value={}} has error {}", key, field, value, e);
        }
        return null;
    }

    /**
     * 当且仅当域[field]尚未存在于哈希表[key]的情况下, 将它的值设置为[value], 并设置TTL
     *
     * @param key      键
     * @param field    值
     * @param value    域
     * @param timeout  失效时间
     * @param timeUnit 时间粒度
     * @return 赋值成功为true, 失败为false
     */
    public Boolean setHashIfNotExist(String key, Object field, Object value, long timeout, TimeUnit timeUnit) {
        try {
            setExpire(key, timeout, timeUnit);
            return redisTemplate.opsForHash().putIfAbsent(key, field, value) && Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHashIfNotExist} with parameter {key={},field={},value={},timeout={},timeUnit={}} has error {}", key, field, value, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 同时将[map]中多个field-value(域-值)对设置到哈希表[key]中
     *
     * @param key 键
     * @param map 域值对
     * @return 赋值成功为true
     */
    public Boolean setHashMap(String key, Map<Object, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHashMap} with parameter {key={},map={}} has error {}", key, map, e);
        }
        return null;
    }

    /**
     * 同时将[map]中多个field-value(域-值)对设置到哈希表[key]中, 并设置TTL, 时间粒度为 秒
     *
     * @param key 键
     * @param map 域值对
     * @return 赋值成功为true
     */
    public Boolean setHashMap(String key, Map<Object, Object> map, long timeout) {
        return setHashMap(key, map, timeout, TimeUnit.SECONDS);
    }

    /**
     * 同时将[map]中多个field-value(域-值)对设置到哈希表[key]中, 并设置TTL
     *
     * @param key 键
     * @param map 域值对
     * @return 赋值成功为true
     */
    public Boolean setHashMap(String key, Map<Object, Object> map, long timeout, TimeUnit timeUnit) {
        try {
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            redisTemplate.opsForHash().putAll(key, map);
            setExpire(key, timeout, timeUnit);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("class {RedisUtil} method {setHashMap} with parameter {key={},map={},timeout={},timeUnit={}} has error {}", key, map, timeout, timeUnit, e);
        }
        return null;
    }

    /**
     * 返回哈希表[key]中给定域[field]的值
     *
     * @param key   键
     * @param field 域
     * @return 指定域的值
     */
    public Object getHash(String key, Object field) {
        try {
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            return redisTemplate.opsForHash().get(key, field);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getHash} with parameter {key={},field={}} has error {}", key, field, e);
        }
        return null;
    }

    /**
     * 返回哈希表[key]中, 一个或多个给定域的值
     *
     * @param key 键
     * @return 域值对
     */
    public Map<Object, Object> getHashMap(String key) {
        try {
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            return redisTemplate.opsForHash().entries(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getHash} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }

    /**
     * 批量获取keyList中的所有key的值
     *
     * @param keyList key值集合
     * @return key值集合中所有值的集合
     */
    public List<Object> getHashAll(List<String> keyList) {
        try {
            return redisTemplate.executePipelined((RedisCallback<LinkedHashMap<Object, Object>>) connection -> {
                connection.openPipeline();
                for (String key : keyList) {
                    byte[] keyByte = key.getBytes();
                    connection.hGetAll(keyByte);
                }
                return null;
            });
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getAll} with parameter {keyList={}} has error {}", keyList, e);
        }
        return null;
    }

    // List相关操作

    /**
     * 将[value]插入到列表[key]的表头(最左边)
     *
     * @param key   列表的名称
     * @param value 值
     * @return 表的长度
     */
    public Long leftPush(String key, String value) {
        try {
            redisTemplate.setHashValueSerializer(RedisSerializer.json());
            return redisTemplate.opsForList().leftPush(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("class {RedisUtil} method {leftPush} with parameter {key={},value={}} has error {}", key, value, e);
        }
        return null;
    }


    public Long removeValueOfList(String key, String value) {
        try {
            return redisTemplate.opsForList().remove(key, 0, value);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("class {RedisUtil} method {leftPush} with parameter {key={},value={}} has error {}", key, value, e);
        }
        return null;
    }


    /**
     * 将[value]插入到列表[key]的表尾(最右边)
     *
     * @param key   列表的名称
     * @param value 值
     * @return 表的长度
     */
    public Long rightPush(String key, String value) {
        try {
            return redisTemplate.opsForList().rightPush(key, value);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {rightPush} with parameter {key={},value={}} has error {}", key, value, e);
        }
        return null;
    }

    /**
     * 移除并返回列表[key]的头元素
     *
     * @param key 列表的名称
     * @return 列表的头元素
     */
    public String leftPop(String key) {
        try {
            return redisTemplate.opsForList().leftPop(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {leftPop} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }

    /**
     * 移除并返回列表key的尾元素
     *
     * @param key 列表的名称
     * @return 列表的尾元素
     */
    public String rightPop(String key) {
        try {
            return redisTemplate.opsForList().rightPop(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {rightPop} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }

    /**
     * 获取列表key的长度
     *
     * @param key 列表的名称
     * @return 列表的长度
     */
    public Long getListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getListSize} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }

    public List<String> getAllList(String key) {
        try {
            Long end = redisTemplate.opsForList().size(key);
            return redisTemplate.opsForList().range(key, 0, end);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getListSize} with parameter {key={}} has error {}", key, e);
        }
        return null;
    }

    public Long removeHashKey(String Key, String field) {
        try {
            return redisTemplate.opsForHash().delete(Key, field);

        } catch (Exception e) {

            log.error("class {RedisUtil} method {removeHashKey} with parameter {key={}} has error {}", Key, field, e);
        }
        return null;
    }

    public List<String> getListByCount(String key, Long size) {
        try {
            if (size > 0) {
                --size;
            }
            return redisTemplate.opsForList().range(key, 0, size);
        } catch (Exception e) {
            log.error("class {RedisUtil} method {getListSize} with parameter {key={}} has error {}", key, e);
        }
        return null;

    }
}

测试效果如下图
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值