Redis的实现

66 阅读3分钟

Redis的数据库是由hashtable实现的,在Redis中,相同的桶存储着哈希值相同的值。当Redis数据库存储数据时,会先对键进行哈希运算,然后根据哈希值确定存储位置,即确定存储在哪个桶中。如果哈希值相同,那么它们会被存储在同一个桶的位置上,通常使用链表法来解决哈希冲突。链表中的每个节点都包含键值对,这样可以存储多个键值对在同一个桶中。如果哈希值相同,也会存储到同一个桶上,每个桶的值都是键值对的集合,其中键是唯一的,值是与键对应的数据。所以,不同的数据类型在不同的桶中存储,桶的值就是键值对的集合,其中键是唯一的,值是与键对应的数据。相同的话则使用这种设计使得Redis能够高效地存储和检索不同类型的数据。 rehash(渐进地扩容)

  1. Redis会创建一个新的更大的哈希表,通常是当前哈希表大小的两倍。 2. 然后,Redis会按照一定的顺序,逐个将原哈希表中的键值对重新哈希并存储到新的哈希表中。这个过程称为rehash。 3. 在rehash过程中,Redis会通过增加新的桶,将键值对均匀地分布到新的哈希表中,以保持较低的负载因子。 4. 当所有键值对都被重新哈希到新的哈希表后,Redis会将新的哈希表替换原来的哈希表,完成扩容过程。 在rehash过程中,Redis会在原哈希表和新哈希表之间进行渐进式的迁移,以避免对系统性能产生较大的影响。在此期间,Redis会同时维护原哈希表和新哈希表,以确保数据的一致性。 SDS做的优化 1:使用char类型来存储数据的长度,一个char类型为一个byte,一个byte有8个bit,3 bit来存储数据类型和5来存 数据长度的。 2、老版本free字段新版本alloc字段。free字段是当前buffer的空闲长度。buufer长度=当前使用长度+空闲长度。遇到扩容的时候,如果大小为8则扩容到16也就是扩大到(原来的+新增的)*2.新版本的alloc就是数组的长度,老版本是free+buffer=16 redis的key是任意数据类型 redis数据库实现: 本质就是两个hashtable,采用渐进式的方法扩容rhash就是两个复制。底层类型的话,用string就是string,用zset就是zset,不同的是底层编码的区别,redis是键值,value就是redisobject。里面有几个类型就是type(数据类型)、encoding(编码格式)、lru(淘汰算法)、ptr(存储指针) redisdb下面先是字典,字典下面是hashtable,扩容的时候先扩大到原来两倍,新的接收到数据后进行转移。老的table转移完成后清空,然后指针指向新数组,新table指向null.hashtable下面是个redisobject.sss string的编码格式主要是根据长度决定的。原理如下: 存储的键都是redisobject,sds是基于redisobject实现的,平时我们拿一个cacheline大概是64字节,redisobject大概占了16个字节,里面有数据类型、编码类型、淘汰算法类型、存储指针。sds在他的基础上增加了4个字节的存储,有alloc、数据现在长度、char[]buffer,和一个char类型,char类型的话用来存储数据的长度和类型,一个char类型为8个bit,3个bit存储数据类型,5个bit存储的是长度,于是一个cacheline被瓜分剩下44个字节,这44字节开发者希望利用起来存储,小于44的话就是embstr,大于的话就是raw。