消失的Redis Key

本文探讨了在使用Redis限制用户操作频率或确保幂等性时,如何利用setNX实现简单互斥逻辑。关键在于掌握Key何时存在及何时消失。直接删除Key是可见的,而Key过期消失可能造成问题,需要根据业务调整过期时间。另外,Redis内存满触发淘汰机制或连接池配置不当也可能导致Key意外消失,对此需关注Redis监控、连接池参数和内存管理。

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

很多场景下我们需要限制用户的操作频率,或者保证一段代码的幂等性。例如在前者的场景下,若用户在1秒内对接口发起同样的请求,即只放过第一个请求,而在这一秒内的后续请求视为无效请求,系统直接给用户提示“您的操作过快,请稍后再试”。后者场景则多见于写操作接口或具有写操作逻辑的MQ消费中。

虽然我们能够使用限流器或更复杂的控制逻辑,但在大多数简单场景下,可以利用redis的setNX配合一个合适的key过期时间即可满足上述需求。

为什么呢?简单来说,上述场景就是一个简单的互斥逻辑,或者说是一个简单的上锁逻辑。redis其单线程的特性,使得请求到达redis后自然成为线性有序的,消除了并发;由因setNX的语义为set if not exist,即key不存在则set操作成功,反之则失败,是一个现成的互斥操作。

下面就来看下伪代码:

public void doSomething(long orderId) {
   
  // 利用setNX尝试set一个key,并设置过期时间为1秒
  // 若set操作失败,则表示该key在1秒内已经存在于redis
  if(!jedis.setNX("order_key_" + orderId, "test", 1)) {
   
    throw new DemoServiceException("操作过快,稍后重试");
  }
  // doSomething ... 
}

简单来说,我们就是在利用redis中是否存在某个key,来决定后续的操作。那么,这个key什么时候有,什么时候没,是需要注意的关键。

注:利用setNX在简单的互斥场景下是可用的,但完全用它做分布式锁,会存在很多弊端,然而这个不是本次讨论的重点。

key什么时候有?

这个很简单,请求来了,触发了setNX,若此时redis中没有该key,则新增该key。

key什么时候没有?

  1. 肉眼可见的消失

    所谓肉眼可见,就是代码里明确写了,我要删了这个key。这个需要注意的是什么时候删是能符合需求的,如果删的时机不对,可能会带来一些惊喜,但好在,这个动作是写在代码里的,扒一扒代码,梳理下逻辑,是比较容易修正的。

  2. 一眼看不出来的消失

    相对于上面的直接调用删除,key的过期时间到了,自己消失,会相对隐蔽一些,往往有时候不太好拿捏key要定多久消失合适,可能要考虑要限制多长时间,也要考虑后续代码的执行时长。过期时间太长,影响后续请求;太短,兜不住。需要多测多观察,适度调整。

  3. 肉眼不可见的消失

    这就麻烦了,没写代码,但是自己没了,很头大。发生这种事,一般会

### Redis Key 生存时间和淘汰机制 #### 设置键的过期时间 Redis 提供多种方式来设定键的有效期限。通过 `EXPIRE` 或者在创建键的时候使用带有有效时间参数的命令,可以为键设置生存时间。例如: ```python import redis r = redis.Redis(host='localhost', port=6379, db=0) # Set a key with an expiration time (in seconds) r.setex('my_key', 60, 'value') # Sets my_key to expire after 60 seconds. ``` 当一个键被设置了过期时间之后,一旦到达这个时间点,该键就会自动消失[^1]。 #### 淘汰策略 随着存储的数据量增加,可能会遇到内存不足的情况。此时就需要采用一定的淘汰政策来释放空间。Redis 支持几种不同的淘汰策略,可以通过配置文件中的 `maxmemory-policy` 参数来进行选择。常见的有如下几种: - **volatile-lru**: 使用LRU算法移除具有有效期且最近最少使用的键。 - **allkeys-lru**: 不考虑是否有有效期,直接按照 LRU 移除非活跃最久未使用的键。 - **volatile-random**: 随机删除即将到期的键。 - **allkeys-random**: 完全随机地删除任意键。 - **volatile-ttl**: 删除那些剩余存活时间较短的键。 - **no-eviction**(默认): 当达到最大内存限制时不主动驱逐任何数据项;如果尝试写入新数据,则返回错误给客户端[^2]。 这些策略允许管理员根据实际应用场景灵活调整如何管理有限资源下的缓存命中率和服务质量。 #### 解决缓存问题的方法 对于可能出现的各种缓存难题,比如冷启动、雪崩效应等问题,有一些通用的技术手段可以帮助缓解这些问题的影响: - 实施合理的预热计划,在应用上线前预先加载一部分热点数据到缓存里去; - 对于重要业务逻辑所依赖的关键路径上的查询结果实施持久化保存,并定期更新其副本; - 利用分布式锁控制并发读取同一份缓存内容的操作次数,防止瞬间大量请求涌入造成服务器压力过大; - 设定合适的超时重试机制应对临时性的网络波动或节点故障带来的影响; - 结合异步任务队列处理耗时较长的任务,减少对实时响应的要求。 此外,还可以利用 Lua 脚本来批量操作多个 keys ,尽管这并不适用于跨 Keys 的原子性事务[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值