php redis hset过期时间,详解Redis中数据过期策略

  • Post author:
  • Post category:php


相信大家对Redis中数据过期有点了解,本文主要介绍了Redis中的数据过期策略,文中通过示例代码介绍的很详细,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友可以参考借鉴,希望能帮助到大家。

1、Redis中key的的过期时间

通过EXPIRE key seconds命令来设置数据的过期时间。返回1表明设置成功,返回0表明key不存在或者不能成功设置过期时间。在key上设置了过期时间后key将在指定的秒数后被自动删除。被指定了过期时间的key在Redis中被称为是不稳定的。

当key被DEL命令删除或者被SET、GETSET命令重置后与之关联的过期时间会被清除127.0.0.1:6379> setex s 20 1

OK

127.0.0.1:6379> ttl s

(integer) 17

127.0.0.1:6379> setex s 200 1

OK

127.0.0.1:6379> ttl s

(integer) 195

127.0.0.1:6379> setrange s 3 100

(integer) 6

127.0.0.1:6379> ttl s

(integer) 152

127.0.0.1:6379> get s

“1\x00\x00100”

127.0.0.1:6379> ttl s

(integer) 108

127.0.0.1:6379> getset s 200

“1\x00\x00100”

127.0.0.1:6379> get s

“200”

127.0.0.1:6379> ttl s

(integer) -1

使用PERSIST可以清除过期时间127.0.0.1:6379> setex s 100 test

OK

127.0.0.1:6379> get s

“test”

127.0.0.1:6379> ttl s

(integer) 94

127.0.0.1:6379> type s

string

127.0.0.1:6379> strlen s

(integer) 4

127.0.0.1:6379> persist s

(integer) 1

127.0.0.1:6379> ttl s

(integer) -1

127.0.0.1:6379> get s

“test”

使用rename只是改了key值127.0.0.1:6379> expire s 200

(integer) 1

127.0.0.1:6379> ttl s

(integer) 198

127.0.0.1:6379> rename s ss

OK

127.0.0.1:6379> ttl ss

(integer) 187

127.0.0.1:6379> type ss

string

127.0.0.1:6379> get ss

“test”

说明:Redis2.6以后expire精度可以控制在0到1毫秒内,key的过期信息以绝对Unix时间戳的形式存储(Redis2.6之后以毫秒级别的精度存储),所以在多服务器同步的时候,一定要同步各个服务器的时间

2、Redis过期键删除策略

Redis key过期的方式有三种:被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key

主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key

当前已用内存超过maxmemory限定时,触发主动清理策略

被动删除

只有key被操作时(如GET),REDIS才会被动检查该key是否过期,如果过期则删除之并且返回NIL。

1、这种删除策略对CPU是友好的,删除操作只有在不得不的情况下才会进行,不会其他的expire key上浪费无谓的CPU时间。

2、但是这种策略对内存不友好,一个key已经过期,但是在它被操作之前不会被删除,仍然占据内存空间。如果有大量的过期键存在但是又很少被访问到,那会造成大量的内存空间浪费。expireIfNeeded(redisDb *db, robj *key)函数位于src/db.c。/*—————————————————————————–

* Expires API

*—————————————————————————-*/

int removeExpire(redisDb *db, robj *key) {

/* An expire may only be removed if there is a corresponding entry in the

* main dict. Otherwise, the key will never be freed. */

redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);

return dictDelete(db->expires,key->ptr) == DICT_OK;

}

void setExpire(redisDb *db, robj *key, long long when) {

dictEntry *kde, *de;

/* Reuse the sds from the main dict in the expire dict */

kde = dictFind(db->dict,key->ptr);

redisAssertWithInfo(NULL,key,kde != NULL);

de = dictReplaceRaw(db->expires,dictGetKey(kde));

dictSetSignedIntegerVal(de,when);

}

/* Return the expire time of the specified key, or -1 if