|NO.Z.00059|——————————|BigDataEnd|——|Hadoop&Redis.V04|——|Redis.v04|RedisDB结构.v04|结构7种type.v02|
一、字典(重点+难点)
### --- 字典(重点+难点)
~~~ 字典dict又称散列表(hash),是用来存储键值对的一种数据结构。
~~~ Redis整个数据库是用字典来存储的。(K-V结构)
~~~ 对Redis进行CURD操作其实就是对字典中的数据进行CURD操作。
### --- 数组
~~~ 数组:用来存储数据的容器,
~~~ 采用头指针+偏移量的方式能够以O(1)的时间复杂度定位到数据所在的内存地址。
~~~ Redis 海量存储 快
### --- Hash函数
~~~ Hash(散列),作用是把任意长度的输入通过散列算法转换成固定类型、固定长度的散列值。
~~~ hash函数可以把Redis里的key:包括字符串、整数、浮点数统一转换成整数。
~~~ key=100.1 String “100.1” 5位长度的字符串
~~~ Redis-cli :times 33
~~~ Redis-Server : siphash
~~~ 数组下标=hash(key)%数组容量(hash值%数组容量得到的余数)
### --- Hash冲突
~~~ 不同的key经过计算后出现数组下标一致,称为Hash冲突。
~~~ 采用单链表在相同的下标位置处存储原始key和value
~~~ 当根据key找Value时,找到数组下标,遍历单链表可以找出key相同的value

### --- Redis字典的实现
~~~ Redis字典实现包括:字典(dict)、Hash表(dictht)、Hash表节点(dictEntry)。

### --- Hash表
typedef struct dictht {
dictEntry **table; # 哈希表数组
unsigned long size; # 哈希表数组的大小
unsigned long sizemask; # 用于映射位置的掩码,值永远等于(size-1)
unsigned long used; # 哈希表已有节点的数量,包含next单链表数据
} dictht;
~~~ # hash表的数组初始容量为4,
~~~ 随着k-v存储量的增加需要对hash表数组进行扩容,新扩容量为当前量的一倍,即4,8,16,32
~~~ # 索引值=Hash值&掩码值(Hash值与Hash表容量取余)
### --- Hash表节点
typedef struct dictEntry {
void *key; # 键
union { # 值v的类型可以是以下4种类型
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next; # 指向下一个哈希表节点,形成单向链表 解决hash冲突
} dictEntry;
~~~ # key字段存储的是键值对中的键
~~~ v字段是个联合体,存储的是键值对中的值。
~~~ next指向下一个哈希表节点,用于解决hash冲突

### --- dict字典
typedef struct dict {
dictType *type; # 该字典对应的特定操作函数
void *privdata; # 上述类型函数对应的可选参数
dictht ht[2]; # 两张哈希表,存储键值对数据,ht[0]为原生哈希表,
# ht[1]为 rehash 哈希表 */
long rehashidx; # rehash标识 当等于-1时表示没有在rehash,
# 否则表示正在进行rehash操作,存储的值表示
hash表 # ht[0]的rehash进行到哪个索引值
(数组下标)*/
int iterators; # 当前运行的迭代器数量
} dict;
### --- type字段,指向dictType结构体,里边包括了对该字典操作的函数指针
typedef struct dictType {
// 计算哈希值的函数
unsigned int (*hashFunction)(const void *key);
// 复制键的函数
void *(*keyDup)(void *privdata, const void *key);
// 复制值的函数
void *(*valDup)(void *privdata, const void *obj);
// 比较键的函数
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
// 销毁键的函数
void (*keyDestructor)(void *privdata, void *key);
// 销毁值的函数
void (*valDestructor)(void *privdata, void *obj);
} dictType;
### --- Redis字典除了主数据库的K-V数据存储以外,
~~~ 还可以用于:散列表对象、哨兵模式中的主从节点管理等在不同的应用中,
~~~ 字典的形态都可能不同,dictType是为了实现各种形态的字典而抽象出来的操作函数(多态)。
~~~ 完整的Redis字典数据结构:

### --- 字典扩容
~~~ 字典达到存储上限,需要rehash(扩容)
### --- 扩容流程:
~~~ # 说明:
~~~ 初次申请默认容量为4个dictEntry,非初次申请为当前hash表容量的一倍。
~~~ rehashidx=0表示要进行rehash操作。
~~~ 新增加的数据在新的hash表h[1]
~~~ 修改、删除、查询在老hash表h[0]、新hash表h[1]中(rehash中)
~~~ 将老的hash表h[0]的数据重新计算索引值后全部迁移到新的hash表h[1]中,
~~~ 这个过程称为rehash。

### --- 渐进式rehash
~~~ 当数据量巨大时rehash的过程是非常缓慢的,所以需要进行优化。
~~~ 服务器忙,则只对一个节点进行rehash
~~~ 服务器闲,可批量rehash(100节点)
### --- 应用场景:
~~~ 主数据库的K-V数据存储
~~~ 散列表对象(hash)
~~~ 哨兵模式中的主从节点管理
Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
——W.S.Landor
分类:
bdv012-redis
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」