一. 概述
对于前面的五章中, 已清楚了数据对象的类型以及命令实现, 其实还有一种数据对象为 HyperLogLog, 以后需要用到再了解. 下面再了解类型检查, 内存回收, 对象共享, 对象的空转时长.
1.1 类型检查与命令多态
Redis 中用于操作键的命令基本上可以分为两种类型, 一种是可以对任何的键执行, 如: del, expire,rename,type,object 这些命令等, 对于这些命令属于多态命令. 另一种命令只能针对特定类型的键执行, 如:
Set, get, append, strlen 等命令只能对字符串键执行 |
Hdel,hset,hget,hlen 等命令只能对哈希键执行 |
Rpush, lpop, linsert,llen 等命令只能对列表键执行 |
Sadd, spop, sinter,scard 等命令只能对集合键执行 |
Zadd,zcard,zrank,zscore 等命令只能对有序集合键执行 |
1.2. 内存回收
在 c 语言中并不具备自动内存回收功能, 所以 Redis 在自己的对象系统中构建了一个引用计数来实现内存回收机制, 通过这一机制, 程序可以跟踪对象的引用 计数信息, 在适当的时候自动释放对象并进行内存回收.
每个对象的引用计数信息由 redisObject 结构的 refcount 属性记录. 对象的引用计数信息会随着对象的使用状态而不断变化:
(1) 在创建一个新对象时, 引用计数的值会被初始化为 1;
(2) 当对象被一个新程序使用时, 它的引用计数值会加 1;
(3) 当对象不再被一个程序使用时, 它的引用计数值会减 1;
当对象的引用计数值变为 0 时, 对象所占用的内存就会被释放. OBJECT REFCOUNT <key> 返回给定 key 引用所储存的值的次数. 此命令主要用于除错.
1.3 对象共享
上面讲到了 refcount 属性, 除了对象引用计数, 还有对象共享的作用. 假设键 A 创建了一个包含整数值 100 的字符串对象作为值对象, 键 B 也要保存一个同样的值, 那么在 Redis 中, 会让多个键共享同一个值对象, 来节约内存 (实际在 Redis 4.06 版本中对象共享不能通过 refcount 来识别) .
1.4 对象的空转时长
在前面章节中介绍了 redisobject 结构的 type,encoding,ptr 还有 refcount 属性, 在该结构里还有一个属性为 lru 属性, 该属性记录了对象最后一次被命令程序访问的时间.
OBJECT IDLETIME <key> 返回给定 key 自储存以来的空闲时间 (idle, 没有被读取也没有被写入), 以秒为单位.
例如: 使用 set 命令新建一个 key 为 msg, 过一会时间使用 object idletime 命令打印该 key 的空转时长
- 127.0.0.1:6379> set msg "hello"
- OK
127.0.0.1:6379> object idletime msg -- 显示空转时长 110 秒
(integer) 110
127.0.0.1:6379> get msg -- 再次被换醒
"hello"
127.0.0.1:6379> object idletime msg -- 空转时长重新计算 3 秒
(integer) 3
如果服务器打开了 maxmemory 选项, 并且服务器用于回收的算法为 volatile-lru 或者 allkeys-lru, 那么当服务器占用的内存数超过了 maxmemory 选项所设置的上限值时. 空转时长较高的那部分键会优先被服务器释放, 从而回收内存.
- 127.0.0.1:6379> config get maxmemory
- 1) "maxmemory"
- 2) "0"
- 127.0.0.1:6379> config get maxmemory-policy
- 1) "maxmemory-policy"
- 2) "noeviction"
maxmemory 表示 Redis-cache 所能使用的最大内存 (bytes), 默认为 0, 表示 "无限制".maxmemory-policy 表示当达到 maxmemory 最大内存时, 触发的 "清除策略". 包括以下取值:
内存清除策略选项 | 说明 |
noeviction | 不做任何干扰操作, 直接返回 OOM 异常 |
volatile-lru | 对 "过期集合" 中的数据采取 LRU(近期最少使用) 算法。如果对 key 使用 "expire" 指令指定了过期时间,那么此 key 将会被添加到 "过期集合" 中。全部移除仍不能满足内存需求, 将 OOM |
allkeys-lru | 对所有的数据, 采用 LRU 算法 |
volatile-random | 对 "过期集合" 中的数据采取 "随即选取" 算法, 并移除选中的 K-V, 直到 "内存足够" 为止. 全部移除仍不能满足, 将 OOM |
allkeys-random | 对所有的数据, 采取 "随机选取" 算法, 并移除选中的 K-V, 直到 "内存足够" 为止 |
volatile-ttl | 对 "过期集合" 中的数据采取 TTL 算法 (最小存活时间), 移除即将过期的数据. |
二. 切换数据库
2.1 服务器中数据库
Redis 服务器将所有数据库都保存在服务器状态 Redis.h/redisServer 结构的 db 数组中, db 数组的每个项都是一个 Redis.h/redisDB 结构, 每个 redisDB 结构代表一个数据库. 在初始化服务器时, 程序会根据服务器状态的 dbnum 属性来决定应该创建多少个数据库. 默认情况下会创建 16 个数据库.,
- struct redisServer{
- redisDb* db;
- int dbnum;
- ...
- };
2.2 切换数据库
每个 Redis 客户端都有自己的目标数据库, 每当客户端执行数据库写命令或读命令的时候, 就是操作自己的目标数据库. 默认情况下, Redis 客户端的目标数据库为 0 号数据库, 但客户端可以通过执行 select 命令来切换目标数据库.
下例客户端在 0 号数据库设置并读取键 msg, 之后切换到 1 号数据库再读取 msg 键时, 提示没有该键, 说明数据库之间具有隔离性.
- 127.0.0.1:6379> set msg "hello"
- OK
- 127.0.0.1:6379> get msg
- "hello"
127.0.0.1:6379> select 1 -- 切换到第 2 个数据库
OK
127.0.0.1:6379[1]> get msg -- 没有该 key
(nil)
来源: https://www.cnblogs.com/MrHSR/p/9990231.html