Redis的字符串类型

原由

今天面试惨败,面试官问了不到10个问题就让我出来写题了……对其中的一个题目印象深入:c++

Redis获取字符串长度的复杂度是多少?

刚开始我是一脸懵逼的,由于不清楚Redis的字符串类型是怎么实现的,因此彻底无法答下去了……回来后立刻开始学习。面试

字符串类型

字符串是Redis里很是常见的类型,而用C实现的RedisJava不同。在C里字符串是用长度为N+1的字符数组实现的,且使用空字符串'\0'做为结束符号。获取字符串的长度须要遍历一遍,找到空字符串'\0'才知道字符串的长度,复杂度是O(N)数据库

若是有一个长度很是大的字符串,单线程的Redis获取它的长度就可能会阻塞好久,这是不能接受的,因此Redis须要一种更高效的字符串类型。数组

SDS

Redis实现了一个叫SDS(simple dynamic string)的字符串类型,其中有两个变量来分别表明字符串的长度和字符数组未使用的字符数量,这样就能够用O(1)的复杂度来获取字符串的长度了,并且一样也是使用空字符串'\0'做为结束符号。学习

struct sdshdr {
    // 字符串长度
    int len;
    // 字符数组未使用的字符数量
    int free;
    // 保存字符串的字符数组
    char buf[];
}

如今已经能够回答上面的面试题了,实际上是很是简单的一个问题,怪不得答不出来面试官立刻就说面试结束了……优化

扩容机制

SDS在字符数组空间不足于容纳新字符串的时候会自动扩容。ui

若是把一个C字符串拼接到一个SDS后面,当字符数组空间不足时,SDS会先扩容到恰好能够容纳新字符串的长度,而后再扩充新字符串的空字符长度,最终SDS的字符数组长度等于 2 * 新字符串 + 1(结束符号'\0')。不过当新字符串的大小超过1MB后,扩充的空字符长度大小会固定为1MBspa

之因此会有这个机制,是由于Redis做为一个NoSQL数据库,会频繁的修改字符串,扩容机制至关于给SDS作了一个缓冲池。把SDS连续增加N次字符串须要内存重分配N次优化成了SDS连续增加N次字符串最多须要内存重分配N次,这其实和Java里的StringBuilder实现思想是同样的。线程

后记

此次翻车是有缘由的,我看过两本关于Redis的书,里面都是讲Redis如何实战的可是并无讲Redis的设计和实现。这也就致使了面试很尴尬,由于面试官最喜欢问原理相关的东西了,因此之后学习技术的时候不要从实战类的书籍开始了,仍是先看懂原理比较好。设计

参考资料

这是《Redis设计与实现》里字符串一节的总结。

相关文章
相关标签/搜索