redis的设计与实现(四)——单机数据库特性

1. 前言

我们前面了解了redis的数据结构,对象。但是redis对于这些对象的使用和管理策略需要也熟记于心,这篇文章我们就了解一下吧。

2. 类型检查和命令多态

  • DEL,EXPIRE,RENAME,TYPE,OBJECT 可以对任何数据类型执行
  • SET,GET,APPEND,STRLEN,等只能对字符串执行
  • HDEL,HSET,HGET,HLEN,等只能对哈希键执行
  • RPUSH,LPOP,LINSERT,LLEN,等只能对列表键执行
  • SADD,SPOP,SINTER,SCARD,等只能对集合键执行
  • ZADD,ZCARD,ZRANK,ZSCORE,等只能对有序集合键执行

如何实现的类型检查?

  1. 在执行llen命令之前,确保对象内type是不是命令对应类型
  2. 如果是的话就执行
  3. 否则就返回上图类型错误

如何实现通用命令多态?

  • 实际上不仅是通用命令是多态,像llen也是多态实现,由于列表底层可以是压缩列表或者或链表,所以获取元素数量的内置操作是不同的。
  • 所以内部会进行if操作,如果是ziplist就执行ziplistLen如果是链表就使用listlength获取长度

而这些通用命令也是一样的思路。

3. 内存回收策略

c 语言不具备内存回收功能,所以redis自行实现了,内存回收。使用的策略是引用计数策略 和 jvm 的可达性分析不一样。

  • 当创建一个对象的时候,引用数设置为1
  • 当被一个新程序使用的时候,引用数加1
  • 不被一个程序使用的时候,引用数减1
    对象的生命周期包括:创建对象,操作对象,和释放对象

4. 对象共享

对象共享的目的是节约内存,实际上和 java 语言类似。

redis内部已经实现了这些,但是我们理解内部过程对于熟练使用redis极为重要。

  • redis 在初始化的时候会创建1w(0-9999)个整数字符串

    我们可以看到1这个证书字符串,居然整数1被引用率2147483647之多。这种思路在java中integer有点类似,integer在创建之初就有-128-127的缓存。

另外,这些共享对象不单单只有字符串键可以使用,那些在数据结构中嵌套了字符串对象的对象(linkedlist编码的列表对象、hashtable编码的哈希对象、hashtable编码的集合对象,以及zset编码的有序集合对象)都可以使用这些共享对象。

5. 对象空转时长

redisObject中还有最后一个属性,lru,长度为22字节

这个属性记录了上次使用时间,当前之间减去lru可以计算出空转时长

如果服务器打开了maxmemory选项,并且服务器用于回收内存的算法为volatile-lru或者allkeys-lru,那么当服务器占用的内存数超过了maxmemory选项所设置的上限值时,空转时长较高的那部分键会优先被服务器释放,从而回收内存

6. 数据库

  1. redisDb *d保存着redis中所有数据库
  2. redis会根据dbnum决定数据库创建的数量,默认是16.
  3. 通过select可以选择数据库

    redisClient中*db记录了当前数据库
  4. reids 全数据字典

    redis所有的数据都是key-value,redisDb数据结构中,dict中保存了所有数据的key-value。如果添加数据,就是向dict中添加值。

6.1. 过期键的删除策略

过期时间并非保存在对象内,而是另外开了一个字典exoires,专门用于保存对象的生存时间。好处是集中处理更便捷。

  • 定时删除
    使用定时器定期对对象删除
  • 惰性删除:
    等读取时,进行过期判断
  • 定期删除:
    使用定时器,不过限制删除的时间,相当于降低了延迟,降低了吞吐,是一个中庸的方法。

6.2. rdb和aof对过期键的处理

  1. rdb不保存处理
    如果rdb存储键值的时候会对过期键进行过期检查,只有非过期的键才会保存持久化。
  2. aof的不理睬处理
  • aof一般情况下并不会关系键是否过期,因为aof跟踪数据库状态,除非系统处理过期键,然后aof会追加和系统相同的删除命令。
  • 当然,如果aof进行了重写,这时候的思路就和rdb类似,会对过期键理睬,只保存不过期的键,因为aof重写本身就是一个类rdb的行为。
相关推荐
掘金-我是哪吒10 分钟前
分布式微服务系统架构第109集:HTTP缓存优化,Nginx 代理配置,蓝绿部署, Jenkins一键切流脚本
分布式·http·缓存·微服务·系统架构
Mikey_n13 分钟前
NoSQL入门指南:Redis与MongoDB的Java实战
数据库
forestsea1 小时前
全解:Redis RDB持久化和AOF持久化
数据库·redis·缓存
叫我DPT1 小时前
分享一个python启动文件脚本(django示例)
数据库·python·django
小五Z2 小时前
Redis--事务
redis·分布式·后端·缓存
XXYBMOOO2 小时前
基于 Qt 的 BMP 图像数据存取至 SQLite 数据库的实现
数据库·c++·qt
Sunlight_7772 小时前
第五章 SQLite数据库:1、SQLite 基础语法及使用案例
java·linux·服务器·jvm·数据库·tcp/ip·sqlite
JhonKI2 小时前
【从零实现高并发内存池】内存池整体框架设计 及 thread cache实现
java·redis·缓存
嘉嘉king2 小时前
Mysql联表查询
数据库
镜舟科技3 小时前
NoSQL 与 NewSQL 全面对比:如何选择适合你的数据库方案?
数据库·starrocks·nosql·newsql·技术架构·实时数据分析