共计 3304 个字符,预计需要花费 9 分钟才能阅读完成。
redis实例key数量统计信息
使用dbsize查看
127.0.0.1:6379[1]> dbsize
(integer) 2556
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> dbsize
(integer) 1
使用info查看
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1,expires=0,avg_ttl=0
db1:keys=2499,expires=65,avg_ttl=69453573
- db[num]:代表数据库编号
- keys:代表有多少key
- expires:代表设置了TTL的keys数量
- avg_ttl:代表所有含有TTL的key的平均剩余时间,单位为秒
127.0.0.1:6379[1]> info stats
# Stats
total_connections_received:957
total_commands_processed:82588
instantaneous_ops_per_sec:0
total_net_input_bytes:42483858
total_net_output_bytes:408848674
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:130
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:96489
keyspace_misses:5594
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:377
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
- expired_keys:代表已过期但未删除的key
redis的key过期设置
设置过期时间
EXPIRE key seconds
PEXPIRE key milliseconds
- expire:设置key多少秒过期
- pexpire:设置key多少毫秒过期
查看key过期时间
TTL mykey
- 返回值大于0:代表多少秒后过期
- 返回值-1:表示该key没有设置过期时间
- 返回值-2:表示该key不存在
redis中key的过期配置
过期key不是立即删除,过期的key会在一定条件下进行惰性删除。具体来说,当一个过期的key被访问时,Redis会检查这个key是否过期,如果过期就删除它(返回空值(nil))。这样做的好处是可以减少Redis服务器在清理过期key时的负担,提高系统性能。但同时也意味着,如果有一些过期的key长时间没有被访问,那么它们可能会一直存在于数据库中,直到Redis服务器进行内存回收时才会被删除。
有几个可能的原因导致 Redis 中的过期键没有被及时删除:
- Redis 定期删除过期键的任务未执行。Redis 会以 1s 为单位检查是否有过期键需要删除,并在需要时执行删除操作。如果 Redis 的主线程被阻塞了(比如正在执行一个长时间的命令),那么这个定期删除的任务就可能无法被及时执行。
- Redis 机器的内存不足,导致 Redis 没有足够的内存来创建新的键值对。在这种情况下,Redis 会优先删除过期键,但是如果过期键的数量非常大,那么 Redis 可能会因为内存不足而无法创建新的键值对。
- Redis 配置了 AOF 持久化,但是 AOF 持久化的刷盘策略为每秒钟刷盘一次,这意味着即使过期键已经被删除了,它们也不会立即从磁盘上删除。如果 Redis 宕机了,那么这些过期键可能会被重新加载到 Redis 中。
如果你的 Redis 中出现了过期键没有被及时删除的情况,你可以通过检查 Redis 的日志和使用 Redis 监控命令来排查问题。
Redis中过期key的删除时间是由配置文件中的两个参数共同决定的:hz
和 maxmemory
hz
表示每秒执行多少次过期扫描。它的值默认为10,意味着Redis每秒会执行10次过期扫描。当然,你可以通过修改配置文件来调整这个值,以达到你的需求maxmemory
表示Redis可以使用的最大内存。如果Redis的内存使用量超过了这个值,那么就会执行过期扫描以删除过期的key。如果你的系统中有很多过期key需要删除,但是Redis的内存使用量又很高,那么你可以考虑适当调高maxmemory
的值,以便更快地删除过期key
需要注意的是,过期key的删除并不是实时进行的,而是通过定期扫描实现的。这也就意味着,有可能某些过期key会被保留一段时间,直到过期扫描定时执行时再被删除。
key过期删除策略参数
- noeviction:在达到最大内存限制时,所有写入操作(SET、LPUSH、RPUSH等)都会报错,或者简单地返回一个错误,从而阻止写入操作继续执行。配置参数:
maxmemory-policy noeviction
- allkeys-lru:当达到最大内存限制时,在所有键中选择最近最少使用的键进行删除。配置参数:
maxmemory-policy allkeys-lru
- volatile-lru:当达到最大内存限制时,在设置了过期时间的键中选择最近最少使用的键进行删除。配置参数:
maxmemory-policy volatile-lru
- allkeys-random:当达到最大内存限制时,在所有键中随机选择一个进行删除。配置参数:
maxmemory-policy allkeys-random
- volatile-random:当达到最大内存限制时,在设置了过期时间的键中随机选择一个进行删除。配置参数:
maxmemory-policy volatile-random
- volatile-ttl:当达到最大内存限制时,在设置了过期时间的键中,根据键值对象的过期时间,从小到大进行排序,删除过期时间最早的键。配置参数:
maxmemory-policy volatile-ttl
如果你需要实时删除过期key,那么可以通过手动执行DEL
命令来实现
使用lua脚本批量删除过期key
KEYS_PATTERN:用来匹配设置了TTL的key,因为过期key和未设置过期时间的key的TTL返回值都是-1,所以在操作前,需要过滤设置了TTL的key,这个需要咨询业务开发,避免把没有设置过期的key也删了!!!
local cursor = "0"
repeat
local keys = redis.call("SCAN", cursor, "MATCH", KEYS_PATTERN, "COUNT", BATCH_SIZE)
cursor = keys[1]
local key_batch = keys[2]
for i, key in ipairs(key_batch) do
if redis.call("TTL", key) < 0 then
redis.call("DEL", key)
end
end
until cursor == "0"
执行脚本
redis-cli --eval delete_expired_keys.lua
使用python批量延长key的过期时间
import redis
client = redis.Redis(host='localhost', port=6379)
# 过滤匹配的key
# client.scan_iter(match='prefix:*')
# 遍历所有的key
for key in client.scan_iter():
# 获取key的剩余过期时间
ttl = client.ttl(key)
# 如果剩余过期时间小于60秒,则延长过期时间
if ttl > 0 and ttl < 60:
client.expire(key, 600)
正文完