在redis
中, 对象系统中构建一个引用计数
实现的内存回收机制, 通过这一机制, 程序可以通过跟踪对象的引用计数信息, 在适当的时候自动释放对象并进行内存回收.
typedef struct redisObject { // 引用计数 int refcount; }
对象计数信息变化
-
在创建一个新对象时, 引用计数的值会被初始化为
1
-
当对象被一个新程序引用时, 它的引用计数值会被
+1
-
当对象不再被一个程序使用时, 它的引用计数值会被
-1
-
当对象的引用计数值变为
0
时, 对象占用的内存会被释放
对象共享
除了用于实现计数内存回收机制外, 对象的引用计数属性还带有对象共享
作用。
在redis中, 让多个键共享同一个值对象需要执行以下两个步骤:
-
将数据库键的值指向一个现有的值对象
-
将被共享的值对象的引用计数
+1
NOTE: 目前redis会在初始化服务器时, 创建一万个字符串对象, 这些对象包含了从
0
到9999
的所有整数值, 当服务器需要用到0
到9999
的字符串对象时, 服务器就会使用这些共享对象。
# 查看对象的引用计数信息
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