Redis常用应用场景

概述

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

那么Redis可以用来干什么?.

缓存

这是Redis应用最广泛地方,基本所有的Web应用都会使用Redis作为缓存,来降低数据源压力,提高响应速度。

计数器

Redis天然支持计数功能,而且计数性能非常好,可以用来记录浏览量、点赞量等等。

 /**     * 判断同一个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提供了列表和有序集合数据结构,合理地使用这些数据结构可以很方便地构建各种排行榜系统。

//当前日期字符串        String today = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd");        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();        ZSetOperations operation = redisTemplate.opsForZSet();        //添加日榜数据  incrementScore方法当对应的key不存在时,会自动创建对应key的集合,已存在则会增加对应value的score        operation.incrementScore("2022-06-13:dayRank","lyx",30);        operation.incrementScore("2022-06-13:dayRank","lisi",5);        operation.incrementScore("2022-06-13:dayRank","zhangsan",10);

社交网络

赞/踩、粉丝、共同好友/喜好、推送、下拉刷新。

消息队列

Redis提供了发布订阅功能和阻塞队列的功能,可以满足一般消息队列功能。

分布式锁

分布式环境下,利用Redis实现分布式锁,也是Redis常见的应用。

@RestControllerpublic class IndexController8 {
    public static final String REDIS_LOCK = "good_lock";
    @Autowired    StringRedisTemplate template;
    @Autowired    Redisson redisson;
    @RequestMapping("/buy8")    public String index(){
        RLock lock = redisson.getLock(REDIS_LOCK);        lock.lock();
        // 每个人进来先要进行加锁,key值为"good_lock"        String value = UUID.randomUUID().toString().replace("-","");        try{            String result = template.opsForValue().get("goods:001");            int total = result == null ? 0 : Integer.parseInt(result);            if (total > 0) {                // 如果在此处需要调用其他微服务,处理时间较长。。。                int realTotal = total - 1;                template.opsForValue().set("goods:001", String.valueOf(realTotal));                System.out.println("购买商品成功,库存还剩:" + realTotal + "件, 服务端口为8001");                return "购买商品成功,库存还剩:" + realTotal + "件, 服务端口为8001";            } else {                System.out.println("购买商品失败,服务端口为8001");            }            return "购买商品失败,服务端口为8001";        }finally {            if(lock.isLocked() && lock.isHeldByCurrentThread()){                lock.unlock();            }        }    }}

Redis的应用一般会结合项目去问,以一个电商项目的用户服务为例:

  • Token存储:用户登录成功之后,使用Redis存储Token
  • 登录失败次数计数:使用Redis计数,登录失败超过一定次数,锁定账号
  • 地址缓存:对省市区数据的缓存
  • 分布式锁:分布式环境下登录、注册等操作加分布式锁