redis的key 底层都是String
C语言标识字符串:
char data[] = “Strig\0” : \0结尾标识
redis定义的字符串类型
len:6
char buf[] = “string\0jaa”
依据len长度取值,
1:二进制安全的数据结构
2:提供内存预分配机制,避免频繁内存分配
3:兼容C语言函数库
后面会加上\0
free: buff还有多少可用空间
key扩容
成倍的扩容
(len + addlen ) 2
append命令
setbit命令涉及 key扩容
*长度=1024时,只会成倍扩容
String
数据结构
// redis 3.2 以前
struct sdshdr {
int len;
int free;
char buf[];
};
3.2提供了5种区分不同的长度,应对不同的场景
typedef char *sds;
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len; /* used */
uint16_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
........
#define SDS_TYPE_5 0
#define SDS_TYPE_8 1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
static inline char sdsReqType(size_t string_size) {
if (string_size < 32)
return SDS_TYPE_5;
if (string_size < 0xff) //2^8 -1
return SDS_TYPE_8;
if (string_size < 0xffff) // 2^16 -1
return SDS_TYPE_16;
if (string_size < 0xffffffff) // 2^32 -1
return SDS_TYPE_32;
return SDS_TYPE_64;
}
key
value:
: String ,hash set ,sorted set list
map —> dict
数据库:海量数据的存储
redis 使用了下面两种数据结构
1:数组: O(1)
2:链表:O(n)
hash(key) -> 自然数 %4 获取 arr的坐标值
1:任意仙童的输入,一定得到相同的输出
2:不同的输入可能会有相同的输出
hash碰撞
解决方案:链表法 类型hashmap,开放地址法(用的少)
redisDb
typedef struct redisDb {
dict *dict; // key -value
dict *expires; //过期时间
dict *blocking_keys;
dict *ready_keys;
dict *watched_keys;
int id;
long long avg_ttl;
unsigned long expires_cursor;
list *defrag_later;
} redisDb;
typedef struct dictEntry {
void *key; // 指针,sds对象
union { // 值,只会用到下面的一个
void *val; //执行一个value 对象 执行不同的类型,执行任意对象,redisObject
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next; //链表,hash冲突时
} dictEntry;
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx;
unsigned long iterators;
} dict;
typedef struct redisObject {
unsigned type:4; //标识value对象类型,string,hash,约束value类型
unsigned encoding:4; //底层编码:命令: > Object
unsigned lru:LRU_BITS;
int refcount; //: 对象引用,回收用的
void *ptr; //value的真实内存指向
} robj;
typedef struct dictht {
dictEntry **table;
unsigned long size; //hashTabl容量
unsigned long sizemask; = size-1 求模用
unsigned long used;
} dictht;
扩容不是一次全部都转移,而是分批次的
String结构
embstr嵌入式string 45一下
raw类型 45以上
bitmap
一亿级日活统计,
key: 日期
value : offset
setbit key offset 0/1 setbit a-bit-map 0 1 对key a-bit-map 的第0 位设为1
bitcount a-bit-map 统计bit=1的个数 bitcount a-bit-map 0 12 统计0-12范围的位等于1的个数
bitcount and login-11-5-6 login-11-
bitop and newkey login11-5-6 login11-5-7 把后面的key 位与运算存在new key中 然后在 bitcount newkey 得到位1的总算 bitop or newkey key1 key2 然后在 bitcount newkey 统计