概述

redis在大部分时候,被用作缓存,用于加快查询速度。但其适用范围,不仅仅限于缓存,比如用户关系的存储:求两个用户的共同关注好友。就可以使用redis的列表类型求交集来完成,操作简单、高效。 之前看过一本《redis开发与运维》,里面讲的是如何使用redis,对于redis如何管理(运维)。对于没接触过redis的人,可以通过那本书入门上手。最近在看《redis设计与实现》,这本书里讲的是原理层面的内容,适用于充分理解其解决问题的思路。 我希望通过这篇总结,可以讲清楚,为啥redis这么快,如何实现的。

字符串

redis是用C语言实现的,其基本的5中数据结构中,字符串是最简单的。后续支持的地理位置,出了LBS相关业务,其他的基本用不上。 KV结构中,字符串这种数据结构,redis依托于C语言,有自己的实现:简单动态字符串(simple dynamic string SDS),其数据结构有三个元素:len(字符串长度),free(未使用空间),buf(实际字符数组)。

buf数组,实现仍然是参考C语言,这样可以使用一部分C语言的字符串库函数。也就是说:以\0表示字符串结尾。但是len统计长度的时候,是不包含\0这一字节的。

SDS解决了C语言字符串的两个问题:1 获取字符串长度代价高;2 无法自动扩展;3 无法保存带有\0格式的二进制数据

优势1:获取字符串长度的时候,仅仅访问其len属性即可得到。而C语言的字符串需要遍历,才能获取到。

优势2:防止出现缓冲区溢出。C语言字符串在执行/strcat函数的时候,会把一个字符串B拼接到另一个字符串A的尾部,当A字符串没有足够剩余空间的时候,就会覆盖其他内容。redis字符串首先会检查A字符串剩余空间的长度,如果不够,则为其重新分配充足的内存,以便容纳B字符串。

优势3:可以保存任意格式的二进制数据,而非仅仅文本数据。(就算数据有\0也能保存)

分配空间的时候,使用“预分配”和“惰性释放”两个策略,减少分配内存操作次数,降低耗时。

链表

链表的底层实现用的是/listNode

字典

字典的底层实现用的是/dictht