Redis的计数功能

Redis的学习专栏:http://t.csdnimg.cn/a8cvV

许多应用都会使用Redis作为计数的基本工具,可以实现快速计数、查询缓存的功能,同时数据也可以异步处理。例如:博客浏览,用户每查看一次,就会增加一次的访问量;手机验证码,一分钟之内只能发送一次!

普通的计数器,有很多bug,比如:访问量计数方式呢?阅读程度呢?总不可能一刷新就增加一次吧!

解决方法:在规定时间内一个用户,不能超过规定只能访问一次。而这种情况,我们可以先将数据存储在主存里,然后同步到数据库当中。

方法:

  1. 先初始化一下RedisTemplate,这个是操作redis的第三方库,我们先要对他初始化一下(重新序列化)
java 复制代码
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // 这个地方不可使用 json 序列化,如果使用的是ObjectRecord传输对象时,可能会有问题,会出现一个 java.lang.IllegalArgumentException: Value must not be null! 错误
        redisTemplate.setHashValueSerializer(RedisSerializer.string());
        return redisTemplate;
    }
}

2.访问

java 复制代码
 /**
     * 利用redis做计数器
     * 可以处理业务上面的的一些访问次数之类的
     * 例如:文章的点赞数,阅读量,允许有一点的延迟效果,先保存到redis中,然后在同步到数据库当中
     */
    @RequestMapping("hello")
    public void count() {
        /**
         * 判断是否到达次数
         */
        Boolean aBoolean = invokeExceededTimes("time_key2",1,3);
        if (aBoolean) {
            LOGGER.info("可以访问");
        }else {
            LOGGER.info("请求次数达标了");
        }
    }

    /**
     * 判断同一个key在规定时间内访问次数是否到达了最高值
     * @param key   键
     * @param days  时间
     * @param count 一定时间内的访问次数
     * @return
     */
    public Boolean invokeExceededTimes(String key, int days, int count) {

        LOGGER.info("key值:{}",key);
        // 判断在redis中是否有key值
        Boolean redisKey = stringRedisTemplate.hasKey(key);
        if (redisKey) {
            // 获取key所对应的value
            Integer hasKey =Integer.parseInt((String)stringRedisTemplate.opsForValue().get(key));
            if (hasKey >= count) {
                return false;
            }
            // 对value进行加1操作
            stringRedisTemplate.opsForValue().increment(key,1);
            return true;
        }else {
            // 如果没有key值,对他进行添加到redis中
            stringRedisTemplate.opsForValue().set(key,"1",days,TimeUnit.DAYS);
        }
        return true;
    }

我们设置每一个Redis当中的KEY值,如果KEY当中的值超过固定次数,则不会再自增了,而一旦过了存活时间之后就可以再次访问了。

RedisTemplate 常用方法

|------------------------------------------------------------------|----------------------------------------------------------------------|
| Boolean expire(K key, final long timeout, final TimeUnit unit) | 为指定的 key 指定缓存失效时间。时间一到 key 会被移除。key 不存在时,不影响 |
| Boolean expireAt(K key, final Date date) | 设置 key 失效日期。注意:如果 key 后续被重新设置值,比如 set key value,则 key 过期时间失效,需要重新设置。 |
| Long getExpire(K key) | 获取 key 的剩余过期时间。 -1 表示永久有效。-2 表示 key 不存在。 |
| Long getExpire(K key, final TimeUnit timeUnit) | 获取 key 的剩余过期时间,并换算成指定的时间单位 |
| Boolean hasKey(K key) | 判断 key 是否存在 |
| Boolean delete(K key) | 删除指定的 key |
| Long delete(Collection keys) | 删除多个 key |
| RedisSerializer<?> getDefaultSerializer() | 获取默认的序列化方式。RedisTemplate 是 JdkSerializationRedisSerializer; |
| Set keys(K pattern) | 获取整个库下符合指定正则的所有 key,如 keys(*) 获取所有 key |
| Boolean move(K key, final int dbIndex) | 将 key 从当前库移动目标库 dbIndex |
| ClusterOperations<K, V> opsForCluster() | 获取 ClusterOperations 用于操作集群 |
| GeoOperations<K, V> opsForGeo() | 获取 GeoOperations 用于操作地图 |
| redisTemplate.getConnectionFactory().getConnection().flushAll(); | //清空 redis 所有数据库(all databases)中的所有数据(all keys) |
| redisTemplate.getConnectionFactory().getConnection().flushDb(); | 清空 redis 当前连接的数据库(selected database)中的所有数据(all keys) |

还有很多很多方法,需要时再去找、使用。

相关推荐
王ASC1 小时前
JDBC使用p6spy记录实际执行SQL方法【解决SQL打印两次问题】
数据库·sql
一直要努力哦3 小时前
Redis最终篇分布式锁以及数据一致性
数据库·redis·缓存
wqq_9922502774 小时前
ssm面向品牌会员的在线商城小程序
数据库·小程序
呼啦啦呼啦啦啦啦啦啦6 小时前
在win10环境部署opengauss数据库(包含各种可能遇到的问题解决)
数据库
跳动的梦想家h6 小时前
黑马点评 秒杀下单出现的问题:服务器异常---java.lang.NullPointerException: null(已解决)
java·开发语言·redis
m0_748230216 小时前
mysql约束和高级sql
数据库·sql·mysql
刘艳兵的学习博客6 小时前
刘艳兵-DBA046-ASSM表空间的全表扫描范围由哪些因素综合确定?
数据库·sql·oracle·刘艳兵
2401_857636396 小时前
实验室管理技术革新:Spring Boot系统
数据库·spring boot·后端
生活很暖很治愈7 小时前
C51数字时钟/日历---LCD1602液晶显示屏
数据库·单片机·mongodb
YONG823_API7 小时前
1688商品数据采集API的测试对接步骤分享(提供免费测试key)
开发语言·数据库·爬虫·python·数据挖掘