redis常见使用场景

文章目录

redis常见使用场景

Redis 是一种高性能的内存数据库,广泛应用于各种场景中。以下是 Redis 的常见使用场景:

  1. 缓存:作为缓存层,将频繁访问的数据存储在内存中,以加速数据访问速度。Redis 提供了丰富的数据结构和缓存策略,可以用于实现各种灵活的缓存方案。
  2. 会话存储:将用户会话数据存储在 Redis 中,用于实现分布式会话管理,提高系统的可扩展性和容错性。
  3. 计数器:用于实现各种计数器功能,比如网站访问量统计、点赞数统计等。
  4. 消息队列:利用 Redis 的发布订阅功能或者列表数据结构,实现简单的消息队列,用于异步处理任务、事件驱动等场景。
  5. 分布式锁:利用 Redis 的原子性操作和过期时间特性,实现分布式锁,用于解决并发访问时的资源竞争问题。
  6. 地理位置应用:利用 Redis 的地理位置数据结构,实现地理位置相关的应用,比如附近的人功能、地理位置搜索等。
  7. 实时排行榜:利用有序集合数据结构,实现实时排行榜功能,用于排名、统计等应用场景。
  8. 缓存预热:在系统启动或者高峰期前,通过 Redis 预先加载数据,以提高系统的响应速度和稳定性。
  9. 分布式会议管理:用于实现分布式锁、分布式信号量等功能,用于分布式系统的协调和同步。
  10. 实时数据分析:通过 Redis 提供的数据结构和原子性操作,支持实时数据分析、统计等功能。
    总的来说,Redis 在缓存、会话存储、消息队列、分布式锁等方面具有广泛的应用场景,可以帮助构建高性能、可扩展的应用系统。然而在使用 Redis 时,需要考虑数据持久化、高可用性、安全性等方面的问题,以及合理设计和优化 Redis 的使用方式。

缓存

String类型

例如:热点数据缓存(例如报表、明星出轨),对象缓存、全页缓存、可以提升热点数据的访问数据。

数据共享分布式

String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享

例如:分布式Session

复制代码
<dependency> 
    <groupId>org.springframework.session</groupId> 
    <artifactId>spring-session-data-redis</artifactId> 
    </dependency>

全局ID

nt类型,incrby,利用原子性

incrby userid 1000

分库分表的场景,一次性拿一段

位统计

String类型的bitcount(1.6.6的bitmap数据结构介绍)

字符是以8位二进制存储的

setk1 a

setbit k1 6 1

setbit k1 7 0

get k1

/* 6 7 代表的a的二进制位的修改

a 对应的ASCII码是97,转换为二进制数据是01100001

b 对应的ASCII码是98,转换为二进制数据是01100010

因为bit非常节省空间(1 MB=8388608 bit),可以用来做大数据量的统计。

*/

例如:在线用户统计,留存用户统计

购物车

String 或hash。所有String可以做的hash都可以做

用户消息时间线timeline

list,双向链表,直接作为timeline就好了。插入有序

抽奖

自带一个随机获得值

spop myset

商品筛选

sdiffset1 set2

//获取交集(intersection )

sinter set1 set2

//获取并集

sunion set1 set2

分布式锁

复制代码
 String 类型setnx方法,只有不存在时才能添加成功,返回true  
public static boolean getLock(String key) {
    Long flag = jedis.setnx(key, "1");
    if (flag == 1) {
        jedis.expire(key, 10);
    }
    return flag == 1;
}
 
public static void releaseLock(String key) {
    jedis.del(key);
}

代码要执多个redis命令,不加锁的情况下如何保证原子性 --分布式锁

lua脚本:https://segmentfault.com/a/1190000009811453

Redis 中执行 Lua 脚本

Lua脚本功能为Redis开发和运维人员带来如下三个好处:

●Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令。

●Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令常驻在Redis内存中,实现复用的效果。

●Lua脚本可以将多条命令一次性打包,有效地减少网络开销。

限流

int类型,incr方法

以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false

redis实现计数器

int类型,increment()方法

例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库

使用场景: 一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等

复制代码
 /**
     * 利用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在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单,Redis 只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的 10 个用户--我们称之为"user_scores",

我们只需要像下面一样执行即可:

当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:

ZRANGE user_scores 0 10 WITHSCORES

Agora Games 就是一个很好的例子,用 Ruby 实现的,它的排行榜就是使用 Redis 来存储数据的,你可以在这里看到

消息队列

List提供了两个阻塞的弹出操作:blpop/brpop,可以设置超时时间

blpop:blpop key1 timeout 移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

brpop:brpop key1 timeout 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

上面的操作。其实就是java的阻塞队列。学习的东西越多。学习成本越低

● 队列:先进先除:rpush blpop,左头右尾,右边进入队列,左边出队列

● 栈:先进后出:rpush brpop

发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis 客户端可以订阅任意数量的频道。

客户端向频道中发布消息,多个订阅者可以同时收到

Reids 在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得 Redis 能作为一个很好的消息队列平台来使用。Redis 作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。

如果你快速的在 Google 中搜索"Redis queues",你马上就能找到大量的开源项目,这些项目的目的就是利用 Redis 创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用 Redis 作为 broker,你可以从这里去查看。

Redis 异步队列

答:一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有消息的时候, 要适当

sleep 一会再重试。

如果对方追问可不可以不用 sleep 呢?

list 还有个指令叫 blpop,在没有消息的时候,它会阻塞住直到消息到来。如果对方追问能不能生产一

次消费多次呢? 使用 pub/sub 主题订阅者模式, 可以实现1:N 的消息队列。

如果对方追问 pub/sub 有什么缺点?

在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 RabbitMQ 等。

如果对方追问 redis 如何实现延时队列?

我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话, 怎么问的这么详细。但是你很克制,然后神态自若的回答道:使用 sortedset,拿时间戳作为score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。到这里, 面试官暗地里已经对你竖起了大拇指。但是他不知道的是此刻你却竖起了中指, 在椅子背后。

redis 如何实现延时队列

redis过期监听

redis的zset

redisson

redis延迟队列 的原理

基于上述原理,Redis延迟队列的工作流程通常如下:

● 将待执行的任务或消息以有序集合的形式存储在Redis中,其中成员为消息内容,分数为消息的执行时间。

● 使用定时任务轮询机制,定期检查有序集合中是否有到期的任务。可以通过Redis的定时任务调度器或外部定时任务程序实现。

● 当检测到有任务的执行时间已到达时,从有序集合中取出该任务,并执行相应的处理逻辑。

通过以上流程,可以实现延迟处理任务或消息的功能。Redis延迟队列通常具有较高的性能和可靠性,并且易于实现和部署。然而,需要注意的是,Redis延迟队列通常只能提供基本的延迟功能,如果需要更复杂的消息队列功能(如消息重试、消息持久化等),可能需要结合其他消息中间件来实现。

Redis延迟队列是一种常用的消息队列模式,用于延迟处理任务或消息。其原理通常基于两个主要组件:有序集合(Sorted Set)和定时任务轮询。

  1. 有序集合(Sorted Set):
    ○ Redis中的有序集合是一种数据结构,其中的每个成员都关联了一个分数(score)。有序集合的特性之一是按照分数从小到大排序。在延迟队列中,可以将消息或任务的执行时间作为分数,将消息内容作为成员存储在有序集合中。
  2. 定时任务轮询:
    ○ 定时任务轮询是一种机制,用于定期检查有序集合中是否有到期的任务或消息。通过定期轮询有序集合,可以检查是否有任务的执行时间已到达,从而将其取出并执行。
    基于上述原理,Redis延迟队列的工作流程通常如下:
    ● 将待执行的任务或消息以有序集合的形式存储在Redis中,其中成员为消息内容,分数为消息的执行时间。
    ● 使用定时任务轮询机制,定期检查有序集合中是否有到期的任务。可以通过Redis的定时任务调度器或外部定时任务程序实现。
    ● 当检测到有任务的执行时间已到达时,从有序集合中取出该任务,并执行相应的处理逻辑。
    通过以上流程,可以实现延迟处理任务或消息的功能。Redis延迟队列通常具有较高的性能和可靠性,并且易于实现和部署。然而,需要注意的是,Redis延迟队列通常只能提供基本的延迟功能,如果需要更复杂的消息队列功能(如消息重试、消息持久化等),可能需要结合其他消息中间件来实现。

redis生产常用的场景

分布式锁

限流

计数器

我们项目中有用到,主要用了3个场景:

1.缓存相关的场景,我们是做在线教育的,内容模板会有很多课程相关,这些数据在DB单表有5.600W;如果走mysql查询会很比较慢,用户体验感比较差,并发也上不去。所以我们做了些接口缓存、课程内容的对象缓存。提升了性能的同时,还解决了本地缓存不一致问题。

2.同时,我们由于它是分布式的,并且可以设置过期时间,也会用来保存用户token。因为token也是有过期时间的,用Redis来保存刚好满足。

3.我们还用它去基于日期+incr自增指令实现了一个分布式ID。因为我们的课程ID比较大,需要分库分表,数据库自增满足不了我们需求。

相关推荐
Lion Long3 小时前
CodeBuddy 中国版 Cursor 实战:Redis+MySQL双引擎驱动〈王者荣耀〉战区排行榜
数据库·redis·mysql·缓存·腾讯云·codebuddy首席试玩官·codebuddy
柯南二号10 小时前
MacOS 用brew 安装、配置、启动Redis
redis
星星点点洲13 小时前
【Redis】RedLock实现原理
redis·缓存
我来整一篇13 小时前
用Redis的List实现消息队列
数据库·redis·list
加什么瓦13 小时前
Redis——数据结构
数据库·redis·缓存
lybugproducer15 小时前
浅谈 Redis 数据类型
java·数据库·redis·后端·链表·缓存
青山是哪个青山15 小时前
Redis 常见数据类型
数据库·redis·bootstrap
杨不易呀15 小时前
Java面试全记录:Spring Cloud+Kafka+Redis实战解析
redis·spring cloud·微服务·kafka·高并发·java面试·面试技巧
郭逍遥15 小时前
[工具]B站缓存工具箱 (By 郭逍遥)
windows·python·缓存·工具