redis db

struct redisDb {
    dict *dict;                    // 保存键值对的字典
    dict *expires;              // 过期字典,保存数据库中所有键的过期时间,key-dict中的某个键对象,value-long long类型,保存该键过期时间
}
 
每个redisDb表示一个数据库,dbnum决定应该创建多少个数据库,可通过服务器配置的database选项决定,默认16个
 
服务器中保存客户端状态的struct client中保存有一个redisDb指针,表示客户端当前数据库,其指向redisServer.db中的一个元素。可以通过改变struct client中的redisDb指针来切换数据库(即SELECT功能,例如:SELECT 2表示选择2号数据库作为当前数据库)
 
Redis是一个键值对(kv)数据库服务器,其成员dict保存了所有的键值对,称为键空间
 
Redis的过期键删除策略:惰性删除和定期删除相结合
    1.惰性删除策略实现:expireIfNeeded,所有的读写数据库的Redis命令在执行前都会调用。在该函数执行时,如果该键已经过期,则删除;如果没有过期,则该函数不做任何操作
    2.定期删除策略实现:activeExpireCycle。每当Redis的周期操作函数ServerCron函数执行时,便调用一遍activeExpireCycle函数。该函数每次运行时,都选取部分数据库中的部分键进行检查,删除过期键。有一个全局变量current_db记录该次遍历的db编号,下次执行时从该编号开始
 
int expireIfNeeded(redisDb *db, robj *key)  —> db.c文件
    1.在db的expires字典里获取到key的过期时间—>when
    2.获取当前时间—>now。备注:出于一致性考虑,在lua脚本执行的过程中不能删除key,查看github issue #1525
    3.调用propagateExpire函数,TODO: 具体参照replication以及AOF
    4.调用notifyKeyspaceEvent函数,调用通知功能,用于通知相应的客户端,包括键空间通知和键事件通知
    5.删除key
 
int activeExpireCycle(int type) —> expire.c
    1.令dbs_per_call = CRON_DBS_PER_CALL,表示需要遍历多少个db,如果dbs_per_call > server.dbnum,则dbs_per_call = server.dbnum
    2.设置timelimit = ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC * cpu时间,即该次执行最多占ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC的cpu时间
    3.for (j = 0; j < dbs_per_call; j++)循环处理dbs_per_call个db
        1> static int current_db,使用静态变量,便于该次循环访问db的时候,可以保证从上次函数结束的地方开始
        2> db = server.db + (current_db & server_num); current_db++; 获取到要操作的db句柄
        3> do...while(expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP / 4),expired表示该次循环删掉的过期键的数量。如果该次循环所删掉的数量小于单次循环应该删掉的数量 * 25%,则停止该while循环,跳到for循环的下一个元素,即开始操作下一个db。这样做的原理就是:如果每次循环都有一定数量的键删除,则继续循环,处理一次,直到某次处理的过期键数量少于给定的比例(25%)时,跳出循环,操作下一个db
            1) num = min{ dictSize(db->expires), ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP },表示该次循环删除该db下的num个过期键
            2) 循环num次,每次随机选取一个键,如果其已经超时,则调用activeExpireCycleTryExpire函数去删除该键,并统计删掉的过期键的数量—>expired,如果没有过期则不删除
            3) 如果函数总执行时间超过了timelimit,退出函数
 
主从模式下的过期键处理:
    1.客户端在访问从服务器中的某个键时,即使从服务器发现该键已经过期,也不会去做删除,而是继续该操作
    2.主服务器在删除一个键之后,会向从服务器发送DEL命令,从服务器接收到命令后删除该键。
即:所有键的删除都是有主服务器发起的,这样可以保证主从一致
 
数据库通知:(notify.c/notifyKeyspaceEvent函数)
该功能可以让客户端通过订阅来获知数据库中键的变化(通过Publish功能),以及数据库中命令的执行情况,分为两种:
    1.键空间通知(key-space notification),即某个键执行了什么命令
    2.键事件通知(key-event notification),即某个命令被什么键执行了
函数实现:void notifyKeyspaceEvent(int type, char *event, robj *key, int dbid)
    1.参数:
        type-当前想要发送的通知类型
        event-发送的事件的名称
        keys-产生事件的键
        dbid-产生事件的db id
        举例:SADD命令实现中的发送通知:notifyKeyspaceEvent(REDIS_NOTIFY_SET, “sadd”, c->argv[1], c->db->id)
    2.功能:
        1.如果服务器不允许发送该type类型的通知,return
        2.发送键空间通知:令chan = “__keyspace@{bdid}__:{key}”, 将event通过publish实现发送至chan
        3.发送键时间通知:令chan = “__keyspace@{bdid}__:{key}”, 将key通过publish发送至chan
 

转载于:https://www.cnblogs.com/levy5307/p/9668606.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值