看完这个还不了解redis的SDS,半夜你来扒我家墙头

Posted king哥Java架构

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了看完这个还不了解redis的SDS,半夜你来扒我家墙头相关的知识,希望对你有一定的参考价值。

概述:

我们都知道redis底层是用C语言实现的,而C的字符串是以‘\\0’来判断结束的,是一个对特殊字符存储不安全的。那redis是怎么做到存储二进制安全的呢?

重头戏-redis中的字符串

redis中还是有用到C中字符串的地方,比如一些不需要修改的字面量一些reids要输出的日志信息等。而需要修改的字符串redis抽象成了我们的SDS对象:简单动态字符串(simple dynamic string,SDS)。这部分的源码对应在这两个文件中

sds.h

sds.c

SDS的定义

每个 sds.h/sdshdr 结构表示一个 SDS 值,结构如下:

struct sdshdr {

    // 记录 buf 数组中已使用字节的数量
    // 等于 SDS 所保存字符串的长度
    int len;
    // 记录 buf 数组中未使用字节的数量
    int free;
    // 字节数组,用于保存字符串,
    char buf[];

}; 

我们的buf中存放的就是我们真正的按照\\0结束的字符串内容(在3.2版本之后此处改成了一个指针会根据不同长度指向不同的结构),len是我们的字符串内容的长度。还可以看到有一个free的子段,这个子段的作用先卖个关子下边说

如果你觉得自己学习效率低,缺乏正确的指导,可以加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
[Java架构群]
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的JAVA交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

SDS中free的作用

在c语言中使用不当经常会有内存溢出的问题,导致我们的字符串被覆盖,而redis是怎么避免这种问题的出现的呢?

首先我们在redis中插入一个key:

> set demo hello;

这个时候的SDS对象是:

struct sdshdr {
    int len; = 5
    int free; = 0
    char buf[]; = 'hello'

}; 

> set demo ‘hello world’;

这个时候的SDS对象是:

struct sdshdr {
    int len; = 11
    int free; = 11
    char buf[]; = 'hello world'

};
> set demo 'hello world wang';
struct sdshdr {
    int len; = 16
    int free; = 6
    char buf[]; = 'hello world wang'

}; 

我们在set hello world之后 redis会根据我们的free子段去判断需不需要向操作系统申请内存,如果free够用则不申请。这个时候就涉及到redis的内存分配策略了,为了避免多次向操作系统申请内存的开销,redis在每次申请都会按照当前len的两倍去申请(当len于1M时候就只会多申请1M),也就可以解释我们的free为什么是11了,这就是redis的空间预分配。

我们可以看下redis-5源码涉及到内存分配的策略,扩容是这个方法XDM可以去看看 sds sdsMakeRoomFor(sds s, size_t addlen)

还有一个惰性空间释放的概念会涉及到我们的free子段,当我们将redis的字符串内容减少的时候,redis并不会立马释放内存而是仅仅修改free子段,以便下次使用。

总结

  • 因为SDS有存储字符串长度len,所以我们获取redis字符串长度是一个O(1)的操作。
  • len的存在避免了内存溢出的问题
  • 通过内存分配策略,减少了字符串修改时候的内存分配次数

最后

给大家分享一篇一线开发大牛整理的java高并发核心编程神仙文档,里面主要包含的知识点有:多线程、线程池、内置锁、JMM、CAS、JUC、高并发设计模式、Java异步回调、CompletableFuture类等。

文档地址:一篇神文就把java多线程,锁,JMM,JUC和高并发设计模式讲明白了

码字不易,如果觉得本篇文章对你有用的话,请给我一键三连!关注作者,后续会有更多的干货分享,请持续关注!

以上是关于看完这个还不了解redis的SDS,半夜你来扒我家墙头的主要内容,如果未能解决你的问题,请参考以下文章

了解下Redis的SDS结构

看完这篇还不懂链表你来打我

看完这篇还不懂线程与线程池你来打我

看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)

还不懂Redis?看完这个故事就明白了!

还不懂 Redis?看完这个故事就明白了