内存数据保存状态
redis服务器将所有数据库都保存在redis.h/redisServer结构中的db数组中,db数组中的每一项都是redis.h/redisDb结构,而redisDb就是一个数据库的底层表现形式。
struct redisServer{
//····
//数组形式的,保存着redis服务器中的所有数据库,一般为16个,可以通过dbnum来指定
redisDb *db;
int dbnum;
//···
}
redis服务端会保存每个客户端的状态属性,其中也包括客户端使用的目标数据库,一般默认使用0号数据库,可以通过select命令进行切换。
struct redisClient{
//......
//记录客户端当前正在使用的数据库
redisDb *db;
//......
}redisClient;
redis是一个键值对数据数据库服务器(key-value pair),在redisDb结构的dict字典中保存了一个数据库下所有的键值对,我们称之为键空间(key space)
typedef struct redisDb{
dict *dict;//数据库键空间
dict *expires;//过期管理字典
dict *wathcd_keys;//实现watch,用于事物
struct evictionPoolEntry *eviction_pool;//内存不足是,用于LRU算法回收
//......
}redisDb;
需要注意两点,
1、键空间的键都是字符串对象
2、键空间的值可以是字符串对象、列表对象、哈希表对象、集合对象和有序对象中的任意一种。
每一个对象都对应着一个redisObject
typedef redisObject{
unsigned type; //无符号类型
unsigned encoding;//编码
void *ptr;//指针,指向底层数据实现的指针
unsigned lru;//实现LRU算法
int refcount;//引用计数
}robj;
持久化数据保存形式
redis的数据持久化包括RDB和AOF两种。RDB适用于全量备份,AOF适用于增量备份。
RDB因为是定时备份的所以不一定具有完整数据,但是因为底层是通过二进制的形式来保存键值对数据,所以redis服务启动时,加载到内存的速度更快。
AOF则是相当于将原始命令保存到AOF文件中,数据加载的过程相当于是所有命令的重新输入生效的过程,虽然之后也有aof_rewrite的实现方式,但是加载到内存的速度还是不如RDB,但是AOF的优点在于他是实时的。RDB文件只能备份最后一次save/bgsave的数据,如果距离最后一次备份时间过久,丢失数据越多。
当开启AOF的时候有限AOF加载数据。
RDB的底层文件结构。
[redis][db_versiong][databases][EOF][check_sum]
1、5个字节长度的5个reids字符,用于快速检查该文件是否是RDB文件
2、4个字节长度的RDB文件版本
3、databases包含任意个数据库,以及数据库中的键值对数据
4、一个字节长度的结束标记符号
5、8个字节长度的无符号整数,该值前面4个部分的算法校验和,以此来检查RDB文件是否损坏
redis字符 | RDB文件版本 | select | db_number数据库号码 | pairs键值对数据 | 任意多个数据库及其键数据 | EOF结束符 | check_num校验和 |
redis | db_version | select | 0 | pairs | … | EOF | check_num |
其中pairs保存的是所有键值对数据,以Type、key、value的格式保存、如果有过期时间则是EXPIRETIME_MS、ms、TYPE、key、value