redis · 4 4 月, 2021 0

redis数据库

redis数据库组成

  • redis在启动时会启动16个数据库实例

  • redis客户端链接时, 默认链接的是0数据库

  • 可以通过select index的方式切换数据库

数据存储方式

  • redis是键值对方式存储数据, 键是字符串对象; 值时具体对象,包括字符串对象, 列表对象, 集合对象, 哈希对象, 有序集合对象

  • redis在每个数据库中存储数据是采用的是dict(字典)数据结构进行存储

    • key : 字符串对象redisObject

    • value: 存储的是redisObject对象

读写键控件时的维护操作

  • 在读取一个键(读操作和写操作都要对键进行读取), 服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数. 这两个值可以在info stats命令的keyspace_hits属性和keyspce_misses属性查看

  • 在读取一个键之后, 服务器会更新键的LRU时间。这个值可以用于计算键的闲置时间, 可以使用OBJECT idletime <key>命令查看

  • 如果服务器在读取一个键时发现该键已经过期, 那么服务器会先删除这个过期键. 再执行其他操作

  • 如果客户端使用WATCH命令监视了某个键, 那么服务器在对呗监视的键进行修改之后, 会将这个键标记为脏(dirty), 从而让事务程序注意到这个键已经被修改过.

  • 如果服务器开启了数据库通知功能, 那么在对键进行修改之后, 服务器将按配置发送相应的数据通知.

设置过期时间

在redis中, 可以通过为key设置过期时间, 达到在指定时间(毫秒或者秒为精度)之后, 将自动删除键.

  • EXPIRE <key> <ttl> 命令用于将键key的生存时间设置为ttl秒

  • EXPIREAT <key> <timestamp> 命令用于将键key的生存时间设置为timestamp所指定的秒数时间戳

  • PEXPIRE <key> <ttl> 用于将键key的生存时间设置为ttl毫秒

  • PEXPIREAT <key> <timestamp> 命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳

NOTE: 对于以上的任何命令, 最终都是使用PEXPIREAT命令

保存过期时间

在redis中保存过期时间是通过dict老保存, 保存格式为:

  • key: 为键值对的key对象, 与具体的键值对共享同一个字符串对象

  • value: 具体的过期时间,

NOTE: 因为存储的key-value和过期时间的key-value中的key是共用对象, 所以不会造成内存浪费的情形.

移除过期时间

PERSIST命令可以移除一个键的过期时间:

 redis> PEXPIREAT message 122223232323
 ​
 redis> TTL message
 ​
 redis> PERSIST message
 ​
 redis> TTL message

 

过期键的删除策略

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

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

  • 定期删除: 每隔一段时间, 程序就对该数据库进行一次检查, 删除里面的过期键.

定时删除

  • 定时删除对内存最友好, 可以保证过期的键会尽可能地被删除, 并释放过期键占用的内存.

  • 对CPU时间时不友好的, 在过期键比较多的情况下, 删除过期键这一行为可能会占用相当一部分CPU时间, 在内存不紧张但是CPU时间非常紧张的情况下, 将CPU时间用在删除和当前任务无关的过期键上, 无疑对服务器响应时间和吞吐量造成影响

  • 创建定时器需要用到redis服务器中的时间事件, 而当前时间事件实现方式-无序链表, 查找一个事件的时间复杂度为O(N). 并不能处理大量的事件时间

惰性删除

  • 惰性删除对CPU最友好, 因为不会花过多的时间在删除过期键的行为上, 只在有需要的时候执行必要的键删除操作.

  • 堆内存来说很不友好, 如果一个键已经过期, 但是仍然在数据库中, 那么只要这个键不被删除, 它所占用的内存就不会释放。

定期删除

  • 定时删除占用太多CPU时间, 影响服务器的响应时间和吞吐量

  • 惰性删除浪费太多内存, 有内存泄露的危险

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

  • 定期删除策略每个一段时间执行一次删除过期键操作, 并通过限制删除操作执行的时长和频率减少删除操作对CPU时间的影响

  • 通过定期删除过期键, 定期删除策略有效地减少了因为过期键带来内存浪费

Redis的过期键删除策略

对于redis服务器实际使用的是惰性删除定义删除两种策略: 通过配合使用这两种删除策略, 很好地在合理使用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文件中.

复制

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

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

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

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

数据库通知

数据库通知是Redis 2.8版本新增加的功能, 这个功能可以让客户端通过订阅给定的频道或者模式, 来获知数据库中键的变化, 以及数据库中命令的执行情况.

服务器配置的notify-keyspace-events选项决定了服务器所发送的通知类型:

  • 想让服务器发送所有类型的键空间通知和键时间通知, 可以将选项设置为AKE

  • 想让服务器发送所有类型的键空间通知, 可以将选项的值设置为AK

  • 想让服务器发送所有类型的键时间通知, 可以将选项的值设置为AE

  • 想让服务器只发送和字符串键有关的键空间通知, 可以将选项的值设置为K$

  • 想让服务器只发送和列表键有关的键时间通知, 可以将选项设置为El