前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一起来学redis-数据库属性

一起来学redis-数据库属性

作者头像
六个核弹
发布2022-12-23 21:22:26
3920
发布2022-12-23 21:22:26
举报

redis数据库结构介绍

在redis源码中数据库的结构由server.h/redisDb表示, redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间(key space),redisDb源码:

代码语言:javascript
复制
typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
} redisDb;

源码中redisDb拥有字典属性dict,字典中存储了数据库中的键,为字符串类型的redisObject。这个redisObject中的ptr属性指向值的redisObject,结构示意图:

键空间的维护

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

  1. 在读取一个键之后(读操作和写操作都要对键进行读取),服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数,这两个值可以在INFO stats命令的keyspace_hits属性和keyspace_misses属性中查看。
  2. 在读取一个键之后,服务器会更新键的LRU值,关于这个值我们在上一章节已经介绍过了;
  3. 如果有客户端使用WATCH命令监视了某个键,那么服务器在对被监视的键进行修改之后,会将这个键标记为脏(dirty),从而让事务程序注意到这个键已经被修改过
  4. 如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知

键的过期时间

通过EXPIRE命令或者PEXPIRE命令可以设置键的过期时间,那么在数据库中这个过期时间是怎么维护的呢?

redisDb结构体中有一个字典属性expires便是用来保存键的过期时间的, 我们称这个字典为过期字典。过期字典的键是一个指针,指向键空间中的键;过期字典的值是一个long类型的数,记录了过期时间的时间戳。当客户端执行PEXPIREAT命令,服务器会在数据库的过期字典中关联给定的数据库键和过期时间。

如果现在给key设置一个过期时间,在过期时间到的时候,Redis是如何清除这个key的呢?Redis 中提供了三种过期删除的策略:

  • 定时删除:在设置某个 key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作;
  • 惰性删除:当一个键值对过期的时候,只有再次用到这个键值对的时候才去检查删除这个键值对;
  • 定期删除:采样一定个数的key 判断过期比例,并删除过期键,当过期比例不达标则重新采样删除,直到达标。

Redis 中实际采用的策略是惰性删除加定期删除的组合方式,服务器会定期清除掉一部分过期的key,对于那些未清除到的过期key,会在获取这个key的时候进行判断是否过期,过期则删除。惰性删除会带来一个问题就是当从从库获取一个过期key的时候从库是否应该删除这个key呢?

如果一个主库创建的过期键值对,已经过期了,主库在进行定期删除的时候,没有及时的删除掉,这时候从库请求了这个键值对,当执行惰性删除的时候,因为是主库创建的键值对,这时候是不能在从库中删除的。从库会通过惰性删除来判断键值对的是否过期,如果过期则读不到这个键,真正的删除是当主节点触发键过期时,主节点会同步一个del命令给所有的从节点。

我们知道redis 持久化策略中包括RDB持久化功能、AOF持久化,这两种持久化对过期未删除的键处理也是有区别的。RDB持久化不会保存过期未删除的键,而AOF持久化当过期键被惰性删除或者定期删除之后,程序会向AOF文件追加一条DEL命令,来显式地记录该键已被删除。

阻塞

在 Redis 命令中,有一些命令是阻塞模式的,BRPOP, BLPOP, BRPOPLPUSH, 这些命令都有可能造成客户端的阻塞。

比如向客户端发来一个blpop key命令,redis先找到对应的key的list,如果list不为空则pop一个数据返回给客户端;如果对应的list不存在或者里面没有数据,就将该key添加到redisDb 的blockling_keys的字典中,value就是想订阅该key的client链表。并将对应的客户端标记为阻塞。

如果客户端发来一个repush key value命令,先从redisDb的blocking_keys中查找是否存在对应的key,如果存在就往redisDb的ready_keys这个链表中添加该key;同时将value插入到对应的list中,并响应客户端。redis处理完客户端命令后都会遍历ready_keys和blockling_keys来筛选出需要pop出的clinet。

因此,redis客户端的阻塞是通过ready_keys和blockling_keys联合来实现的,blockling_keys 记录阻塞中的key和客户端,ready_keys记录数据已准备好的key。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 六个核弹 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • redis数据库结构介绍
  • 键空间的维护
  • 键的过期时间
  • 阻塞
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档