第9章 数据库

  很重要的一章,通过两种重要的结构体介绍了单机数据库的实现,其次介绍了数据库键过期的删除策略

 9.1 服务器中的数据库

  对每一个Redis服务器,或者每开启的一个Redis Server进程,它都对应着一个redisServer的结构,该结构包含两个重要的属性:1、数据库数组 2、数据库数组的长度即该服务器包含多少个数据库。其中redisDb结构体代表一个数据库。一个redis服务器默认创建16个redis数据库。

struct redisServer {
    int dbnum;//服务器的数据库数量,值由服务器配置的“databases”选项决定,默认为16
    redisDb *db;//数组,保存着服务器中的所有数据库
}

   

  

 9.2 切换数据库

  可以通过select 语句切换数据库,切换底层的原理就是通过改变redisClient中db指针指向redisDb数组中的不同数据库。

9.3 数据库键空间

  对于每一个redis数据库而言,他都对应着一个键值对空间,即所有的key-value都保存在该空间中,具体的按照添加进去的顺序保存在redisDb中的dict数组中。对一个键除了增删改查之外,也会存在一些额外的操作,比如修改LRU的过期时间等等。

9.4 设置键的生成时间或过期时间

  Redis作为一种用来存储缓存的服务器,提供了设置键过期时间的命令,即一个键如果到了它被设置的过期时间,该键会从其数据库的键值空间中删除。

9.4.1 设置过期时间

  Redis共提供了四种有关设置过期时间的api

  • EXPIRE<key><ttl> 把key的生存时间设置成ttl秒
  • PEXPIRE<key><ttl>把key的生存时间设置为ttl毫秒
  • EXPIREAT<key><timestamp> 把key的生存时间设置为timestamp所指定的秒数时间戳
  • PEXPIREAT<key><timestamp> 把ket的生存时间设置为timestamp所指定的毫秒数时间戳

  上述四种spi底层都是通过PEXPIREAT来实现的

9.4.2 保存过期时间

  一个redisDB中所有键的过期时间保存在expires字典中,只要一个键被设置了过期时间都会被保存在expires字典中。expires也是一个字典,她的键指向dict中某个被设置了过期时间的键,值是该键过期的时间

  从PEXPIREAT的定义可以看出该方法非常简单,就是在expires中加上新的键值对。

def PEXPIREAT(key,expire_time_in_ms) :
#如果给定的键不存在于键空间,那么不能设置过期时间
if key not in redisDB.dict :
return 0
#在过期字典中关联键和过期时间
redisDB.expires[key]=expire_tirne_in_ms
#过期时间设置成功
return 1

9.4.3移除过期时间

  从expires数组中删除key

9.5 过期键删除策略

  当能确定一个键已经过期时,什么时候去删她?

9.5.1 定时删除

  当为一个键设置了过期时间时,同时为该键设置一个定时器,当定时器时间到达时删除该键。

  • 优点:内存友好,一个键一旦过期会被立即删除
  • 缺点:CPU不友好,如果过期的键非常的多,那么会有很多CPU时间用在删除过期的键上

9.5.2 惰性删除

  一个键过期了就过期了,等到下次访问该键的时候才会尝试删除该键,即一个过期的键会苟活到下次被访问

  • 优点:CPU友好,只有取出改键时才会进行过期检查,不会有过多的CPU时间浪费在删除过期的键
  • 缺点:内存不友好,如果大量的无用的键在内存中,而这些键又很不幸的不会被访问,那么就是一种内存泄露

9.5.3 定期删除

  定期删除是对上述两种方式的一种折衷,没隔一个固定的时间执行一次删除操作,既不会占用太多的CPU时间也不会造成内存泄露。但是要确定好定时删除的间隔和频率。

9.6 Redis的过期键删除策略

  Redis是惰性删除和定期删除结合实现

9.6.1 惰性删除策略的实现

  执行所有Redis操作之前都会先通过一个方法判断该方法想要访问的键是否过期,如果过期那么就直接删除。这种策略像过滤器一样。

9.6.2 定期删除策略的实现

  定时删除策略会按顺序遍历所有数据库,并随机的检查expire中的key-value对,删除其中过期的内容。

  

  

原文地址:https://www.cnblogs.com/AshOfTime/p/10673988.html