
redis对存储值的过期处理实际上是针对该值的键(key)处理的,即时间的设置也是设置key的有效时间。Expires字典保存了所有键的过期时间,Expires也被称为过期字段。
四种处理策略
EXPIRE 将key的生存时间设置为ttl秒
PEXPIRE 将key的生成时间设置为ttl毫秒
EXPIREAT 将key的过期时间设置为timestamp所代表的的秒数的时间戳
PEXPIREAT 将key的过期时间设置为timestamp所代表的的毫秒数的时间戳
其实以上几种处理方式都是根据PEXPIREAT来实现的,设置生存时间的时候是redis内部计算好时间之后在内存处理的,最终的处理都会转向PEXPIREAT。
1、2两种方式是设置一个过期的时间段,就是咱们处理验证码最常用的策略,设置三分钟或五分钟后失效,把分钟数转换成秒或毫秒存储到redis中。
3、4两种方式是指定一个过期的时间 ,比如优惠券的过期时间是某年某月某日,只是单位不一样。
符
1 SET key value
2 GET key
3 KEYS
4 DEL key
5 EXISTS key
6 EXPIRE key seconds
7 PERSIST key
8 TTL key
9 SELECT index
10 FLUSHDB
11 FLUSHALL
12 MOVE key dbindex
13 RENAME key newkey
14 RANDOMKEY
15 RENAMENX key newkey
16 TYPE key
17 EXPIREAT key timestamp
18 SETNX key value
19 SETEX key seconds value
20 MSET key value [key value ]
1 技术背景
2 设计思想
3 总结
常见问题
附录
从 Redis 280+ 开始Redis提供了 Keyspace Notifications [^1]特性; 这一特性使得客户端可以通过发布/订阅来接收redis影响数据集相关事件, 例如:
由于该特性会新增CPU消耗, keyspance events notifications 是默认关闭的, 可通过修改redisconf或 CONFIG SET 配置 notify-keyspace-events 来开启,
配置中至少需要出现 K / E , 否则将不会接收到任何事件, 如果配置为 KEA 则会接收到任何可能的事件。
注意: Redis的发布/订阅阅后即焚是不支持持久化的, 故如果客户端断开重连则在这期间的消息将丢失!
订阅事件
过期一个KEY
收到通知
网上实际有很多其他方案, 在 spring-data-redis 中已提供了对上面特性的实现只是很少有人介绍到, 我推荐使用以下方案, 则每当有KEY失效则以下listener会收到消息:
实现原理是在 orgspringframeworkdataredislistenerKeyExpirationEventMessageListener 中订阅事件 __keyevent@__:expired 如下:
有多种方式去实现分布式锁, 关于使用Redis做分布式锁我推荐大家可以看看附录[^2]官方的文章, 里面详细介绍了官方推荐的正确的实现方式。
在 Spring Integration [^3]中从40开始就提供了一种基于redis的分布式锁实现 RedisLockRegistry , 可用过用 obtain 方法直接获取到 javautilconcurrentlocksLock 也很简单:
根据实际的需求选择使用 tryLock / lock 来实现我们的具体场景, java中对该对象定义如下:
定义任务管理服务, 用于受理其他服务程序通过RPC/DB/MQ等任务创建指令, 该服务根据任务等元数据(META DATA)判断任务是需要立即执行或是延时执行。
根据不同等任务数据调用不用等任务具体实方法去执行任务, 例如执行一条SQL、执行一个RPC调用等, 执行成功则任务调度完成, 执行不成功则根据任务元数据(META DATA)来控制任务执行情况, 例如可约定以下数据:
当任务执行失败且还满足可执行条件, 则根据配置 RETRY_INTERVAL 将任务数据放入 Redis 并设置 TTL = RETRY_INTERVAL , 则任务则会在 TTL 之后重新被执行。
根据前面技术背景中提到当 Redis 现有当特性, 以及前面我们根据KEY的TTL来控制任务的执行, 则收到KEY过期事件即代表任务达到执行时间了; 但在分布式环境中, 多个JVM会同时监听到KEY过期, 为了防止任务重复执行, 所以在可执行任务前需要再结合分布式锁获取到锁的JVM方可执行任务, 否则直接忽略该事件, 因为其他JVM已经执行了该任务。
本文描述的方案主要结合了 Redis 两大特性:
来实现来分布式任务调度, 都基于Redis来实现, 较大程度发挥了其自身优势, 相较于 quartz [^4]更加轻量级。
[1] Redis Keyspace Notifications
>
redis数据淘汰原理
redis过期数据删除策略
redis server事件模型
redis cluster mget 引发的讨论
redis 3x windows 集群搭建
redis 命令执行过程
redis string底层数据结构
redis list底层数据结构
redis hash底层数据结构
redis set底层数据结构
redis zset底层数据结构
redis 客户端管理
redis 主从同步-slave端
redis 主从同步-master端
redis 主从超时检测
redis aof持久化
redis rdb持久化
redis 数据恢复过程
redis TTL实现原理
redis cluster集群建立
redis cluster集群选主
这篇文章的目的是为了描述redis server在处理client命令的执行过程,大概包括流程图、源码、以及redis的命令格式说明,redis的通信协议参考自redis的 官网 。
整个redis的server端命令执行过程就如下面这个流程图:
nread = read(fd, c->querybuf+qblen, readlen);负责读取命令数,通过processInputBuffer进行下一步处理。
核心在于processInlineBuffer处理内联命令,processMultibulkBuffer处理批量命令包括get/set等,核心的processCommand用于执行命令。
执行命令的过程其实主要是寻找命令对应的执行函数,通过lookupCommand查找对应的执行命令,通过call执行命令。
负责执行命令 c->cmd->proc 并更新统计信息,执行完成后负责同步数据 propagate 。
主要是负责同步数据到AOF文件和slave节点,feedAppendOnlyFile负责同步到AOF文件,replicationFeedSlaves负责同步
AOF涉及的缓存有多份,包括
包含了命令和对应执行函数的映射关系,应该看上去很清晰命令。
协议的一般格式如下,注意前面的或者$等字符,结尾的\r\n是分隔符。
其中, 回复中的第二个元素为空。
的计算方法有以下几种:
1 平均耗时计算:可以通过计算每次服务调用的总耗时,除以调用次数,得到服务的平均耗时。
2 中位数计算:可以通过将每次服务调用的耗时进行排序,然后取中间值,得到服务的中位数耗时。
3 分位数计算:可以通过将每次服务调用的耗时进行排序,然后取不同分位数的值,得到服务的分位数耗时。
4 百分位计算:可以通过将每次服务调用的耗时进行排序,然后取不同百分位的值,得到服务的百分位耗时。
之前有朋友问过我,说我们生产环境的redis怎么经常会丢掉一些数据?写进去了,过一会儿可能就没了。
我的天啊,你问这个问题就说明redis你就没用对啊。redis是缓存,你给当存储了是吧?
啥叫缓存?用内存当缓存。内存是无限的吗?恰恰相反,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个G的内存,但是可以有几个T的硬盘空间。redis主要是基于内存来进行高性能、高并发的读写 *** 作的。
那既然内存是有限的,比如redis就只能用10个G,你要是往里面写了20个G的数据,会咋办?当然会干掉10个G的数据,然后就保留10个G的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。
所以说,这是缓存的一个最基本的概念,数据是会过期的,要么是你自己设置个过期时间,要么是redis自己给干掉。
例如:set key value 过期时间(1小时)
set进去的key,1小时之后就没了,就失效了
(1)设置过期时间
我们set key的时候,都可以给一个expire time,就是过期时间,指定这个key比如说只能存活1个小时?10分钟?这个很有用,我们自己可以指定缓存到期就失效。
如果假设你设置一批key只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?
答案是:定期删除+惰性删除
所谓定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。
假设redis里放了10万个key,都设置了过期时间,你每隔几百毫秒,就检查10万个key,那redis基本上就死了,cpu负载会很高的,消耗在你的检查过期key上了。
注意,这里可不是每隔100ms就遍历所有的设置过期时间的key,那样就是一场性能上的灾难。实际上redis是每隔100ms随机抽取一些key来检查和删除的。
但是问题是,定期删除可能会导致很多过期key到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。惰性删除就是说,在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
所以并不是key到时间就被删除掉,而是你查询这个key的时候,redis再懒惰的检查一下。
通过上述两种手段,保证过期的key一定会被干掉。
很简单,就是说,你的过期key,靠定期删除没有被删除掉,还停留在内存里,占用着你的内存呢,除非你的系统去查一下那个key,才会被redis给删除掉。
但是实际上这还是有问题的,如果定期删除漏掉了很多过期key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了,咋整?
答案是:走内存淘汰机制。
(2)内存淘汰
如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略:
1)noeviction:当内存不足以容纳新写入数据时,新写入 *** 作会报错,这个一般没人用吧,实在是太恶心了
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给干掉啊
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
例如:redis 里有10个key,现在内存已经满了,设置的淘汰策略是allkeys-lru,redis需要删除掉一些key来保证你可以继续写入。在这10个key中,其中1个key,最近1分钟被查询了100次,1个key,最近10分钟被查询了50次,1个key,最近1个小时被查询了1次。肯定那些最近最少使用的被干掉了。
为啥存redis的数据有时候会丢失?
很简单,你写的数据太多了,内存占满了,或者触发了什么条件,如redis allkeys-lru内存淘汰策略,自动给你清理掉了一些最近很少使用的数据。
使用Redis的脚本功能实现Redis中数据简单查询,有需要的朋友可以参考下。 在Redis的设计中,key是一切,对于Redis是可见的,而value对于Redis来说就是一个字节数组,Redis并不知道你的value中存储的是什么
在这篇文章中,我们来讲一讲Redis的数据结构和通用命令。
Redis支持多种不同的数据结构,包括5种基础数据结构和几种比较复杂的数据,这些数据结构可以满足不同的应用场景。
五种基础数据结构
复杂的数据结构
不同数据结构的相同之处
从上面的介绍,我们看到支持的数据结构的不同,但其实,Redis的每一种数据结构都由一个key和value组成,可以抽象为:
Redis数据结构组成
而所有数据结构的key的值都是任意合法的字符串,不同的数据结构的区别就在于value存储的值的不同而不同。
比如,最简简单的String数据结构,其value为String,所以String可以表示为:
而Hash数据结构,其value为一个哈希列表,所以Hash可以表示为:
这里就列出String和Hash来讲解说明,关于更多数据结构的内部结构及详细 *** 作,我们在之后的文章在再谈谈吧。
Redis官网将Redis的命令按照功能划分为15个主题分组,其中,Kyes主题的命令对所有的数据结构都通用,因此,有必要在了解其他数据结构命令前好好学习一下。
keys
keys命令的作用是列出Redis所有的key,该命令的时间复杂度为 O(N) , N 随着Redis中key的数量增加而增加,因此Redis有大量的key,keys命令会执行很长时间,而由于Redis是单线程,某个命令耗费过长时间,则会导致后面的的所有请求无法得到响应,因此,千万不要在生产服务器上使用keys命令。
示例
exists
exists命令用于判断一个或多个key是否存在,判断多个key时,key之间用空格分隔,exists的返回值为整数,表示当前判断有多少个key是存在的。
示例
del
del命令用于删除一个或多个key,多个key之间用空格分隔,其返回值为整数,表示成功删除了多少个存在的key,因此,如果只删除一个key,则可以从返回值中判断是否成功,如果删除多个key,则只能得到删除成功的数量。
示例
expire,pexpire
expire设置key在多少秒之后过期,pexpire设置key在多少毫秒之后过期,成功返回1,失败返回0。
示例
ttl,pttl
ttl和pttl命令用于获取key的过期时间,其返回值为整型,代表的意义分为几种情况:
示例(ttl的演示,pttl类似)
expireat,pexpireat
设置key在某个时间戳过期,expreat参数时间戳用秒表示,而pexpireat则用毫秒表示,与expire和pexpire功能类似,返回1表示成功,0表示失败。
示例
persist
移除key的过期时间,将key设置为永久有效,当key设置了过期时间,使用persist命令移除后返回1,如果key不存在或本身就是永久有效的,则返回0。
示例
type
判断key是什么类型的数据结构,返回值为string,list,set,hash,zset,分别表示我们前面介绍的Redis的5种基础数据结构。
示例
上面介绍的是Redis中最常用的通用命令,虽然简单,但还是非常有必要掌握其用法和使用方面要注意的事项,其实,对于普通开发人员来说,很多时候,也只是使用这些基础通用的命令来 *** 作Redis而已。
以上就是关于redis怎么设置时间全部的内容,包括:redis怎么设置时间、redis-cli执行命令返回1、基于Redis实现分布式定时任务等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)