【Redis监听过期key不及时问题,适用于高并发及其海量数据的场景】

本文探讨了在高并发及海量数据环境下Redis监听过期Key存在的问题,并提出了通过分离缓存与监听数据来提高监听效率的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前沿

redis监听过期key的教程网上都有文章,但大多数都是针对于一般的处理,如果遇上高并发及其海量数据的数据的情况下会有一些问题。

本文会分析一般的监听过期key的处理在海量数据情况下出现的问题?怎么去解决,本文的思路和步骤都很清晰哦~

抛出问题:redis监听过期key不及时

举个例子:

现在时间09:00, 有个key设置一分钟后过期,也就是我在09:01的时候redis会告知我这个key过期了。

但是如果redis存储了海量数据,可能会导致这个的不及时通知,意思就是可能09:02才通知你

出现这种情况通知不及时很可能影响到业务操作,所以我们需要解决这个问题

分析问题:为什么会出现通知不及时的情况?

我们首先得了解redis底层是如何知道key过期的,它有三种方案:

在这里插入图片描述

redis默认采用的是定期删除+惰性删除

定期删除的过程:

每隔一段时间,Redis 会分别去各个库随机拿 20 个非永久 Key,判断它们是否过期,过期则删除,如果这一次拿的 key 中有超过 1/4 的数据过期,则再执行一遍过程 1,直到过期数据不超过当次拿出来的 20 条记录的 1/4。

(可以通过配置 redis.conf 中的 hz 修改 Redis 执行定期删除的频率,默认 hz=10,即每 100ms 执行一次,1/4 与每次拿的数量 20 暂时未找到配置项);

如果当前数据库没有非永久 key,则跳过当前数据库;

如果 key 已过期,但没有被定期删除,由于惰性删除策略,在下次请求获取该数据时会将该数据删除;

平时我们都是把所有key都存在一个库里,它去随机获取的时候不一定能拿到过期key,所以就可能造成key过期没有及时通知

解决方案:

1.将缓存数据与监听数据分离,即把不同功能类型的数据分库存放(Redis 默认有 16 个库,库的数量可在 redis.conf 配置修改),例如把缓存数据存在 database0,把监听数据存在 database1;

  1. 让进行监听的库中 key 尽量少,如果不同业务的监听超时时间差异较大,则考虑将不同业务的超时监听数据存放到不同的数据库;

存放不同的库之后意味着执行命令需要动态切换库,公众号回复 redis多库组件 就能获得动态切库组件了

在这里插入图片描述

<think>我们正在讨论Redis的实际应用场景和作用。根据引用内容,Redis是一个基于内存的高性能键值数据,支持多种数据结构,适用于需要高性能读写和较小数据量的场景。由于Redis使用内存存储,其读写速度远快于磁盘数据,但受限于内存大小,适合存储海量数据。以下是一些Redis的实际应用场景及作用举例:1.**缓存**:最常见的应用场景,将频繁访问的数据存储在Redis中,减轻后端数据压力。例如,用户信息、商品信息等热点数据可以缓存在Redis中,查询时先从Redis获取,若存在再查数据并设置到缓存中[^1]。2.**排行榜/计数器**:利用Redis的有序集合(ZSET)可以方便地实现排行榜功能。例如,游戏中的玩家积分排行榜、视频播放量排行榜等。每次更新分数时,使用`ZINCRBY`命令,查询时使用`ZRANGE`命令获取排名[^2]。3.**消息队列**:使用Redis的列表(List)或流(Stream)可以实现简单的消息队列。生产者使用`LPUSH`将消息推入列表,消费者使用`RPOP`或`BRPOP`从另一端取出消息。这种方式适用于异步任务处理、解耦系统组件[^2]。4.**会话存储**:在Web应用中,用户登录后的会话信息(Session)通常需要频繁读取。将会话数据存储在Redis中,可以快速读取,并支持分布式共享(多个Web服务器访问同一个Redis实例)[^1]。5.**实时系统**:如实时监控、实时计数。例如,网站实时在线人数统计、每分钟的请求量统计等。利用Redis的原子操作(如`INCR`)和过期时间(如`EXPIRE`)可以轻松实现[^1]。6.**好友关系/社交网络**:使用集合(Set)存储用户的好友列表、粉丝列表等。集合操作(如并集、交集)可以快速计算共同好友、可能认识的人等[^2]。7.**限速器**:限制用户操作频率,例如短信验证码发送频率(同一手机号1分钟内只能发送1次)。使用`INCR`和`EXPIRE`组合实现:每次操作前检查计数是否超过阈值,并设置过期时间[^2]。8.**发布/订阅**:Redis提供发布订阅模式,允许多个订阅者监听频道,发布者向频道发布消息。适用于即时通讯、消息通知等场景[^2]。以下是具体示例:-**场景1:缓存用户信息**用户访问个人主页时,后端先尝试从Redis中读取用户信息(key如`user:123`)。若存在,则从MySQL中查询并存入Redis(设置过期时间)。```pythonimportredisr=redis.Redis()defget_user(user_id):key=f"user:{user_id}"user_data=r.get(key)ifuser_data:returnuser_data#假设已反序列化else:user_data=db_query_user(user_id)#模拟数据查询r.setex(key,3600,user_data)#缓存1小时returnuser_data```-**场景2:实现排行榜**游戏结束后更新玩家得分并获取前10名:```pythondefupdate_score(player_id,score):r.zincrby("game_leaderboard",score,player_id)defget_top10():returnr.zrevrange("game_leaderboard",0,9,withscores=True)```**注意**:在使用Redis时需考虑持久化策略(RDB快照、AOF日志)防止数据丢失,以及内存淘汰策略(如LRU)管理内存空间[^1]。§§相关问题§§1.Redis在分布式系统中如何保证数据一致性?2.Redis支持的数据结构及其适用场景?3.Redis和Memcached的区别是什么?</think> ### Redis的实际应用场景与作用详解 Redis是一个基于内存的键值数据,以其高性能和多样化数据结构著称。以下结合引用内容,详细说明其核心作用和应用场景: --- #### 一、核心作用 1. **内存存储加速** 数据存储在内存中(持久化到磁盘做备份),读写速度达微秒级,比磁盘数据快100倍以上[^1]。 2. **丰富数据结构支持** 支持5种数据结构: - `String`:字符串/数字 - `List``:有序列表 - `Set`:无序集合 - `ZSet`:有序集合(带分值) - `Hash`:键值对字典[^2] 3. **单线程原子操作** 避免多线程竞争,保证操作原子性(如计数器增减会出错)[^1]。 --- #### 二、典型应用场景与代码示例 ##### 1. 实时排行榜(ZSet) ```python import redis r = redis.Redis() # 更新用户积分(自动排序) r.zadd("game_rank", {"userA": 1500, "userB": 2300}) # 获取TOP3 top3 = r.zrevrange("game_rank", 0, 2, withscores=True) # 返回: [(b'userB', 2300.0), (b'userA', 1500.0)][^2] ``` **适用场景**:游戏积分榜、电商销量排名、热搜榜单。 --- ##### 2. 消息队列(List) ```python # 生产者推送消息 r.lpush("order_queue", "{'order_id': 1001}") r.lpush("order_queue", "{'order_id': 1002}") # 消费者获取消息 order_data = r.rpop("order_queue") # 返回: b"{'order_id': 1001}"[^2] ``` **优势**:解耦系统组件,应对秒杀等高并发场景。 --- ##### 3. 页面缓存(String) ```python # 缓存首页HTML(设置30分钟过期) r.setex("home_page", 1800, "<html>...首页内容...</html>") # 读取缓存 if cached := r.get("home_page"): return cached # 命中缓存直接返回[^1] else: data = generate_page() # 未命中则生成新页面 r.setex("home_page", 1800, data) ``` **价值**:降低数据压力,加速页面加载。 --- ##### 4. 分布式锁(String + Lua) ```python # 获取锁(NX: 存在时才设置) lock_acquired = r.set("order_lock", 1, nx=True, ex=10) if lock_acquired: try: process_order() # 执行业务逻辑 finally: r.delete("order_lock") # 释放锁 ``` **应用**:防止重复下单、资源竞争[^2]。 --- ##### 5. UV统计(HyperLogLog) ```python # 统计日活用户(百万级数据误差仅0.81%) r.pfadd("2024-07-14_uv", "user123", "user456") uv_count = r.pfcount("2024-07-14_uv") # 返回估算值[^2] ``` **优势**:用12KB内存统计十亿级数据。 --- #### 三、技术限制 - **内存限制**:数据量受物理内存约束,适合海量数据存储 - **持久化风险**:RDB快照和AOF日志仍有数据丢失可能 - **适用场景**:适合高频读写但数据规模可控的场景(如缓存、计数器)[^1][^2] --- #### 四、实际案例 1. **Twitter**:用Redis存储用户时间线 2. **GitHub**:用Redis存储仓星标数 3. **美团**:日均万亿次调用,支撑外卖订单分发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值