redis 数据库

Redis服务器默认会创建16个数据库

切换数据库

每个redis客户端都有自己的目标数据库,每当客户端执行数据库写命令或者数据库读命令的时候,目标数据库就会成为这些命令的操作对象。默认情况下Redis客户端的目标数据库为0号数据库,但客户端可以通过执行select命令来切换目标数据库。到目前为止,Redis仍然没有可以返回客户端目标数据库的命令。虽然redis-cli客户端会在输入符旁边提示当前所使用的目标数据库。

数据库键空间

Redis是一个键值对数据库服务器,服务器中的每个数据库都由一个redis.h/redisDb结构表示,其中redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间。键空间和用户所见的数据库是直接对应的

1:键空间的键也就是数据库的键,每一个键都是一个字符串对象

2:键空间的值也就是数据库的值,每个值可以是字符串对象,列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象

因为数据库的键空间是一个字典,所以所有针对数据库的操作,比如添加一个键值对多数据库、或者从数据库中删除一个键值对,又或者在数据库中获取某个键值对等,实际上都是通过对键空间字典进行操作来实现的。

添加新键

添加一个新键值对到数据库,实际上就是将一个新键值对添加到键空间字典里面,其中键为字符串对象,而值为任意一种类型的Redis对象,例如set date "2013-12-1"键空间将添加一个新的键值对,这个新键值对的键是一个包含字符串date对象,而键值对的值则是一个包含字符串“2013-12-1”的字符串对象

删除键

删除数据库中的一个键,实际上就是在键空间里面删除键所对应的键值对对象。如 del book

更新键

对一个数据库键进行更新,实际上就是对键空间里面键所对应的值对象进行更新,根据值对象的类型不同,更新方法也有所不同如set message  "blah blah"键message的值对象将从之前包含“hello world”字符串更新为包含"blah blah"

对键取值

对一个数据库键进行取值,实际上就是在键空间中取出键所对应的值对象,根据值对象的类型不同具体的取值方法也不同

例如get message get命令将首先在键空间中查找键message如果存在message键然后判断message键的类型如果键的类型为字符串类型则返回值,如果键的类型非字符串类型则返回错误

读写键空间时的维护操作

当使用Redis命令对数据库进行读写时,服务器不仅会对键空间执行指定的读写操作还会执行一些额外的维护操作,其中包括

1:在读取一个键后,服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数,这两个值可以在INFO stats命令的keyspace_hits属性和keyspace_misses属性中查看

2:在读取一个键后,服务器会更新键的LRU(最后一次访问时间),这个值可以用于计算键的闲置时间,使用OBJECT idletime key命令可以查看键key的闲置时间

3:如果服务器在读取一个键时发现该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的其他操作

4:如果有客户端使用watch命令监视了某个键,那么服务器在对被监视的键进行修改之后,会将这个键标记为赃,从而让事务程序注意到这个键已经被修改过

5:服务器每次修改一个键之后,都会对赃键计数器的值增1,这个计算器会触发服务器的持久化以及复制操作

    设置键的生存时间或过期时间

通过expire命令或者pexpire命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间(TTL)在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间为0的键

expire命令和pexpire命令类似,客户端可以通过expireat命令或pexpireat命令,以秒或者毫秒精度给数据库中的某个键设置过期时间,过期时间是一个unix时间戳,当键的过期时间来临时,服务器就会自动从数据库中删除这个键

TTL命令和PTTL命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间

设置过期时间

Redis有四个不同的命令可以用于设置键的生存时间或过期时间

1:expire key ttl 命令用于将键key的生存时间设置为ttl秒

2:pexpire key ttl 命令用于将键key的生存时间设置为ttl毫秒

3:expireat key timestamp 命令用于将键key的过期时间设置为timestamp所指定的秒数时间戳

4:pexpireat key timestamp 命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳

虽然有多种不同单位和不同形式的设置命令,但实际上expire,pexpire,expireat三个命令都是使用pexpireat命令来实现。

保存过期时间

redisDB结构的expire字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典

1:过期字典的键是一个指针,这个指针指向键空间中的某个键对象

 2:过期字典的值是一个long long类型的整数,这个整数保存了键所指向的数据库键的过期时间

移除过期时间

persist命令就是pexpireat命令的反操作,persist命令在过期字典中查找给定的键,并解除键和值在过期字典中的关联

计算并返回剩余时间

TTL命令以秒为单位返回键的剩余生存时间,而PTTL命令则以毫秒为单位返回键的剩余生存时间,TTL和PTTL两个命令都是通过计算键的过期时间和当前时间之间的差来实现的

过期键的判定

通过过期字典,程序可以用以下步骤检查一个给定键是否过期

1:检查给定键是否存在与过期字典,如果存在,那么取得键的过期时间

2:检查当前unix时间戳是否大于键的过期时间,如果是的话,那么键已经过期;否则的话,键未过期

过期键的删除策略

经过上一节的介绍,我们知道了数据库键的过期时间都保存在过期字典中,又知道了如何根据过期时间去判断一个键是否过期,现在剩下的问题是:如果一个键过期了,那么它什么时候会被删除呢?

这个问题又三种可能的答案,它们分别代表了三种不同的删除策略

1:定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作

2:惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键,如果没有过期,就返回该键

3:定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定

定时删除

定时删除策略对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存,定时删除策略的缺点是,它对CPU时间是最不友好的在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分cpu时间。除此之外,创建一个定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式为无序链表,查找一个事件的时间复杂度为O(N)并不能高效地处理大量时间事件。

惰性删除

惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行,并且删除的目标仅限于当前处理的键,这个策略不会在删除其他无关的过期键上花费任何CPU时间

惰性删除策略的缺点是,它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。

在使用惰性删除策略时,如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问的话,那么它们也许永远也不会被删除,我们甚至可以将这种情况看作是一种内存泄漏

定期删除

定期删除策略是前两种策略的一种整合和折中:

定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,除此之外通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费

AOF,RDB和复制功能对过期键的处理

生成RDB文件

在执行SAVE命令或者bgsave命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中

载入RDB文件

在启动Redis服务器时,如果服务器开启了RDB功能,那么服务器将对RDB文件进行载入

如果服务器以主服务器模式运行,那么在载入RDB文件时,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,而过期的键则会被忽略,所以过期键对载入RDB文件的主服务器不会造成影响

如果服务器以从服务器模式运行,那么在载入RDB文件时,文件中保存的所有键不论是否过期,都会被载入到数据库中,不过因为主服务器在进行数据同步的时候,从服务器的数据库就会被清空,所以一般来讲,过期键对载入RDB文件的从服务器也不会造成影响。

AOF文件写入

当服务器以AOF持久化模式运行时,如果数据库中的某个键已经过期,但它还没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生任何影响

当过期键被惰性删除或者定期删除后,程序会向AOF文件追加一条DEL命令,来显示地记录该键已被删除。

AOF重写

和生成RDB文件类似,在执行AOF重写的过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的AOF文件中

复制

当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制

1:主服务器在删除一个过期键之后,会显示地向所有从服务器发送一个DEL命令,告知从服务器删除这个过期键

2:从服务器在执行客户端发送的读命令时,即使碰到过期键也不会将过期键删除,而是继续像处理未过期的键一样来处理过期键

3:从服务器只有在接到主服务器发来的DEL命令之后,才会删除过期键

原文地址:https://www.cnblogs.com/paulversion/p/8261846.html