Redis的存储结构
RedisDB:代表一个数据库对象;存储了当前库下所有数据;
typedef struct redisDb{ // 键空间:存储了当前库的所有的键值对 dict *dict; // 过期字典:存储了设置了过期时间的key及其过期时间 dict *expires; //... } redisDb;
Hash Table:DB内的键空间;
typedef struct dict{ // 指向对哈希表操作的函数 dictType *type; // 私有数据 void *privdata; // ht[1]指向真正的哈希表结构,ht[2]用于备用扩容,指向正在扩容的哈希表 dictEntry **ht_table[2]; // rehash标志位,标识是否在rehash:如果不在rehash,此值为-1; // 当rehash开始,用trehashidx来记录索引 int trehashidx; } // 实际存储Redis的键值对 struct dictEntry { void *key; union { void *val; uint64_t u64; int64_t s64; double d; } v; // 同一个桶下的下一个key struct dictEntry *next; void *metadata[]; };
RedisObject:是Redis所有数据类型的抽象基类,每一个Redis键值对都是一个RedisObject;
typedef struct redisObject{ //类型 STRING、LIST、SET、HASH、ZSET unsigned type:4; //编码 RAW、INT、EMBSTR unsigned encoding:4; //指向底层数据结构的指针 void *ptr; //引用计数 RedisObject 被多个键所共享时,引用计数会增加 int refcount; //记录最后一次被程序访问的时间戳,用于实现 LRU 缓存淘汰策略 unsigned lru:22; }robj
Redis Datastructure and Command
1. string
String data structure in Redis is a simple key-value pair. It can be used to store integer, text string and Json string.
底层为c语言可变长的动态字符数组(char数组),容量最大512MB;
- 时间复杂度O(1):直接根据len,通过索引获取字符串;
- 杜绝缓冲区溢出,动态扩容预分配内存;
- 二进制安全,按长度读取,而非c语言的字符串按照结束标识("\0")判断;(可能被存储的特殊字符误判)
struct __attribute__ ((__packed__)) hisdshdr8 { uint8_t len; /* buf已使用长度 */ uint8_t alloc; /* buf总大小 */ unsigned char flags; /* 标识当前的sds类型:5、8、16、32、64 */ char buf[]; /* 存储字符数组 */ };
Commnad:
- SET/GET: used to set / retrieve a key-value pair. If the value does not exsit,nilis returnd.
- MSET/MGET: set / get multiple key-value pair in one operation in the order they are requested. If the value does not exsit,nilis returnd for that key's position.
- INCR/DECR: increment / decrement the value of a key that stores an integer.
2. Hash
A hash data structure in Redis is a collection of key-value pairs. It is like a dictionary or a map in programming languages. It is useful for storing objects with multiple fields.
- 相比于string类型不需要存储于json中的符号,存储相同的内容,占用空间更少;
- 可以单独操作每个字段,比较灵活;
- 哈希冲突使用链地址法解决;
- 扩容采用渐进式rehash;
- 传统扩容:一次性拷贝数据到重新分配的内存,这样会在数据量比较大时,消耗大量CPU资源、造成响应延迟、阻塞等情况;
- 渐进式Rehash:逐步被动的迁移数据,在迁移完成后释放原有内存;
- 适用场景:对象、实体缓存;
Command:
- HSET/HGET:HSETis used to set a field-value pair inside a hash.HGETretrieves the value of a specific field in a hash.
- HMSET/HMGET: allows you to set multiple field-value pair and retrieves values of multiple fields.
- HDEL: used to delete one or more fields from a hash.
3. List
A list data structure in Redis is an ordered collection of strings. It can be used to store a sequence of values. The elements in a list are ordered, and you can access them by index.
- list是一个双向链表,支持正反向查找、索引查找、左右pop等;
- 支持阻塞pop,当列表为空,pop阻塞;可以充当阻塞队列使用(Redis5.0之后使用stream作为消息队列);
- 支持索引查找、范围查询、支持重复的元素;
- 适用场景:消息队列、存储列表;
Command:
- LPUSH/RPUSH: allow you push one or more elements to the left / right of a list.
- LPOP/RPOP: allow you pop one or more elements from the left / right of a list.
- LRANGE: retrieves a range of elements from a list.
4. Set
A set in Redis is an unordered collection of unique strings. It is used to store a group of distinct values. It can store
- 无序、唯一、自动去重;
- 适用于:标签、关键字等唯一性场景;
- 使用场景:点赞、关注列表、粉丝列表、抽奖;
Command:
- SADD/SMEMBERS:SADDadds one or more members to a set. andSMEMBERScan retrieve all the elements of a set.
- SREM: removes member from a set.SREM myset "member1"
- SISMEMBER: checks if a given value is a member of a set.
5. Zset(Sorted Set)
A sorted set in Redis is a collection of unique members, each associated with a score. The members are stored based on their scores in ascending or descending order. It is useful for ranking systems.
- 排序集合,自动去重,在set的基础上增加score权重进行排序;
- 应用:排行榜、点赞、延迟队列;
Command:
- ZADD: adds one or more members with their scores to a sorted set.ZADD myzset 1 "member"adds "member" with a score of 1 tomyzset.
- ZRANGE: retrieves a range of members from a zset by scores.ZRANGE 0-30returns all the elements of the zset.
- ZREM: removes one or more members from a zset.
- ZRANK/ : get the rank of a member.ZRANK myzset "member1"returns the position of"member1"in themyzsetsorted set.
- ZREVRANK: get the descending order of score.
Common Commnad
- EXISTS key [key1, key2]: checks if one or more keys exist.
- DEL key [key1, key2]: deletes one or more keys.
Redis的key寻址
- 集群状态下,先使用hash slot算法找到key存放的节点;
- hash槽的总大小是固定的16384;
- 根据key的落点,可以找到key所在的集群节点;
- 客户端向此节点发起查询请求;
- 对key进行hash取模,找到对应的值;