一.Redis为什么快
高速的存储介质
机械硬盘—>固态硬盘—>内存,随机访问的延迟逐渐变小
优良的底层数据结构设计
底层设计用到了hashtable,时间复杂度低
高效的网络IO模型
epoll等,不同平台有不同的实现
高效的线程模型
二.Redis的HashTable
hash值的计算公式:
hash(key) % hashtable.size() 取模得到一个index索引,然后把entry存进去
三.Redis的渐进式ReHash
当HashTable的某个key中链表的节点个数,大于HashTable的size,就会触发扩容。
扩容的时候,因为不能卡顿,所以不会一次性把所有hash槽的内容都挪到新的空间,而是渐进地搬运。redis会维护两个HashTable,首先访问老的,如果老的没有会去新的HashTable访问,有新的元素加进来,放到新的HashTable
四.Redis的Key类型是什么
可以是任意的数据类型,不管传什么类型,都会转成redis的string字符串类型
五.Redis的String
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[];
};
首先,根据数据长度的不同,有很多种sdshdr的实现,从5一直到64,就是bit位数量有区别。
而且,每次扩容的时候,假设size从6变成7,那么申请2x7=14的空间,
六.Redis的数据库设计
/* */
typedef struct redisDb {
dict *dict; /* db的keyspace也就是kv对的结构 */
dict *expires; /* 过期时间 */
dict *blocking_keys; /* 阻塞的API (例如BLPOP)*/
dict *blocking_keys_unblock_on_nokey; /* Keys with clients waiting for
* data, and should be unblocked if key is deleted (XREADEDGROUP).
* This is a subset of blocking_keys*/
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 */
unsigned long expires_cursor; /* Cursor of the active expire cycle. */
list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */
clusterSlotToKeyMapping *slots_to_keys; /* Array of slots to keys. Only used in cluster mode (db 0). */
} redisDb;
然后看一下关键的字典对象dict
struct dict {
dictType *type; //字典类型
dictEntry **ht_table[2]; //ht就是hashTable, 这里有两个一个是新的一个是老的
unsigned long ht_used[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
/* Keep small vars at end for optimal (minimal) struct padding */
int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */
signed char ht_size_exp[2]; /* exponent of size. (size = 1<<exp) */
void *metadata[];
};
下面看一下dictType
typedef struct dictType {
uint64_t (*hashFunction)(const void *key); //hash函数
void *(*keyDup)(dict *d, const void *key);
void *(*valDup)(dict *d, const void *obj);
int (*keyCompare)(dict *d, const void *key1, const void *key2);
void (*keyDestructor)(dict *d, void *key);
void (*valDestructor)(dict *d, void *obj);
int (*expandAllowed)(size_t moreMem, double usedRatio);
//其他省略
} dictType;