redis · 2 4 月, 2021 0

redis对象回收与共享

对象的回收与共享

内存回收

redis中, 对象系统中构建一个引用计数实现的内存回收机制, 通过这一机制, 程序可以通过跟踪对象的引用计数信息, 在适当的时候自动释放对象并进行内存回收.

typedef struct redisObject {
 // 引用计数
 int refcount;
}

 

对象计数信息变化

  • 在创建一个新对象时, 引用计数的值会被初始化为1

  • 当对象被一个新程序引用时, 它的引用计数值会被+1

  • 当对象不再被一个程序使用时, 它的引用计数值会被-1

  • 当对象的引用计数值变为0时, 对象占用的内存会被释放

对象共享

除了用于实现计数内存回收机制外, 对象的引用计数属性还带有对象共享作用。

在redis中, 让多个键共享同一个值对象需要执行以下两个步骤:

  • 将数据库键的值指向一个现有的值对象

  • 将被共享的值对象的引用计数+1

NOTE: 目前redis会在初始化服务器时, 创建一万个字符串对象, 这些对象包含了从09999的所有整数值, 当服务器需要用到09999的字符串对象时, 服务器就会使用这些共享对象。

# 查看对象的引用计数信息
redis> OBJECT REFCOUNT msg
(integer) 1

对象的空转时长

除开前面介绍过的type,encoding,ptr,refcount四个属性wait, redisObject结构包含的最后一个属性为lru属性.该属性记录了对象最后一次被命令程序访问的时间:

typedef struct redisObject {
 unsigned lru:22;
}

 

OBJECT IDLETIME

OBJECT IDLETIME可以查看对象的空转时间, 使用当前时间 - 最后一次命令访问对象的时间

NOTE: OBJECT IDLETIME命令的实现是特殊的, 这个命令在访问键的值对象时, 不会修改之对象的LRU属性

空转时长的作用

  • 可以通过OBJECT IDLETIME命令打印出来

  • 如果服务器打开maxmemory选项, 并且服务器用于回收内存的算法为volatile-lru或者allkeys-lru。那么服务器占用的内存数超过了maxmemory选项所设置的上线值时, 空转时长较高的那部分键会优先被服务器释放, 从而回收内存。

maxmemory 和 maxmemory-policy
# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>
​
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction