Redis操作工具类

2023-10-29

前期文章中关于RedisOperateUtil工具类使用时需要强制类型转换,针对List等操作不方便,为此特意更新RedisOperateUtil工具类,前文链接:https://blog.csdn.net/liwenyang1992/article/details/111771097?spm=1001.2014.3001.5501

通过Docker搭建Redis环境并启动,命令如下:

#docker启动redis服务
docker run -itd --name redis -p 6379:6379 redis
#使用redis-cli连接redis
docker exec -it redis redis-cli

application.properties配置如下:

server.port=8080
server.servlet.context-path=/redis

############################################################
# REDIS 配置
############################################################
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.lettuce.pool.max-active=18
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.shutdown-timeout=100ms
spring.redis.timeout=100
spring.cache.cache-names=myCache
#是否启用连接池,如果依赖中有common-pools2依赖自动会启用
spring.redis.lettuce.pool.enabled=true

pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lwy.it</groupId>
    <artifactId>spring-redis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-redis</name>
    <description>Demo project for Spring Boot Redis</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- RedisTemplate底层使用commons-pool2来作为连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

由于SpringBoot 2.0版本之后spring-boot-starter-data-redis的底层默认使用了Lettuce来操作redis,早期的版本使用的是Jedis,使用Lettuce获取连接都是通过LettuceConnectionFactory这个工厂类来获取的,默认情况下Lettuce使用的是一个线程安全的共享的本地连接来操作Redis,如果你不希望使用本地连接可以设置shareNativeConnection这个参数为false。备注:RedisTemplate底层使用commons-pool2来作为连接池。

备注:默认情况下RedisTemplate是不使用连接池的,并且性能还是不错的。

RedisConfiguration配置如下:

package com.lwy.it.configuration;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 使用Jackson2JsonRedisSerializer序列化和反序列化
 */
@Configuration
public class RedisConfiguration extends CachingConfigurerSupport {

    @Bean("redisTemplate")
    public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        // 启用连接共享
        lettuceConnectionFactory.setShareNativeConnection(true);
        // 配置连接工厂
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        // 使用Jackson2JsonRedisSerializer来序列化和反序列化Redis的value值
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定药序列化的域,field,get和set,以及修饰符范围
        // ANY任何级别的字段都可以自动识别
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会抛出异常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // value采用Json序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // 使用StringRedisSerializer来序列化和反序列化Redis的key
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 使用StringRedisSerializer来序列化和反序列化Redis的Hash key
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // Hash value采用Json序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }

    @Override
    public CacheErrorHandler errorHandler() {
        return new RedisCacheErrorHandler();
    }

}

核心Redis操作工具类RedisOperateUtil如下,主要包括Redis键(Key)、字符串(String)、哈希(Hash)、列表(List)、集合(Set)等常用的操作。

package com.lwy.it.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public final class RedisOperateUtil {
    private static Logger LOGGER = LoggerFactory.getLogger(RedisOperateUtil.class);
    // 默认最长时效时间(秒)
    private static long EXPIRED_TIME = 604800L;

    private void setDefaultExpiredTime(final String key) {
        Long ttl = this.ttl(key, TimeUnit.SECONDS);
        if (!Objects.isNull(ttl) && ttl.equals(-1L)) {
            this.expire(key, EXPIRED_TIME, TimeUnit.SECONDS);
        }
    }

    @Autowired
    private RedisOperations redisTemplate;

    /**
     * DEL key
     *
     * @param key Redis Key
     * @return 是否删除成功
     */
    public Boolean del(final String key) {
        Boolean result = null;
        try {
            result = redisTemplate.delete(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * DEL key key
     *
     * @param keys Redis Keys
     * @return 删除的数量
     */
    public Long del(final Set<String> keys) {
        Long result = null;
        try {
            result = redisTemplate.delete(keys);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * EXISTS key
     *
     * @param key Redis Key
     * @return 是否存在key
     */
    public Boolean exists(final String key) {
        Boolean result = null;
        try {
            result = redisTemplate.hasKey(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * EXISTS key1 key2
     *
     * @param keys Redis Keys
     * @return 指定为参数的键中存在的键数,多次提及和存在的键被多次计算。
     */
    public Long exists(final Set<String> keys) {
        Long result = null;
        try {
            result = redisTemplate.countExistingKeys(keys);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * EXPIRE key seconds
     *
     * @param key     Redis Key
     * @param timeout 超时时间
     * @param unit    时间粒度单位
     * @return 在管道/事务中使用时为 null
     */
    public Boolean expire(final String key, final long timeout, TimeUnit unit) {
        Boolean result = null;
        try {
            result = redisTemplate.expire(key, timeout, unit);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * TTL key
     *
     * @param key      Redis Key
     * @param timeUnit 时间粒度单位
     * @return 按照给定时间粒度单位,返回过期时间,时间粒度单位为空时默认为秒
     */
    public Long ttl(final String key, TimeUnit timeUnit) {
        if (Objects.isNull(timeUnit)) {
            timeUnit = TimeUnit.SECONDS;
        }
        Long result = null;
        try {
            result = redisTemplate.getExpire(key, timeUnit);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * TTL key
     *
     * @param key Redis Key
     * @return 按照给定时间粒度单位,返回过期时间,时间粒度单位为空时默认为秒
     */
    public Long ttl(final String key) {
        return this.ttl(key, TimeUnit.SECONDS);
    }

    /**
     * SET key value
     *
     * @param key   Redis Key
     * @param value 存储的value
     * @param <V>   value泛型类型
     */
    public <V> void set(final String key, final V value) {
        this.setex(key, value, EXPIRED_TIME, TimeUnit.SECONDS);
    }

    /**
     * GET key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 返回存储的value
     */
    public <V> V get(final String key) {
        ValueOperations<String, V> operations = redisTemplate.opsForValue();
        V result = null;
        try {
            result = operations.get(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * GETSET key value
     *
     * @param key   Redis Key
     * @param value 存储的value
     * @param <V>   value泛型类型
     * @return 指定key的值,并返回key的旧值
     */
    public <V> V getset(final String key, final V value) {
        ValueOperations<String, V> operations = redisTemplate.opsForValue();
        V result = null;
        try {
            result = operations.getAndSet(key, value);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * MSET key value [key value ...]
     * 缺少过期时间,不建议使用
     *
     * @param map 不能为空
     * @param <V> value泛型类型
     */
    @Deprecated
    public <V> void mset(final Map<String, V> map) {
        if (!CollectionUtils.isEmpty(map)) {
            ValueOperations<String, V> operations = redisTemplate.opsForValue();
            try {
                operations.multiSet(map);
            } catch (Exception exception) {
                LOGGER.error(exception.getMessage(), exception);
            }
        } else {
            LOGGER.warn("Parameters map is null or empty");
        }

    }

    /**
     * MGET key [key ...]
     * 建议使用LinkedHashSet
     *
     * @param keys 不重复Redis Key集合,不能为空
     * @param <V>  value泛型类型
     * @return 结果List集合
     */
    public <V> List<V> mget(final Set<String> keys) {
        List<V> result = Collections.emptyList();
        if (!CollectionUtils.isEmpty(keys)) {
            ValueOperations<String, V> operations = redisTemplate.opsForValue();
            try {
                result = operations.multiGet(keys);
            } catch (RedisConnectionFailureException exception) {
                LOGGER.error(exception.getMessage(), exception);
            } catch (QueryTimeoutException exception) {
                LOGGER.error(exception.getMessage(), exception);
            }
        }
        return result;
    }

    /**
     * SETEX key seconds value
     *
     * @param key     Redis Key
     * @param value   Redis Value
     * @param timeout 超时时间
     * @param unit    单位
     * @param <V>     value泛型类型
     */
    public <V> void setex(final String key, final V value, final long timeout, TimeUnit unit) {
        if (Objects.isNull(unit)) {
            unit = TimeUnit.SECONDS;
        }
        ValueOperations<String, V> operations = redisTemplate.opsForValue();
        try {
            operations.set(key, value, timeout, unit);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
    }

    /**
     * SETNX key value
     *
     * @param key     Redis Key
     * @param value   Redis Value
     * @param timeout 超时时间
     * @param unit    单位
     * @param <V>     value泛型类型
     * @return 设置成功,返回true。设置失败,返回false。
     */
    public <V> Boolean setnx(final String key, final V value, final long timeout, TimeUnit unit) {
        if (Objects.isNull(unit)) {
            unit = TimeUnit.SECONDS;
        }
        ValueOperations<String, V> operations = redisTemplate.opsForValue();
        Boolean result = null;
        try {
            result = operations.setIfAbsent(key, value, timeout, unit);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * INCR key
     * 如果key不存在,那么key的值会先被初始化为0,然后再执行INCR操作。
     * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
     *
     * @param key Redis Key
     * @return 加上1之后,key的值。
     */
    public Long incr(final String key) {
        return this.incrby(key, 1L);
    }

    /**
     * INCRBY key increment
     *
     * @param key   Redis Key
     * @param delta 指定的增量值
     * @return 加上指定的增量值之后,key的值。
     */
    public Long incrby(final String key, final long delta) {
        Long result = null;
        ValueOperations<String, Long> operations = redisTemplate.opsForValue();
        try {
            result = operations.increment(key, delta);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * DECRBY key
     *
     * @param key Redis Key
     * @return 减去1之后,key的值。
     */
    public Long decr(final String key) {
        return this.decrby(key, 1L);
    }

    /**
     * Redis Decrby命令将key所储存的值减去指定的减量值。
     * 如果key不存在,那么key的值会先被初始化为0,然后再执行DECRBY操作。
     * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
     *
     * @param key   Redis Key
     * @param delta 指定减量值
     * @return 减去指定减量值之后,key的值。
     */
    public Long decrby(final String key, final long delta) {
        ValueOperations<String, Long> operations = redisTemplate.opsForValue();
        Long result = null;
        try {
            result = operations.decrement(key, delta);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HDEL key field [field ...]
     *
     * @param key      Redis Key
     * @param hashKeys Hash Keys
     * @return 被成功删除字段的数量,不包括被忽略的字段。
     */
    public Long hdel(final String key, final String... hashKeys) {
        Long result = null;
        try {
            result = redisTemplate.opsForHash().delete(key, hashKeys);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HEXISTS key field
     *
     * @param key     Redis Key
     * @param hashKey Hash Key
     * @return 如果哈希表含有给定字段,返回teue。如果哈希表不含有给定字段,或key不存在,返回false。
     */
    public Boolean hexists(final String key, final String hashKey) {
        Boolean result = null;
        try {
            result = redisTemplate.opsForHash().hasKey(key, hashKey);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HGET key field
     *
     * @param key     Redis Key
     * @param hashKey Hash Key
     * @param <V>     value泛型类型
     * @return 返回给定字段的值。如果给定的字段或key不存在时,返回null。
     */
    public <V> V hget(final String key, final String hashKey) {
        HashOperations<String, String, V> operations = redisTemplate.opsForHash();
        V result = null;
        try {
            result = operations.get(key, hashKey);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HGETALL key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 以列表形式返回哈希表的字段及字段值。若key不存在,返回空列表。
     */
    public <V> Map<String, V> hgetall(final String key) {
        HashOperations<String, String, V> operations = redisTemplate.opsForHash();
        Map<String, V> result = null;
        try {
            result = operations.entries(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HKEYS key
     *
     * @param key Redis Key
     * @return 包含哈希表中所有域(field)列表。当key不存在时,返回一个空列表。
     */
    public Set<String> hkeys(final String key) {
        Set<String> result = null;
        try {
            result = redisTemplate.opsForHash().keys(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HLEN key
     *
     * @param key Redis Key
     * @return 获取哈希表中字段的数量
     */
    public Long hlen(final String key) {
        Long result = null;
        try {
            result = redisTemplate.opsForHash().size(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HMGET key field [field ...]
     * 建议使用LinkedHashSet
     *
     * @param key      Redis Key
     * @param hashKeys Hash Key
     * @param <V>      value泛型类型
     * @return 一个包含多个给定字段关联值的表,表值的排列顺序和指定字段的请求顺序一样。
     */
    public <V> List<V> hmget(final String key, final Set<String> hashKeys) {
        HashOperations<String, String, V> operations = redisTemplate.opsForHash();
        List<V> result = null;
        try {
            result = operations.multiGet(key, hashKeys);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HSET key field value
     *
     * @param key     Redis Key
     * @param hashKey Hash Key
     * @param value   存储的值
     * @param <V>     value泛型类型
     */
    public <V> void hset(final String key, final String hashKey, final V value) {
        try {
            redisTemplate.opsForHash().put(key, hashKey, value);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
    }

    /**
     * HMSET key field value [field value ...]
     *
     * @param key Redis Key
     * @param map Redis Key Value
     * @param <V> value泛型类型
     */
    public <V> void hmset(final String key, final Map<String, V> map) {
        if (!CollectionUtils.isEmpty(map)) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                this.setDefaultExpiredTime(key);
            } catch (Exception exception) {
                LOGGER.error(exception.getMessage(), exception);
            }
        }
    }

    /**
     * HSETNX key field value
     * 只有在字段 field 不存在时,设置哈希表字段的值。
     *
     * @param key     Redis Key
     * @param hashKey Hash Key
     * @param value   存储的值
     * @param <V>     value泛型类型
     * @return 设置成功,返回true。如果给定字段已经存在且没有操作被执行,返回false。
     */
    public <V> Boolean hsetnx(final String key, final String hashKey, final V value) {
        Boolean result = null;
        try {
            result = redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * HVALS key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 一个包含哈希表中所有值的列表。当key不存在时,返回一个空表。
     */
    public <V> List<V> hvals(String key) {
        List<V> result = null;
        try {
            result = redisTemplate.opsForHash().values(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * BLPOP key timeout
     *
     * @param key     Redis Key
     * @param timeout 超时时间
     * @param unit    单位
     * @param <V>     value泛型类型
     * @return 被弹出元素的值
     */
    public <V> V blpop(final String key, final long timeout, TimeUnit unit) {
        if (Objects.isNull(unit)) {
            unit = TimeUnit.SECONDS;
        }
        ListOperations<String, V> operations = redisTemplate.opsForList();
        V result = null;
        try {
            result = operations.leftPop(key, timeout, unit);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * BRPOP key timeout
     *
     * @param key     Redis Key
     * @param timeout 超时时间
     * @param unit    单位
     * @param <V>     value泛型类型
     * @return 被弹出元素的值
     */
    public <V> V brpop(final String key, final long timeout, TimeUnit unit) {
        if (Objects.isNull(unit)) {
            unit = TimeUnit.SECONDS;
        }
        ListOperations<String, V> operations = redisTemplate.opsForList();
        V result = null;
        try {
            result = operations.rightPop(key, timeout, unit);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LINDEX key index
     *
     * @param key   Redis Key
     * @param index 索引
     * @param <V>   value泛型类型
     * @return 通过索引获取列表中的元素
     */
    public <V> V lindex(final String key, final long index) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        V result = null;
        try {
            result = operations.index(key, index);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LLEN key
     *
     * @param key Redis Key
     * @return 列表长度
     */
    public Long llen(final String key) {
        Long result = null;
        try {
            result = redisTemplate.opsForList().size(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LPOP key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 移出并获取列表的第一个元素
     */
    public <V> V lpop(final String key) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        V result = null;
        try {
            result = operations.leftPop(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LPUSH key value
     *
     * @param key   Redis Key
     * @param value 存储的值
     * @param <V>   value泛型类型
     * @return 执行LPUSH命令后,列表的长度
     */
    public <V> Long lpush(final String key, final V value) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        Long result = null;
        try {
            result = operations.leftPush(key, value);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LPUSH key value [value ...]
     *
     * @param key    Redis Key
     * @param values 存储的列表值
     * @param <V>    value泛型类型
     * @return 执行LPUSH命令后,列表的长度
     */
    public <V> Long lpush(final String key, final Collection<V> values) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        Long result = null;
        try {
            result = operations.leftPushAll(key, values);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LRANGE key start stop
     *
     * @param key   Redis Key
     * @param start 开始索引
     * @param end   结束索引
     * @param <V>   value泛型类型
     * @return 列表指定范围内的元素
     */
    public <V> List<V> lrange(final String key, final long start, final long end) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        List<V> result = null;
        try {
            result = operations.range(key, start, end);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * LSET key index value
     *
     * @param key   Redis Key
     * @param index 索引
     * @param value 存储的值
     * @param <V>   value泛型类型
     */
    public <V> void lset(final String key, final long index, final V value) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        try {
            operations.set(key, index, value);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
    }

    /**
     * RPOP key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 被移除的元素
     */
    public <V> V rpop(final String key) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        V result = null;
        try {
            result = operations.rightPop(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * RPUSH key value
     *
     * @param key   Redis Key
     * @param value 存储的值
     * @param <V>   value泛型类型
     * @return 执行RPUSH操作后,列表的长度
     */
    public <V> Long rpush(final String key, final V value) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        Long result = null;
        try {
            result = operations.rightPush(key, value);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * RPUSH key value [value ...]
     *
     * @param key    Redis Key
     * @param values 存储的列表值
     * @param <V>    value泛型类型
     * @return 执行RPUSH操作后,列表的长度
     */
    public <V> Long rpush(final String key, Collection<V> values) {
        ListOperations<String, V> operations = redisTemplate.opsForList();
        Long result = null;
        try {
            result = operations.rightPushAll(key, values);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * SADD key member [member ...]
     *
     * @param key    Redis Key
     * @param values 存储的列表值
     * @param <V>    value泛型类型
     * @return 被添加到集合中的新元素的数量,不包括被忽略的元素。
     */
    public <V> Long sadd(final String key, final V... values) {
        SetOperations<String, V> operations = redisTemplate.opsForSet();
        Long result = null;
        try {
            result = operations.add(key, values);
            this.setDefaultExpiredTime(key);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * SCARD key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 集合的数量。当集合key不存在时,返回0。
     */
    public <V> Long scard(final String key) {
        Long result = null;
        try {
            result = redisTemplate.opsForSet().size(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * SISMEMBER key member
     *
     * @param key    Redis Key
     * @param object 成员元素
     * @return 如果成员元素是集合的成员,返回true。如果成员元素不是集合的成员,或key不存在,返回false。
     */
    public Boolean sismember(final String key, final Object object) {
        Boolean result = null;
        try {
            result = redisTemplate.opsForSet().isMember(key, object);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * SMEMBERS key
     *
     * @param key Redis Key
     * @param <V> value泛型类型
     * @return 集合中的所有成员。
     */
    public <V> Set<V> smembers(final String key) {
        SetOperations<String, V> operations = redisTemplate.opsForSet();
        Set<V> result = null;
        try {
            result = operations.members(key);
        } catch (RedisConnectionFailureException exception) {
            LOGGER.error(exception.getMessage(), exception);
        } catch (QueryTimeoutException exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }

    /**
     * SREM key member [member ...]
     *
     * @param key    Redis Key
     * @param values 删除的值
     * @return 被成功移除的元素的数量,不包括被忽略的元素。
     */
    public Long srem(final String key, final Object... values) {
        Long result = null;
        try {
            result = redisTemplate.opsForSet().remove(key, values);
        } catch (Exception exception) {
            LOGGER.error(exception.getMessage(), exception);
        }
        return result;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis操作工具类 的相关文章

  • StackExchange.Redis 和 StackExchange.Redis.StrongName 之间有什么区别?

    当我关注Azure时文档 http azure microsoft com en us documentation articles cache dotnet how to use azure redis cache 关于如何在Azure
  • 找不到模块“socket.io/node_modules/redis”

    当尝试做的时候 var redis require socket io node modules redis 我收到错误 找不到模块 socket io node modules redis 我不明白为什么 我正在运行 Windows 并运
  • 如何清理redis中不活跃的玩家?

    我正在制作一个使用 redis 来存储游戏状态的游戏 它可以很好地跟踪位置和玩家 但我没有一个好的方法来清理不活跃的玩家 每当玩家移动时 这是一个半慢速移动游戏 想想每秒 1 5 帧 我就会用新位置更新哈希并删除旧位置键 跟踪活跃玩家的最佳
  • Docker&Celery - 错误:Pidfile (celerybeat.pid) 已存在

    应用程序包括 姜戈 雷迪斯 芹菜 码头工人 Postgres 在将项目合并到 docker 之前 一切都运行顺利且正常 但是一旦将其移入容器 就开始出现问题 起初它开始得很好 但过了一会儿我确实收到了以下错误 celery beat 1 E
  • Spring RedisTemplate:8次调用后方法键挂起

    我使用 Spring RedisTemplate spring data redis 1 7 1 与 Redis 进行通信 我需要通过正则表达式获取然后删除键 例如 context user1 我用的方法 RedisTemplate key
  • connect-redis - 如何保护会话对象免受竞争条件影响

    我使用 nodejs 和 connect redis 来存储会话数据 我将用户数据保存在会话中 并在会话生命周期中使用它 我注意到两个更改会话数据的请求之间可能存在竞争条件 我尝试过使用 redis lock 来锁定会话 但这对我来说有点问
  • python 3.5 中的 json.loads 和 Redis

    我使用 json dumps 创建了一个 JSON 对象 并在 Redis 列表中将其 RPUSH ed 当使用 LRANGE redis lrange 返回 JSON 时 我收到一个二进制字符串 b si 00 ff 所以 json lo
  • 如何在多个Lua State(多线程)之间传递数据?

    我在中启动Redis连接池redis lua 通过从 C 调用 我得到了redis lua state 此 Lua 状态全局启动一次 仅在其他线程中启动get从中 当有一个 HTTP 请求 工作线程 时 我需要从redis lua stat
  • Redis键空间事件不触发

    我有两个 Redis 客户端 在一个文件中我有一个简单的脚本设置并删除了 Redis 键 var redis require redis var client redis createClient 6379 127 0 0 1 client
  • 如何统计 Redis 流中未读或已确认的消息?

    使用 Redis 5 0 3 假设我们创建一个名为streamy和一个消费群体consumers XGROUP CREATE streamy consumers MKSTREAM 然后向其中添加一些消息 XADD streamy messa
  • redis-cli 重定向到 127.0.0.1

    我在PC1上启动Redis集群 然后在PC2上连接它 当需要重定向到另一个集群节点时 它会显示Redirected to slot 7785 located at 127 0 0 1 但应该显示Redirected to slot 7785
  • Redis INCRBY 有限制

    我想知道是否有一种方法可以通过我的应用程序的单次往返在 Redis 中执行此操作 对于给定的键K 其可能值V是范围内的任意整数 A B 基本上 它有上限和下限 When an INCRBY or DECRBY发出命令 例如INCRBY ke
  • 如何批量删除Redis中数十万个带有特殊字符的key

    我们有一个包含数十万个 Redis 键的列表 其中包含各种特殊字符 我们希望批量删除它们 对于这个问题上的类似问题 有一些很好的答案 如何使用 Redis 自动删除与模式匹配的键 https stackoverflow com questi
  • 如何测试我的 Redis 缓存是否正常工作?

    我已经安装了 django redis cache 和 redis py 我遵循了 Django 的缓存文档 据我所知 以下设置就是我所需要的 但我如何判断它是否正常工作 设置 py CACHES default BACKEND redis
  • Node Js:Redis 作业在完成其任务后未完成

    希望你们做得很好 我在我的 Nodejs 项目中实现了 BullMQ Bull 的下一个主要版本 来安排发送电子邮件的作业 例如 发送忘记密码请求的电子邮件 所以 我编写了如下所示的代码 用户服务 await resetPasswordJo
  • Redis Cluster 与 Pub/Sub 中的 ZeroMQ,用于水平扩展的分布式系统

    如果我要设计一个巨大的分布式系统 其吞吐量应随系统中的订阅者数量和通道数量线性扩展 哪个会更好 1 Redis集群 仅适用于Redis 3 0 alpha 如果是集群模式 您可以在一个节点上发布并在另一个完全不同的节点上订阅 消息将传播并到
  • redis - 使用哈希

    我正在使用 redis 为我的 Web 应用程序实现社交流和通知系统 我是 redis 的新手 我对哈希值及其效率有一些疑问 我读过这篇很棒的文章Instagram 帖子 http instagram engineering tumblr
  • 有没有办法让特定的key在集群模式下定位到特定的redis实例上?

    我想让我的多锁位于不同的redis实例上 我发现redission可以指定一个实例来执行命令 但是如果该命令与key相关 则指定的实例会将命令传输到另一个实例 你能给我一些建议吗 你可以 但这并不是微不足道的 首先 Redis 在键中使用大
  • 使用 Celery 通过 Gevent 进行实时、同步的外部 API 查询

    我正在开发一个 Web 应用程序 该应用程序将接收用户的请求 并且必须调用许多外部 API 来编写对该请求的答案 这可以直接从主 Web 线程使用 gevent 之类的东西来扇出请求来完成 或者 我在想 我可以将传入的请求放入队列中 并使用
  • Redis+Docker+Django - 错误 111 连接被拒绝

    我正在尝试使用 Redis 作为使用 Docker Compose 的 Django 项目的 Celery 代理 我无法弄清楚我到底做错了什么 但尽管控制台日志消息告诉我 Redis 正在运行并接受连接 事实上 当我这样做时 docker

随机推荐

  • 初始C语言——统计单词

    define CRT SECURE NO WARNINGS 1 防止visual studio2013以上版本scanf报错 vc6 0环境可忽略 include
  • python算法中的深度学习算法之深度信念网络(详解)

    目录 学习目标 学习内容 深度信念网络 预训练 微调 学习目标 一分钟掌握 python算法中的深度学习算法之深度信念网络 入门知识
  • pip安装jupyter notebook后找不到jupyter notebook命令

    安装jupyter pip install jupyter notebook 配置环境变量 在系统变量的path中添加一下路径 YourUsername是你的用户名 C Users YourUsername AppData Roaming
  • 【转载】[python基础] python中变量存储的方式

    为了解决刚刚python 2 循环运算中 变量存储的地址与期望值的地址不同的问题 稍微检索了下python中变量的存储方式 虽然并没有解决问题 但应该可以猜测是python 3更新期间 修改 或者说bugfix 了变量存储的方式 所以在py
  • 斯坦福大学吴恩达教授联手OpenAI上线chatGPT免费课程

    斯坦福大学吴恩达教授和 OpenAI 一起制作了四个关于 ChatGPT 的短课程 一共有四个课 每个课都是一个小时左右 并且每个课被分成了多个小节 建议收看的顺序是 1 ChatGPT Prompt Engineering for Dev
  • spring ajax传输json

    ajax传输文件 主要用一个jquery文件来执行 链接 https pan baidu com s 12 YznRvPxxsvADqbKSoseg 提取码 lphb 发送Ajax请求要 用到 js jquery文件 为了 防止 静态文件被
  • 论文阅读-Joint Audio-Visual Deepfake Detection(音视频Deepfake检测)

    一 论文信息 论文名称 Joint Audio Visual Deepfake Detection 会议 ICCV2021 作者团队 二 动机与创新 动机 Visual deepfake上有许多检测方法和数据集 而对audio deepfa
  • css滚动条样式属性

    webkit scrollbar 滚动条整体部分 可以设置宽度 webkit scrollbar button 滚动条两端的按钮 webkit scrollbar track 外层轨道 webkit scrollbar track piec
  • FIO详解

    fio Flexible IO Tester 一 服务器配置 由于我们想通过fio得到SSD真实的参数信息 因此我们需要服务器BIOS一些参数的配合 以便能更好的体现硬盘的性能 以华为1288HV5为例 二 fio 1 安装 a 下载地址
  • C++ reverse函数使用

    STL C reverse remove remove if 1 reverse函数使用 函数功能 将序列 first last 的元素在原容器中颠倒重排 包含在algorithm库中 C 头文件 include reverse函数用于反转
  • 服务器换主板要重装系统吗,换主板需要重装系统吗【解决方案】

    有不少用户在使用电脑的过程中可能会碰到换主板需要重装系统吗的情况 大部分用户电脑技术都是菜鸟水平 面对换主板需要重装系统吗的问题 无法自行解决 不少用户都来咨询小编换主板需要重装系统吗要怎么处理 其实可以根据以下步骤 1 打开机箱 将除了显
  • 简单易学的机器学习算法——Softmax Regression

    Contents hide 1 简介 2 代价函数 3 Softmax回归模型参数化的特点 4 权重衰减 5 Softmax回归与Logistic 回归的关系 6 Softmax 回归 vs k 个二元分类器 7 中英文对照 8 中文译者
  • 2019年利用qshell将七牛云存储文件下载到本地的方法

    最近在做一个有赞微商城的课程设置 想着先丰富微商城的课程内容 于是就想到了使用之前课程网站的视频 第一步当然就是要把课程视频下载下来 但由于原来网站的视频都是技术开发人员之前把视频上传到了七牛后调用的 而且还做了防盗链处理 于是找到七牛云存
  • cuBLAS使用(1)

    cuBLAS 的 API 参考指南 CUDA 基本线性代数子程序库 CUDA Basic Linear Algebra Subroutine 介绍 cuBLAS库是在NVIDIA CUDA 运行时之上实现的BLAS 基本线性代数子程序 它允
  • buucft web (exec)

    一 解题 打开链接 发现是一道ping题 于是便输入本地IP127 0 0 1查看回显 发现回显正常 然后便测试管道符合 是否可用并输入 127 0 0 1 ls 来查看文件目录 结果发现管道符合 并未禁用且发现以下两个文件目录 然后输入
  • 转盘中文字部分的实现(没啥用,别看)

    text width 642rpx height 642rpx width 590rpx height 590rpx margin left 26rpx margin top 26rpx display flex justify conte
  • uniapp上传图片视频文件集合组件

  • 分享一个科幻风的404

    先看效果 再看代码
  • 华为OD机试 C++ 最大可靠性设备

    题目 你正在组装一台设备 这台设备由不同种类的零件组成 每种类型的零件都需要一个 每个零件都有自己的 可靠度 和价格 昂贵的零件通常具有更高的可靠度 但是 组装完成的设备的可靠度是由所有零件中可靠度最低的那个决定的 也就是说 如果你有5个零
  • Redis操作工具类

    前期文章中关于RedisOperateUtil工具类使用时需要强制类型转换 针对List等操作不方便 为此特意更新RedisOperateUtil工具类 前文链接 https blog csdn net liwenyang1992 arti