EXPIREAT 命令可以设置某个 key 在多少秒时间戳之后过期
PEXPIREAT 命令可以设置某个 key 在多少毫秒时间戳之后过期
PERSIST 命令可以移除键的过期时间
其实上述命令最终都会被转换成对 PEXPIREAT 命令。在 redisDb->expires 指向的 key 字典中维护着一个到期的毫秒时间戳。
TTL、PTTL 可以通过这两个命令查看某个 key 的过期秒、毫秒数。
redis 内部有一个 事件循环,这个事件循环会检查键的过期时间是否小于当前时间,如果小于则会删除这个键。
过期键删除策略在使用 redis 的时候我们最关心的就是键是如何被删除的,如何高效的准时的删除某个键。其实 redis 提供了两个方案来完成这件事情。
redis 采用 惰性删除 、 定期删除 双重删除策略。
当我们访问某个 key 的时候 redis 会检查它是否过期,这是惰性删除。
robj *lookupKeyRead(redisDb *db, robj *key) { robj *val; expireIfNeeded(db,key); val = lookupKey(db,key); if (val == NULL) server.stat_keyspace_misses++; else server.stat_keyspace_hits++; return val; } int expireIfNeeded(redisDb *db, robj *key) { mstime_t when = getExpire(db,key); mstime_t now; if (when < 0) return 0; /* No expire for this key */ if (server.loading) return 0; now = server.lua_caller ? server.lua_time_start : mstime(); if (server.masterhost != NULL) return now > when; /* Return when this key has not expired */ if (now <= when) return 0; /* Delete the key */ server.stat_expiredkeys++; propagateExpire(db,key); notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,"expired",key,db->id); return dbDelete(db,key); }redis 也会通过 事件循环 周期性的执行 key 的过期删除动作,这是定期删除。
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { /* Handle background operations on Redis databases. */ databasesCron(); } void databasesCron(void) { /* Expire keys by random sampling. Not required for slaves * as master will synthesize DELs for us. */ if (server.active_expire_enabled && server.masterhost == NULL) activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW); }惰性删除 是每次只要有读取、写入都会触发惰性删除代码。周期删除 是由 redis EventLoop 来触发的。redis 内部很多维护性工作都是基于 EventLoop 。
AOF 、RDB 处理过期键策略既然键会随时存在过期问题,那么涉及到持久化 redis 是如何帮我们处理的。
当 redis 使用 RDB 方式持久化时,每次持久化的时候就会检查这些即将被持久化的 key 是否已经过期,如果过期将直接忽略,持久化那些没有过期的键。当 redis 作为 master 主服务器 启动的时候,在载入 rdb 持久化键时也会检查这些键是否过期,将忽略过期的键,只载入没过期的键。
当 redis 使用 AOF 方式持久化时,每次遇到过期的 key redis 会追加一条 DEL 命令 到 AOF 文件,也就是说只要我们顺序载入执行 AOF 命令文件就会删除过期的键。
如果 redis 作为从服务器启动的化,它一旦与 master 主服务器 建立链接就会清空所有数据进行完整同步,当然新版本的 redis 支持 SYCN2 的半同步。如果是已经建立了 master/slave 主从同步之后,主服务器会发送 DEL 命令给所有从服务器执行删除操作。
Redis LRU 算法在使用 redis 的时候我们会设置 maxmemory 选项,64 位的默认是 0 不限制。线上的服务器必须要设置的,要不然很有可能导致 redis 宿主服务器直接内存耗尽最后链接都上不去。
所以基本要设置两个配置:
maxmemory 最大内存阈值
maxmemory-policy 到达阈值的执行策略
可以通过 CONFIG GET maxmemory/maxmemory-policy 分别查看这两个配置值,也可以通过 CONFIG SET 去分别配置。
maxmemory-policy 有一组配置,可以用在很多场景下: