近几天看到了一篇面试被虐文,被文中的题目狠狠虐了一遍,感觉到自己的底层知识和基础知识是多么的薄弱,这几天准备填一填文中的一些坑,今天是第一个部分,原题是redis的hash是如何实现的?
很奇怪吧,这个题目从来没有想过,但是想想一下,这和Java中HashMap结构和源码问题一样,对结构的了解确实能带来很大的提升,并不只是一个造火箭的题目。下面好好描述下了解的步骤
Redis里的对象类型
送分题,redis5种数据结构?String、set、zSet、list、hash?
如果你这么回答了,那么你可能会得到一个回答:先回家等消息吧~我们有消息会通知你的。
开个玩笑,不过为什么我会这么说呢?redis的新版本中为我们带来了全新的数据类型,你可以没用到过,但是不可以不知道的。
目前版本描述redis data type的有六个文件t_hash.c
、t_list.c
、t_set.c
、t_string.c
、t_zset.c
、t_stream.c
- hash-哈希结构
- list-链表结构
- set-无需列表
- string-SDS字符串
- zset-有序列表
- stream-流
Redis里的数据结构
在
server.h
文件里描述了所有的数据结构
1 | /* Objects encoding. Some kind of objects like Strings and Hashes can be |
对象类型和数据结构的对应关系
在
server.h
文件里描述了所有的创建关系,散列在各个方法中,这里整理出了一份,并不代表每一种都会用到,每种对象会在不同的情况下选择不同的数据结构,比如String类型在44字符一下会采用EMBSTR方式,以用来节省内存(随版本有变化)。
- OBJ_STRING
OBJ_ENCODING_RAW、OBJ_ENCODING_INT、OBJ_ENCODING_EMBSTR_SIZE_LIMIT
- OBJ_LIST
OBJ_ENCODING_LINKEDLIST、OBJ_ENCODING_QUICKLIST、OBJ_ENCODING_ZIPLIST
- OBJ_SET
OBJ_ENCODING_HT、OBJ_ENCODING_INTSET
- OBJ_HASH
OBJ_ENCODING_ZIPLIST、OBJ_ENCODING_HT
- OBJ_ZSET
OBJ_ENCODING_SKIPLIST、OBJ_ENCODING_ZIPLIST
- OBJ_STREAM
OBJ_ENCODING_STREAM
ZIPLIST和HT
回到原题上,我们已经知道了OBJ_HASH由OBJ_ENCODING_ZIPLIST和OBJ_ENCODING_HT方式实现,
那这两种数据结构有什么异同呢?
OBJ_ENCODING_HT可以用一个dict来表示,可以用hashMap的思想去看,也就是我们常用的字符串,
而OBJ_ENCODING_ZIPLIST则使用了一个压缩列表来放置键值对,数据获取的时候先寻找键所在的位置,
然后用ziplistNext在下个节点里获取值。
redis目前默认创建hash结构的时候使用的是ZIPLIST编码类型,这种类型有什么优点呢?
顾名思义这种类型需要的空间更少,毕竟一个HASH类型组成,至少需要一个dict,
两个dictht。一个dictEntry指针数组和N个dictEntry。
而如果列表中的键值对过多,或者单个键或者值长度过长,就会转换为OBJ_ENCODING_HT方式,
当我了解到这些的时候,还能认为redis操作非常简单么?值得反思。