Redis官方教程 Expire超时

Redis官方教程 Expire超时,第1张

EXPIRE key second

设置超时 key 。超时过期后,key将自动删除。在Redis术语中,通常认为具有超时的key是 不稳定的 。

只有删除或覆盖key内容的命令才能清除超时,包括 DEL , SET , GETSET 和所有 STORE 命令。这意味着 改变 存储在key中的值而不用新key替换它的所有 *** 作将使超时保持不变。举例来说,增加一键的值 INCR ,往列表推新值的,包括 LPUSH ,或改变了哈希的字段值 HSET ,都不会改变超时。

也可以清除超时,使用 PERSIST 命令将key重新转换为持久key。

如果使用 RENAME 重命名key,则相关的生存时间将转移到新key名称。

如果一个key被 RENAME 覆盖,比如,已经存在key Key_A ,被如下命令所覆盖, RENAME Key_B Key_A ,新key Key_A 将继承所有的 Key_B 的属性,与原始 Key_A 否有超时没有关系。

请注意,使用非正数的超时时间调用 EXPIRE / PEXPIRE 或 使用一个过去时间调用 EXPIREAT / PEXPIREAT ,将导致键被 删除 而不是过期(因此,发出的 键事件 将是 del ,而不是 expired )。

可以使用已经设置超时的key作为参数调用 EXPIRE 。在这种情况下,key的生存时间将 更新 为新值。有许多有用的应用程序,下面的 导航会话 模式部分中记录了一个示例 。

在之前的Redis 213版本中 ,使用命令更改key来使用超时设置更改key,具有完全删除key的效果。由于复制层中的限制现在已得到修复,因此需要使用此语义。

EXPIRE 将返回0并且不会更改具有超时设置的key的超时。

整数回复 ,具体为:

假如你有一个web服务,你需要记录用户最近浏览的N个页面,每个相邻页面的浏览时间不超过60s。

你可以用redis轻松实现,每次用户打开一个页面,执行如下命令:

如果用户60s没有 *** 作,页面就会被删除,只有60s以内的页面会被记录。

通常,创建Redis key时没有相关的过期时间。key只会永远存在,除非用户以明确的方式将其 删除 ,例如使用 DEL 命令。

EXPIRE 家族命令能够给key设置超时时间,但是会使用一些额外的内存成本。当key设置了过期时,Redis将确保在指定的时间过后删除key。

可以使用 EXPIRE 和 PERSIST 命令(或其他严格相关的命令)更新或完全删除key生存时间。

在Redis 24中,到期可能不精确,误差可能在0到1秒之间。

从Redis 26开始,到期误差从0到1毫秒。

Key到期信息存储为绝对Unix时间戳(在Redis 26或更高版本的情况下以毫秒为单位)。这意味着即使Redis实例未处于活动状态,时间也在流动。

为了使到期效果良好,计算机时间必须稳定。如果您从两台计时器中移动RDB文件并在其时钟中使用大型desync,则可能会发生有趣的事情(例如加载时加载的所有键都将在加载时过期)。

即使运行实例也会检查计算机时钟,例如,如果您设置的key的生存时间为1000秒,然后将计算机时间设置为当前时间向后2000秒,key将立即过期,而不是持续1000秒。

Redis key以两种方式过期:被动方式和主动方式。

当某个客户端尝试访问key时,如果发现key超时,key被动过期。

当然这还不够,因为有过期的key永远不会被再次访问。这些key无论如何都应该过期,所以周期性地Redis会在具有过期设置的key中随机测试几个key。已经过期的所有key都将从key空间中删除。

具体来说,这就是Redis每秒做10次的事情:

这是一个简单的概率算法,基本上假设我们的样本代表整个key空间,我们继续到期,直到可能过期的key百分比低于25%

这意味着在任何给定时刻,使用内存的已经过期的最大key数量最大等于每秒最大写入 *** 作量除以4。

为了在不牺牲一致性的情况下获得正确的行为,当key到期时,在AOF文件中合成 DEL *** 作并通知所有副本节点。这样,到期过程集中在主实例中,并且不存在一致性错误。

但是,连接到主服务器的副本节点不会单独地使key过期,(但会等待来自主服务器的 DEL ),但它们仍将采用数据集中存在的过期的完整状态,因此当副本被选为主服务器时它将能够独立地使密钥到期,充分充当主人。

Redis 中数据过期策略采用定期删除+惰性删除策略。定期删除策略:Redis 启用一个定时器定时监视所有的 key,判断key是否过期,过期的话就删除。这种策略可以保证过期的 key 最终都会被删除,但是也存在严重的缺点:每次都遍历内存中所有的数据,非常消耗 CPU 资源,并且当 key 已过期,但是定时器还处于未唤起状态,这段时间内 key 仍然可以用。

惰性删除策略:在获取 key 时,先判断 key 是否过期,如果过期则删除。这种方式存在一个缺点:如果这个 key 一直未被使用,那么它一直在内存中,其实它已经过期了,会浪费大量的空间。

2、定期删除+惰性删除策略是如何工作的?

这两种策略天然的互补,结合起来之后,定时删除策略就发生了一些改变,不在是每次扫描全部的 key 了,而是随机抽取一部分 key 进行检查,这样就降低了对 CPU 资源的损耗,惰性删除策略互补了为检查到的key,基本上满足了所有要求。但是有时候就是那么的巧,既没有被定时器抽取到,又没有被使用,这些数据又如何从内存中消失?没关系,还有内存淘汰机制,当内存不够用时,内存淘汰机制就会上场。Redis 内存淘汰机制有以下几种策略:

noeviction:当内存不足以容纳新写入数据时,新写入 *** 作会报错。(Redis 默认策略)

allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。(推荐使用)

allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。

volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。

volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。修改内存淘汰机制只需要在 redisconf 配置文件中配置 maxmemory-policy 参数即可。

redis 过期策略是:定期删除+惰性删除。

所谓定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。

假设redis里放了10w个key,都设置了过期时间,每隔几百毫秒,就检查10w个key,那redis基本上就死了,cpu负载会很高的,消耗在检查过期key上了。实际上redis是每隔100ms随机抽取一些key来检查和删除的。

Redis常用内存优化:

Redis内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,不过大多数情况下这个不会成为Redis的性能瓶颈,不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销。

即在系统启动时先分配一个从1~n那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下。

也能一定程度上节省内存并且提高性能,这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,可以根据自己的需要进行修改,修改后重新编译就可以了。

以上内容参考 百度百科—Redis

        11 锁需要具备唯一性

        12 锁需要有超时时间,防止死锁

        13 锁的创建和设置锁超时时间需要具备原子性

        14 锁的超时的续期问题

        15 B的锁被A给释放了的问题

        16 锁的可重入问题

        17 集群下分布式锁的问题

        问题讲解:

        首先分布式锁要解决的问题就是分布式环境下同一资源被多个进程进行访问和 *** 作的问题,既然是同一资源,那么肯定要考虑数据安全问题其实和单进程下加锁解锁的原理是一样的,单进程下需要考虑多线程对同一变量进行访问和修改问题,为了保证同一变量不被多个线程同时访问,按照顺序对变量进行修改,就要在访问变量时进行加锁,这个加锁可以是重量级锁,也可以是基于cas的乐观锁

        解决方案:

        使用redis命令setnx(set if not exist),即只能被一个客户端占坑,如果redis实例存在唯一键(key),如果再想在该键(key)上设置值,就会被拒绝

        问题讲解:

        redis释放锁需要客户端的 *** 作,如果此时客户端突然挂了,就没有释放锁的 *** 作了,也意味着其他客户端想要重新加锁,却加不了的问题

        解决方案:

        所以,为了避免客户端挂掉或者说是客户端不能正常释放锁的问题,需要在加锁的同时,给锁加上超时时间

        即,加锁和给锁加上超时时间的 *** 作如下 *** 作:

>setnx lockkey true    #加锁 *** 作

ok

>expire lockkey 5    #给锁加上超时时间

do something critical

>del lockkey    #释放锁

(integer) 1

        问题讲解:

        通过23加锁和超时时间的设置可以看到,setnx和expire需要两个命令来完成 *** 作,也就是需要两次RTT *** 作,如果在setnx和expire两次命令之间,客户端突然挂掉,这时又无法释放锁,且又回到了死锁的问题

        解决方案:

        使用set扩展命令

        如下:

>set lockkey true ex 5 nx   #加锁,过期时间5s

ok

do something critical

>del lockkey

        以上的set lockkey true ex 5 nx命令可以一次性完成setnx和expire两个 *** 作,也就是解决了原子性问题

        问题讲解:

        redis分布式锁过期,而业务逻辑没执行完的场景,不过,这里换一种思路想问题,把redis锁的过期时间再弄长点不就解决了吗?那还是有问题,我们可以在加锁的时候,手动调长redis锁的过期时间,可这个时间多长合适?业务逻辑的执行时间是不可控的,调的过长又会影响 *** 作性能。

        解决方案:

        使用redis客户端redisson,redisson很好的解决了redis在分布式环境下的一些棘手问题,它的宗旨就是让使用者减少对Redis的关注,将更多精力用在处理业务逻辑上。redisson对分布式锁做了很好封装,只需调用API即可。RLock lock = redissonClientgetLock("stockLock");

        redisson在加锁成功后,会注册一个定时任务监听这个锁,每隔10秒就去查看这个锁,如果还持有锁,就对过期时间进行续期。默认过期时间30秒。这个机制也被叫做:“看门狗”

        问题讲解:

        A、B两个线程来尝试给key myLock加锁,A线程先拿到锁(假如锁3秒后过期),B线程就在等待尝试获取锁,到这一点毛病没有。那如果此时业务逻辑比较耗时,执行时间已经超过redis锁过期时间,这时A线程的锁自动释放(删除key),B线程检测到myLock这个key不存在,执行 SETNX命令也拿到了锁。但是,此时A线程执行完业务逻辑之后,还是会去释放锁(删除key),这就导致B线程的锁被A线程给释放了。

      解决方案:

      一般我们在每个线程加锁时要带上自己独有的value值来标识,只释放指定value的key,否则就会出现释放锁混乱的场景一般我们可以设置value为业务前缀_当前线程ID或者uuid,只有当前value相同的才可以释放锁

        问题讲解:

        上面我们讲了,为了保证锁具有唯一性,需要使用setnx,后来为了与超时时间一起设置,我们选用了set命令。 在我们想要在加锁期间,拥有锁的客户端想要再次获得锁,也就是锁重入

        解决方案:

       给锁设置hash结构的加锁次数,每次加锁就+1

        问题讲解:

        这一问题是在redis集群方案时会出现的事实上,现在为了保证redis的高可用和访问性能,都会设置redis的主节点和从节点,主节点负责写 *** 作,从节点负责读 *** 作,也就意味着,我们所有的锁都要写在主redis服务器实例中,如果主redis服务器宕机,资源释放(在没有加持久化时候,如果加了持久化,这一问题会更加复杂),此时redis主节点的数据并没有复制到从服务器,此时,其他客户端就会趁机获取锁,而之前拥有锁的客户端可能还在对资源进行 *** 作,此时又会出现多客户端对同一资源进行访问和 *** 作的问题

        解决方案:

        使用redlock,原理与zookeeper分布式锁原理相同多台主机超过半数设置成功则获取锁成功,要注意下主机个数必须是奇数,不过这有效率问题

以上就是关于Redis官方教程 Expire超时全部的内容,包括:Redis官方教程 Expire超时、Redis过期淘汰策略实现方法、redis过期策略有哪些等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9618609.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存