SpringBoot2.3整合Redis6实现基本操作

本文详细介绍了如何在SpringBoot 2.3应用中整合Redis进行数据操作,包括配置Redis连接、序列化设置、创建RedisTemplate及CacheManager,并提供了丰富的Redis数据类型操作接口如String、List、Set、Hash、ZSet等,以及Bitmaps、HyperLogLog和Geospatial命令的使用。
摘要由CSDN通过智能技术生成

1. 概述

Redis是一个开源的key-value存储系统,支持多种数据类型,常用于做高速缓存和存储多样的持久化数据。本文主要介绍SpringBoot2.3整合Redis实现基本的数据操作,包括5中常用的数据类型和3中新型数据类型。

2. 引入核心依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

3. yml配置信息

spring:
  application:
    name: springboot-redis
  redis:
    host: xx.xx.xx.xx
    port: 6379
    database: 0
    timeout: 1800000 #连接超时时间 毫秒
    lettuce:
      pool:
        max-active: 8 #连接池最大连接数 负数表示没有限制
        max-wait: -1m #最大阻塞等待时间 负数表示没有限制
        max-idle: 5 #连接池最大空闲连接
        min-idle: 0 #连接池最小空闲连接

4. 配置类

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常问题
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);
        //配置序列化(解决乱码问题),过期时间600秒
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(configuration).build();
        return cacheManager;
    }
}

5. 接口封装

public interface RedisService {

    /**
     * 查看所有key
     * @param pattern key *
     * @return
     */
    Set<String> keys(String pattern);

    /**
     * 查询key是否存在
     * @param key
     * @return
     */
    Boolean existsKey(String key);

    /**
     * 查看key类型
     * @param key
     * @return
     */
    DataType type(String key);

    /**
     * 删除key
     * @param key
     * @return
     */
    Boolean delete(String key);

    /**
     * 根据value选择非阻塞删除
     * @param key
     * @return
     */
    Boolean unlink(String key);

    /**
     * 给指定key设置过期时间
     * @param key
     * @param times
     * @param timeUnit
     * @return
     */
    Boolean expireKey(String key, long times, TimeUnit timeUnit);

    /**
     * 查看还是多少秒过期
     * @param key
     * @return -1表示不过期,-2表示已过期
     */
    Long ttl(String key);

    /**
     * 设置key-value
     * @param key
     * @param value
     */
    void set(String key, String value);

    /**
     * 设置带过期时间的key-value
     * @param key
     * @param value
     * @param times
     */
    void set(String key, String value, long times);

    /**
     * 获取key的值
     * @param key
     * @return
     */
    String get(String key);

    /**
     * 将给定的value追加到原值末尾
     * @param key
     * @param value
     * @return
     */
    Integer append(String key, String value);

    /**
     * 获取值的长度
     * @param key
     * @return
     */
    Long strlen(String key);

    /**
     * 当key不存在时,设置key的值
     * @param key
     * @param value
     * @return
     */
    Boolean setnx(String key, String value);

    /**
     * 将key中的数字增1
     * @param key
     * @return
     */
    Long incr(String key);

    /**
     * 将key中数字减1
     * @param key
     * @return
     */
    Long decr(String key);

    /**
     * 将key中数字增自定义步长
     * @param key
     * @param step
     * @return
     */
    Long incrby(String key, long step);

    /**
     * 将key中数字减自定义步长
     * @param key
     * @param step
     * @return
     */
    Long decrby(String key, long step);

    /**
     * 同时设置一个或多个值
     * @param map
     */
    void mset(Map<String, String> map);

    /**
     * 同时获取一个或多个值
     * @param keys
     * @return
     */
    List<String> mget(List<String> keys);

    /**
     * 同时设置一个或多个值,仅当key都不存在
     * @param map
     * @return
     */
    Boolean msetnx(Map<String, String> map);

    /**
     * 获取值的范围,前后都包括
     * @param key
     * @param start
     * @param stop
     * @return
     */
    String getrange(String key, long start, long stop);

    /**
     * 设置键值的同时,设置过期时间
     * @param key
     * @param expire
     * @param value
     */
    void setex(String key, int expire, String value);

    /**
     * 设置新值同时获取旧值
     * @param key
     * @param value
     * @return
     */
    String getset(String key, String value);

    /**
     * 获取分布式锁
     * @return
     */
    Long getDistributedLock();

    /**
     * 简单限流 period秒最大执行maxCount次
     * @param key
     * @param period
     * @param maxCount
     * @return
     */
    Boolean SimpleRateLimiter(String key, long period, int maxCount);

    /**
     * 漏洞限流
     * @param key
     * @param capacity
     * @param leakingRate
     * @return
     */
    Boolean FunnelRateLimiter(String key, int capacity, float leakingRate);

    /**
     * 向list中左边插入一个值
     * @param key
     * @param value
     * @return
     */
    Long lpush(String key, String value);

    /**
     * 向list中左边插入多个值
     * @param key
     * @param value
     * @return
     */
    Long lpush(String key, String... value);

    /**
     * 向list右边插入一个值
     * @param key
     * @param value
     * @return
     */
    Long rpush(String key, String value);

    /**
     * 向list右边插入多个值
     * @param key
     * @param value
     * @return
     */
    Long rpush(String key, String... value);

    /**
     * 从list左边取出一个值
     * @param key
     * @return
     */
    String lpop(String key);

    /**
     * 从list右边取出一个值
     * @param key
     * @return
     */
    String rpop(String key);

    /**
     * 从list key1右边取出一个值,插到key2左边
     * @param key1
     * @param key2
     * @return
     */
    String rpoplpush(String key1, String key2);

    /**
     * 按照索引下标获取元素 当start=0/stop=-1时表示获取所有
     * @param key
     * @param start
     * @param stop
     * @return
     */
    List<String> lrange(String key, int start, int stop);

    /**
     * 按照索引下标获取元素
     * @param key
     * @param index
     * @return
     */
    String lindex(String key, int index);

    /**
     * 获取key长度
     * @param key
     * @return
     */
    Long llen(String key);

    /**
     * 在oldValue后面插入newValue
     * @param key
     * @param oldValue
     * @param newValue
     * @return
     */
    Long linsert(String key, String oldValue, String newValue);

    /**
     * 从左边删除n个value
     * @param key
     * @param num
     * @param value
     * @return
     */
    Long lrem(String key, int num, String value);

    /**
     * 将key下标为index的值替换成value
     * @param key
     * @param index
     * @param value
     */
    void lset(String key, int index, String value);

    /**
     * 将一个或多个member元素加入set集合,已经存在的member元素将被忽略
     * @param key
     * @param value
     * @return
     */
    Long sadd(String key, String... value);

    /**
     * 取出set集合中所有值
     * @param key
     * @return
     */
    Set<String> smembers(String key);

    /**
     * 判断set集合中是否含有value值
     * @param key
     * @param value
     * @return
     */
    Boolean sismember(String key, String value);

    /**
     * 返回set集合元素个数
     * @param key
     * @return
     */
    Long scard(String key);

    /**
     * 删除集合中某个元素
     * @param key
     * @param value
     * @return
     */
    Long srem(String key, String... value);

    /**
     * 随机从set集合取出一个值
     * @param key
     * @return
     */
    String spop(String key);

    /**
     * 随机从set集合取出n个值,不会删除
     * @param key
     * @param num
     * @return
     */
    List<String> srandmember(String key, int num);

    /**
     * 把set集合中一个值从一个集合移动到另一个集合
     * @param sourceKey
     * @param value
     * @param destKey
     * @return
     */
    Boolean smove(String sourceKey, String value, String destKey);

    /**
     * 返回两个集合的交集
     * @param key1
     * @param key2
     * @return
     */
    Set<String> sinter(String key1, String key2);

    /**
     * 返回两个集合的并集
     * @param key1
     * @param key2
     * @return
     */
    Set<String> sunion(String key1, String key2);

    /**
     * 返回两个集合的差集
     * @param key1
     * @param key2
     * @return
     */
    Set<String> sdiff(String key1, String key2);

    /**
     * 给hash集合中field赋值value
     * @param key
     * @param field
     * @param value
     */
    void hset(String key, String field, String value);

    /**
     * 获取hash集合field的值
     * @param key
     * @param field
     * @return
     */
    Object hget(String key, String field);

    /**
     * 批量设置hash的值
     * @param key
     * @param map
     */
    void hmset(String key, Map<String, Object> map);

    /**
     * 查看hash表key中,给定field是否存在
     * @param key
     * @param field
     * @return
     */
    Boolean hexists(String key, String field);

    /**
     * 列出该hash集合所有field
     * @param key
     * @return
     */
    Set<Object> hkeys(String key);

    /**
     * 列出hash集合中所有value
     * @param key
     * @return
     */
    List<Object> hvals(String key);

    /**
     * 为hash key中field的值加上增量1 或 -1
     * @param key
     * @param field
     * @param increment
     * @return
     */
    Long hincrby(String key, String field, int increment);

    /**
     * 将hash表key中的field的值设为value,当且仅当field不存在
     * @param key
     * @param field
     * @param value
     * @return
     */
    Boolean hsetnx(String key, String field, String value);

    /**
     * 将一个或多个member元素及其score值加入到zset中
     * @param key
     * @param value
     * @param score
     * @return
     */
    Boolean zadd(String key, String value, double score);

    /**
     * 返回下标在start和stop之间的元素
     * @param key
     * @param start
     * @param stop
     * @return
     */
    Set<String> zrange(String key, long start, long stop);

    /**
     * 返回下标在start和stop之间的元素包括分数
     * @param key
     * @param start
     * @param stop
     * @return
     */
    Set<ZSetOperations.TypedTuple<String>> zrangewithscore(String key, long start, long stop);

    /**
     * 返回所有score值介于min和max之间的元素,并按score递增排序
     * @param key
     * @param min
     * @param max
     * @return
     */
    Set<String> zrangebyscore(String key, double min, double max);

    /**
     * 返回所有score值介于min和max之间的元素,并按score递减排序
     * @param key
     * @param min
     * @param max
     * @return
     */
    Set<String> zrevrangebyscore(String key, double min, double max);

    /**
     * 为zset的score加增量
     * @param key
     * @param value
     * @param increment
     * @return
     */
    Double zincrby(String key, String value, int increment);

    /**
     * 删除zset下指定元素
     * @param key
     * @param value
     * @return
     */
    Long zrem(String key, String value);

    /**
     * 统计zset分数区间内元素个数
     * @param key
     * @param min
     * @param max
     * @return
     */
    Long zcount(String key, double min, double max);

    /**
     * 返回在zset中排名,从0开始
     * @param key
     * @param value
     * @return
     */
    Long zrank(String key, String value);

    /********************Bitmaps命令操作********************/
    /**
     * 设置bitmaps中偏移量offset的值
     * @param key
     * @param offset 偏移量
     * @param value 值 1:true;0:false
     * @return
     */
    boolean setbit(String key, long offset, boolean value);

    /**
     * 获取bitmaps中偏移量的值
     * @param key
     * @param offset 从0开始
     * @return
     */
    Boolean getbit(String key, long offset);

    /**
     * 统计key从start字节到end字节比特值为1的数量
     * @param key
     * @param start
     * @param end
     * @return
     */
    Long bigcount(String key, long start, long end);

    /**
     * 获取多个bitmaps的交集/并集/非/异或并保存结果到destkey中
     * @param operation 操作符 AND, OR, XOR, NOT
     * @param destKey 结果key
     * @param keys
     */
    void bitop(RedisStringCommands.BitOperation operation, String destKey, String... keys);

    /********************HyperLogLog命令操作********************/
    /**
     * 添加元素到hyperloglog
     * @param key
     * @param value
     * @return
     */
    Long pfadd(String key, String... value);

    /**
     * 统计多个值
     * @param keys
     * @return
     */
    Long pfcount(String... keys);

    /**
     * 将一个或多个hll合并后保存到destkey
     * @param destKey
     * @param sourceKeys
     * @return
     */
    Long pfmerge(String destKey, String... sourceKeys);

    /********************Geospatial命令操作********************/
    /**
     * 添加地理位置
     * @param key
     * @param longitude 经度
     * @param latitude 纬度
     * @param member 名称
     * @return
     */
    Long geoadd(String key, double longitude, double latitude, String member);

    /**
     * 获取指定地区坐标值
     * @param key
     * @param members
     * @return
     */
    List<Point> geopos(String key, String... members);

    /**
     * 获取两个位置的直线距离
     * @param key
     * @param member1
     * @param member2
     * @return
     */
    Distance geodist(String key, String member1, String member2);

    /**
     * 给定经纬度为中心,找出某半径内的值
     * @param key
     * @param longitude
     * @param latitude
     * @param radius
     */
    void georadius(String key, double longitude, double latitude, double radius);

    /**
     * 给定地理位置为中心,找出某一半径内的值
     * @param key
     * @param member
     * @param radius
     */
    void georadius(String key, String member, double radius);
}

6. 接口实现

@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public void set(String key, String value, long times) {
        redisTemplate.opsForValue().set(key, value, times);
    }

    @Override
    public String get(String key) {
        String value = redisTemplate.opsForValue().get(key);
        return value;
    }

    @Override
    public Integer append(String key, String value) {
        return redisTemplate.opsForValue().append(key, value);
    }

    @Override
    public Long strlen(String key) {
        return redisTemplate.opsForValue().size(key);
    }

    @Override
    public Boolean setnx(String key, String value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
        //return redisTemplate.opsForValue().setIfAbsent(key, value, 3, TimeUnit.SECONDS);
    }

    @Override
    public Long incr(String key) {
        return redisTemplate.opsForValue().increment(key);
    }

    @Override
    public Long decr(String key) {
        return redisTemplate.opsForValue().decrement(key);
    }

    @Override
    public Long incrby(String key, long step) {
        return redisTemplate.opsForValue().increment(key, step);
    }

    @Override
    public Long decrby(String key, long step) {
        return redisTemplate.opsForValue().decrement(key, step);
    }

    @Override
    public void mset(Map<String, String> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    @Override
    public List<String> mget(List<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    @Override
    public Boolean msetnx(Map<String, String> map) {
        return redisTemplate.opsForValue().multiSetIfAbsent(map);
    }

    @Override
    public String getrange(String key, long start, long stop) {
        return redisTemplate.opsForValue().get(key, start, stop);
    }

    @Override
    public void setex(String key, int expire, String value) {
        redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
    }

    @Override
    public String getset(String key, String value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    @Override
    public Boolean expireKey(String key, long times, TimeUnit timeUnit) {
        Boolean expire = redisTemplate.expire(key, times, timeUnit);
        return expire;
    }

    @Override
    public Long ttl(String key) {
        return redisTemplate.getExpire(key);
        //return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    @Override
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    @Override
    public Boolean existsKey(String key) {
        Boolean hasKey = redisTemplate.hasKey(key);
        return hasKey;
    }

    @Override
    public DataType type(String key) {
        return redisTemplate.type(key);
    }

    @Override
    public Boolean delete(String key) {
        Boolean delete = redisTemplate.delete(key);
        return delete;
    }

    @Override
    public Boolean unlink(String key) {
        return redisTemplate.unlink(key);
    }

    @Override
    public Long getDistributedLock() {
        String uuid = UUID.randomUUID().toString();
        String lockKey = "lock:100";
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, uuid, 3, TimeUnit.SECONDS);
        Long execute = -1L;
        if (lock) {
            //执行业务逻辑
            //todo
            //定义lua脚本
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.cal('del', KEYS[1]) else return 0 end";
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setScriptText(script);
            redisScript.setResultType(Long.class);
            execute = redisTemplate.execute(redisScript, Arrays.asList(lockKey), uuid);
        } else {
            try {
                Thread.sleep(1000);
                getDistributedLock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return execute;
    }

    @Override
    public Boolean SimpleRateLimiter(String key, long period, int maxCount) {
        key = "hist:" + key;
        long milli = Instant.now().toEpochMilli();
        redisTemplate.multi();
        redisTemplate.opsForZSet().add(key, String.valueOf(milli), Double.valueOf(milli));
        redisTemplate.opsForZSet().removeRangeByScore(key, 0, milli - period * 1000);
        Long count = redisTemplate.opsForZSet().zCard(key);
        redisTemplate.expire(key, period, TimeUnit.SECONDS);
        redisTemplate.exec();
        return count <= maxCount;
    }

    @Override
    public Boolean FunnelRateLimiter(String key, int capacity, float leakingRate) {
        Map<String, Funnel> funnels = new HashMap<>();
        Funnel funnel = funnels.get(key);
        if (funnel == null) {
            funnel = new Funnel(capacity, leakingRate);
            funnels.put(key, funnel);
        }
        return funnel.watering(1);
    }

    @Override
    public Long lpush(String key, String value) {
        Long push = redisTemplate.opsForList().leftPush(key, value);
        return push;
    }

    @Override
    public Long lpush(String key, String... value) {
        Long pushAll = redisTemplate.opsForList().leftPushAll(key, value);
        return pushAll;
    }

    @Override
    public Long rpush(String key, String value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    @Override
    public Long rpush(String key, String... value) {
        return redisTemplate.opsForList().rightPushAll(key, value);
    }

    @Override
    public String lpop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    @Override
    public String rpop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    @Override
    public String rpoplpush(String key1, String key2) {
        return redisTemplate.opsForList().rightPopAndLeftPush(key1, key2);
    }

    @Override
    public List<String> lrange(String key, int start, int stop) {
        return redisTemplate.opsForList().range(key, start, stop);
    }

    @Override
    public String lindex(String key, int index) {
        return redisTemplate.opsForList().index(key, index);
    }

    @Override
    public Long llen(String key) {
        return redisTemplate.opsForList().size(key);
    }

    @Override
    public Long linsert(String key, String oldValue, String newValue) {
        return redisTemplate.opsForList().leftPush(key, oldValue, newValue);
    }

    @Override
    public Long lrem(String key, int num, String value) {
        return redisTemplate.opsForList().remove(key, num, value);
    }

    @Override
    public void lset(String key, int index, String value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    @Override
    public Long sadd(String key, String... value) {
        return redisTemplate.opsForSet().add(key, value);
    }

    @Override
    public Set<String> smembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    @Override
    public Boolean sismember(String key, String value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    @Override
    public Long scard(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    @Override
    public Long srem(String key, String... value) {
        return redisTemplate.opsForSet().remove(key, value);
    }

    @Override
    public String spop(String key) {
        return redisTemplate.opsForSet().pop(key);
    }

    @Override
    public List<String> srandmember(String key, int num) {
        return redisTemplate.opsForSet().randomMembers(key, num);
    }

    @Override
    public Boolean smove(String sourceKey, String value, String destKey) {
        return redisTemplate.opsForSet().move(sourceKey, value, destKey);
    }

    @Override
    public Set<String> sinter(String key1, String key2) {
        return redisTemplate.opsForSet().intersect(key1, key2);
    }

    @Override
    public Set<String> sunion(String key1, String key2) {
        return redisTemplate.opsForSet().union(key1, key2);
    }

    @Override
    public Set<String> sdiff(String key1, String key2) {
        return redisTemplate.opsForSet().difference(key1, key2);
    }

    @Override
    public void hset(String key, String field, String value) {
        redisTemplate.opsForHash().put(key, field, value);
    }

    @Override
    public Object hget(String key, String field) {
        return redisTemplate.opsForHash().get(key, field);
    }

    @Override
    public void hmset(String key, Map<String, Object> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    @Override
    public Boolean hexists(String key, String field) {
        return redisTemplate.opsForHash().hasKey(key, field);
    }

    @Override
    public Set<Object> hkeys(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    @Override
    public List<Object> hvals(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    @Override
    public Long hincrby(String key, String field, int increment) {
        return redisTemplate.opsForHash().increment(key, field, increment);
    }

    @Override
    public Boolean hsetnx(String key, String field, String value) {
        return redisTemplate.opsForHash().putIfAbsent(key, field, value);
    }

    @Override
    public Boolean zadd(String key, String value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    @Override
    public Set<String> zrange(String key, long start, long stop) {
        return redisTemplate.opsForZSet().range(key, start, stop);
    }

    @Override
    public Set<ZSetOperations.TypedTuple<String>> zrangewithscore(String key, long start, long stop) {
        return redisTemplate.opsForZSet().rangeWithScores(key, start, stop);
    }

    @Override
    public Set<String> zrangebyscore(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
        //return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
    }

    @Override
    public Set<String> zrevrangebyscore(String key, double min, double max) {
        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
        //return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max);
    }

    @Override
    public Double zincrby(String key, String value, int increment) {
        return redisTemplate.opsForZSet().incrementScore(key, value, increment);
    }

    @Override
    public Long zrem(String key, String value) {
        return redisTemplate.opsForZSet().remove(key, value);
    }

    @Override
    public Long zcount(String key, double min, double max) {
        return redisTemplate.opsForZSet().count(key, min, max);
    }

    @Override
    public Long zrank(String key, String value) {
        return redisTemplate.opsForZSet().rank(key, value);
    }

    @Override
    public boolean setbit(String key, long offset, boolean value) {
        return redisTemplate.opsForValue().setBit(key, offset, value).booleanValue();
    }

    @Override
    public Boolean getbit(String key, long offset) {
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    @Override
    public Long bigcount(String key, long start, long end) {
        return redisTemplate.execute((RedisCallback<Long>) count -> count.bitCount(key.getBytes(), start, end));
        //return redisTemplate.execute((RedisCallback<Long>) count -> count.bitCount(key.getBytes()));
    }

    @Override
    public void bitop(RedisStringCommands.BitOperation operation, String destKey, String... keys) {
        redisTemplate.execute((RedisCallback<Long>) top -> top.bitOp(operation, destKey.getBytes(), Arrays.stream(keys).map(key -> key.getBytes()).collect(Collectors.toList()).toArray(new byte[keys.length][])));
    }

    @Override
    public Long pfadd(String key, String... value) {
        return redisTemplate.opsForHyperLogLog().add(key, value);
    }

    @Override
    public Long pfcount(String... keys) {
        return redisTemplate.opsForHyperLogLog().size(keys);
    }

    @Override
    public Long pfmerge(String destKey, String... sourceKeys) {
        return redisTemplate.opsForHyperLogLog().union(destKey, sourceKeys);
    }

    @Override
    public Long geoadd(String key, double longitude, double latitude, String member) {
        Point point = new Point(longitude, longitude);
        return redisTemplate.opsForGeo().add(key, point, member);
    }

    @Override
    public List<Point> geopos(String key, String... members) {
        return redisTemplate.opsForGeo().position(key, members);
    }

    @Override
    public Distance geodist(String key, String member1, String member2) {
        return redisTemplate.opsForGeo().distance(key, member1, member2);
        //return redisTemplate.opsForGeo().distance(key, member1, member2, Metrics.KILOMETERS);
    }

    @Override
    public void georadius(String key, double longitude, double latitude, double radius) {
        Point point = new Point(longitude, latitude);
        Circle circle = new Circle(point, radius);
        redisTemplate.opsForGeo().radius(key, circle);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(2).sortAscending();
        redisTemplate.opsForGeo().radius(key, circle, args);
    }

    @Override
    public void georadius(String key, String member, double radius) {
        redisTemplate.opsForGeo().radius(key, member, radius);
        Distance distance = new Distance(radius);
        redisTemplate.opsForGeo().radius(key, member, distance);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(2).sortAscending();
        redisTemplate.opsForGeo().radius(key, member, distance, args);
    }

    private class Funnel {
        int capacity;
        float leakingRate;
        int leftQuota;
        long leakingTs;

        public Funnel(int capacity, float leakingRate) {
            this.capacity = capacity;
            this.leakingRate = leakingRate;
            this.leftQuota = capacity;
            this.leakingTs = Instant.now().toEpochMilli();
        }

        void makeSpace() {
            long nowTs = Instant.now().toEpochMilli();
            long deltaTs = nowTs - leakingTs;
            int deltaQuota = (int) (deltaTs * leakingRate);
            if (deltaQuota < 0) {
                this.leftQuota = capacity;
                this.leakingTs = nowTs;
                return;
            }
            if (deltaQuota < 1) {
                return;
            }
            this.leftQuota += deltaQuota;
            this.leakingTs = nowTs;
            if (this.leftQuota > this.capacity) {
                this.leftQuota = this.capacity;
            }
        }

        boolean watering(int quota) {
            makeSpace();
            if (this.leftQuota >= quota) {
                this.leftQuota -= quota;
                return true;
            }
            return false;
        }
    }
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值