Redis高级特性——键的操作

生存时间

在日常业务需求中,总有一些要在某时间节点,做一些特殊的操作这样的需求。如下订单后,需要支付,用户支付一般有一个限制时间,京东15分钟未支付,订单取消;12306在45分钟内未支付则预定火车票取消;再比如登录手机验证码,一般获取一个验证有效期为1分钟,一方面为了保证用户不至于刷短线,另一方面也能够防止一个手机验证码可以长期使用。这些业务需求,在关系型数据库中,一般添加一个到期时间字段,记录每个业务的到期时间,再起一个任务,不断去检查任务是否到期,这样的做法代价太大,耗费资源严重。在Redis中针对每个键都提供了设置生存时间的功能,一旦设置后,到期后Redis自动清除该键值,业务系统只要读取不到就意味着数据到期。

生存时间很重要,但在开发阶段无法做到设置一个非常合理的过期时间。为了尽可能的提高网站的并发量,需要将一些DB中的数据经过整合后,放入到Redis中,以达到提高并发的目的。一般情况下,服务器的内存是有限的,如果将大量的数据键设置为永久有效或具有很长的生存时间如一年;结果可能是在短时间内Redis内存占满,而当用户再继续使用新的DB数据时,将不能够再写入Redis,而使得并发降低,大量的请求直接读库。如果反过来,设置了大量的数据键生存时间较短,如1个小时,这样将会导致Redis数据频繁过期,这一方面也会造成一定的浪费,同时大量的数据过期,也会降低缓存命中率,从而导致很多并发请求转到读库操作,也会降低并发量。

考虑到这些问题,一般情况对于Redis的缓存过期会采用设置生存时间和Redis自有淘汰规则的组合方案。具体的设置方法:

  • 修改Redis的maxmemory参数(最大内存),该参数将会限制Redis的最大使用内存,单位为字节

  • 当一个缓存系统超过了最大内存时,Redis将会按照配置的maxmemory-policy策略进行缓存内数据的淘汰,直到Redis的缓存数量达到最大内存配置为止

Redis的maxmemory-policy支持六种策略,其中LRU最近最少使用的两种策略较为常用(最近最少使用的键,在未来的一段时间内,也会被最少使用到),以下算法会一个键一个键进行删除,直到满足条件。

策略 描述
volatile-lru LRU算法,删除键,只针对设置了生存时间的键
allkeys-lru LRU算法,针对所有键
volatile-random 随机删除键,只针对设置了生存时间的键
allkeys-random 随机删除键,全部键
volatile-ttl 删除生存时间最近的键
noeviction 不删除键,只返回错误信息

LRU算法,并不是完全从全库中进行排序后进行删除,而是随机的从Redis中读取三个键(默认,可以通过maxmemory-samples进行配置),并删除这三个键中最久未使用的键,依此反复,直到满足需求为止。volatile-ttl算法也是按此方法进行。

获取生存时间
TTL key
PTTL key

TTL指令用于获取一个键的生存时间,返回键剩余的生存时间,单位为秒。如返回12,则意味着键还有12秒就过期了。

PTTL指令同TTL基本一致,当指定了有效期时,该指令返回的是毫秒单位。

  • 当键不存在时,该指令返回-2
  • 当键存在,但未设置生存时间,则为永久有效,返回-1
  • 其他情况均返回键的剩余生存时间,单位为秒
TTL a   # 键a不存在
# (integer) -2
SET a 1
# OK
TTL a   # 创建键a,但未设置有效时间,永久有效
# (integer) -1
EXPIRE a 12
# (integer) 1
TTL a
# (integer) 10
PEXPIRE a 12300
# (integer) 1
PTTL a
# (integer) 10116
设置生存时间
EXPIRE key ttl_seconds
PEXPIRE key ttl_millseconds
  • EXPIRE指令用于设置键key的生存时间,单位为秒
  • PEXPIRE指令同EXPIRE指令一致,区别是单位是毫秒

这两个指令可以与TTL/PTTL相对应。指令返回值

  • 当键存在,设置成功时,返回1
  • 当键不存在或设置失败时,返回0
SET a 1
# OK
TTL a
# (integer) -1
EXPIRE a 10
# (integer) 1
TTL a 
# (integer) 8
TTL a 
# (integer) 2
TTL a 
# (integer) -2
SET a 1
# OK
PEXPIRE a 12300
# (integer) 1
TTL a 
# (integer) 8

EXPIRE aa 12    # aa 不存在
# (integer) 0

当设置有效期时,指定的ttl值为-1,则意味着删除该键。

SET a 1
# OK
EXPIRE a -1
# (integer) 1
TTL a
# (integer) -2
清除生存时间
PERSIST key

PERSIST指令可以将一个键的生存时间调整为永久有效,即TTL=-1。当成功调整键有效期为永久有效时,返回1;当键不存在或者键本身为-1时,返回0

除了PERSIST指令可以清除生存时间外,重新使用SET等赋值指令,也可以将原有的生存时间重置为-1

PERSIST a   # 键a不存在
# (integer) 0
SET a 1
# OK
PERSIST a   # a未设置有效期,永久有效
# (integer) 0
EXPIRE a 12300
# (integer) 1
TTL a
# (integer) 12296
PERSIST a
# (integer) 1
TTL a
# (integer) -1
指定时间点到期
EXPIREAT key timestamp
PEXPIREAT key timestamp

EXPIREAT指令也是用于设置key的生存时间,与EXPIRE相比,该指令使用一个时间戳作为第二个参数,意思是到指定的时间点时,该key过期。如设置当天23:00过期,则只要计算出单天23:00的时间戳即可。时间戳单位为秒。

PEXPIREAT指令同EXPIREAT指令一致,唯一区别是单位为毫秒。

当成功设置时,返回1。当键不存在,返回0;当时间戳比当前时间小,返回1,意味着删除键。

SET a 1
# OK
EXPIREAT a 1576561888   # 距离当前还有190秒
# (integer) 1
TTL a
# (integer) 185
PEXPIREAT a 1576561990123   # 距离当前还有139秒又123毫秒
# (integer) 1
PTTL a
# (integer) 127294
TTL a 
# (integer) 125
EXPIREAT a 1476561888   # 时间戳已过去
# (integer) 1
TTL a       # 键不存在
# (integer) -2  

删除键

DEL key [key ...]

DEL指令用于删除指定的一个键或多个键,返回成功删除的键数量。当指定的键不存在时,则不执行操作。

SET a 1
# OK
SET aa 12
# OK
SET aaa 123
# OK
DEL a
# (integer) 1
DEL a aa aaa
# (integer) 2

判断键是否存在

EXISTS key [key ...]

EXISTS指令用于判断指定的key在Redis中是否存在,如果存在,则返回1,不存在返回0。该指令可以同时判断多个key,返回的数量是1的累加,但同时指定多个key,仍无法确认具体的key是否存在。

EXISTS a    # a不存在
# (integer) 0
SET a 1
# OK
SET aa 1
# OK
EXISTS a
# (integer) 1
EXISTS a aa aaa
# (integer) 2

返回指定的键列表

KEYS pattern

KEYS指令用于返回指定模式的键列表信息。如果keys *将返回全部键列表,该指令在库数据量较大时,会阻塞Redis,如果在生产环境下,将会有一定的时间无法正确使用Redis,因此一般都不建议在生产环境使用该指令。

KEYS *
# 全库键列表
KEYS a  #只返回键a
# "a"
KEYS aa*    # 返回aa开头的所有键
# "aa"
# "aaa"

库间移动

MOVE key db

MOVE指令将从当前的库中,移动键到指定的库db中。移动成功时返回1,移动失败时返回0。默认情况下Redis实例安装成功后,将会默认创建0-15索引的16个库。该指令一次只能移动一个键。

# 选择库0
SELECT 0
# OK
KYES a*
# "a"
# "aa"
# "aaa"
MOVE a 1
# (integer) 1
MOVE a 1
# (integer) 0
EXISTS a
# (integer) 0
# 切换库1,库1未使用过
SELECT 1
# OK
KEYS *
# "a"

修改键名

RENAME key newKey
RENAMENX key newKey
  • RENAME指令用于将一个键名为key的键,修改为新键名newKey。当修改成功时,返回OK,其他情况返回错误信息。

key和newKey相同时,返回OK,相当于没有修改(不同版本的Redis可能存在差异)

key不存在时,返回错误信息

当key,newKey存在时,则使用key的值覆盖已存在的newKey

  • RENAMENX指令用于修改键名,但必须指定的newKey不存在时,才修改,如果newKey存在,则不做调整

修改成功时,返回1

newKey存在时,返回0

当key不存在时,返回错误

# key不存在
RENAME aaaaa ad
# no such key
RENAME a ab
# OK
GET aa
# "1"
GET aaa
# "2"
RENAME aa aaa       # 使用aa的值覆盖aaa的值
# OK
GET aa
# nil
GET aaa     # 原有的aaa被覆盖
# "1"

SET a 1
# OK
SET aa 2
# OK
DEL aaa
# (integer) 1
# 将a重命名为aaa
RENAMENX a aaa
# (integer) 1
EXISTS a
# 0
EXISTS aaa
# 1
# aa存在,不会调整
RENAMENX aaa aa
# (integer) 0
RENAMENX aaaaa aa
# no such key

返回键类型

TYPE key

TYPE指令用于检查key的数据类型。

SET a 1
# OK
ZADD b 1 c 2 d
# (integer) 2
SADD c 1 2
# (integer) 2
LPUSH d 1 2
# (integer) 2
HSET e a 1
# (integer) 1
TYPE a
# string
TYPE b
# zset
TYPE c
# set
TYPE d
# list
TYPE e
# hash
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容