Redis面试都卷到C语言去了。。。

news2024/9/20 10:36:51

Redis 面试都卷到 C 去了。有个小伙伴在前两天找松哥模面的时候如是说到。

是啊,没办法,自从 Java 八股文这个概念被提出来并且逐步在 Java 程序员中强化之后,现在各种各样的八股文手册,有免费的有付费的,琳琅满目。

单纯的八股文已经区分不出 Java 猿水平的高低了,所以现在面试总会卷出新高度。

这次是小伙伴面试时候被问到一个 SDS 的问题,也就是 Redis 中 String 字符串的底层实现原理。

我来和小伙伴们简单聊一聊这个话题。

一 String 类型

Redis 中有一个 String 类型,使用频率还比较高,我们日常做缓存、分布式锁都会用到。

很多小伙伴也都知道 Redis 是用 C 写的,那么就有一个问题,Redis 中的 String,底层数据结构是什么样的?

是不是就是 C 中的 String 呢?

二 C 中的 String

玩过 C 的小伙伴应该知道,C 语言本身并没有内置的 String 类型,但是 C 语言中可以使用字符数组(char array[])或指向字符的指针(char *pointer)来表示字符串。在 C 语言中,字符串是以空字符 '\0' 结尾的字符序列。例如:

char *str1 = "Hello, World!";

在这个例子中,str1 是一个指向字符串字面量 “Hello, World!” 的指针。

当我们在 Redis 中使用 String 的时候,很多小伙伴可能会想这个 String 可能就是 C 中的 String 吧?并不是!

为什么不直接使用 C 中的 String 呢?主要有以下几种考虑:

  1. char* 这种方式无法直接获取到字符串的长度,只能逐个字符去遍历,很明显效率低。
  2. C 中的字符串使用 \0 去表示字符串结束,这就导致我们没法在字符串中存储二进制数据,因为二进制中的数据可能会和 \0 冲突。
  3. C 中字符串在创建的时候长度和内存大小就都确定下来了,后期如果缩容和扩容都是创建新数组然后拷贝内容,操作方式过于麻烦。

有鉴于此,Redis 自己搞了个 SDS,全称是 Simple Dynamic String。这个 SDS 和 C 中的字符串的关系,有点像我们 Java 中 List 和数组的关系,有点

三 SDS

为了解决上述问题,小伙伴们可以先想想,我们都需要哪些东西呢?

  • 首先得有一个存储字符的 char 数组吧。
  • 数组的总长度得有一个变量记录下来吧。
  • 数组已经使用的长度得记录下来吧。

这是三个最基本的属性。

3.1 SDS 类型

当然在具体实践中还有一个 flags 属性,这个属性用来表示 SDS 的类型,因为 Redis 设计了几种不同的 SDS 类型,这样的设计主要是为了节省内存。

从这里可以看到,一共有五种不同的 SDS 类型,分别是:

  1. sdshdr5
  2. sdshdr8
  3. sdshdr16
  4. sdshdr32
  5. sdshdr64

从注释中可以看到,sdshdr5 其实没有使用,另外四个的区别主要在于数组长度和分配空间长度的差异。

以 sdshdr16 为例,uint16_t 表示 16 位无符号 int 值,能表示的最大值是 2^16-1,所以它的 buf 数组的最大长度就是 2^16。

按照这样的设计,其实 Redis 的字符串能够存储超大的字符串,例如,sdshdr32 类型意味着能够存储的字符长度是 2^32,一个字符占一个字节,就是 4GB。

可是实际上 Redis 的字符串存不了这么长的,Redis 内部会对字符串的长度进行限制,最大是 512MB。

当然实际生产中我们不建议这么搞,一般字符串最好不要超过 1MB。

3.2 编码格式

为了提升效率,SDS 中使用的编码格式也会根据情况来定。

  • 如果是数字类型,且数字长度小于 20,就会使用 int 编码。

  • 长度小于等于 44 字节的字符串,使用 embstr 编码。
  • 长度大于 44 字节的字符串使用 raw 编码。

3.3 其他特点

不同于 C 中的字符串,SDS 可以存储二进制数据,因为 SDS 不再通过 \0 去判断字符串结束,因为有一个 len 变量存储了字符串的长度。

同时,SDS 在字符串扩容的时候也会进行预分配,这些机制类似于咱们 Java 中 ArrayList 扩容、HashMap 扩容,扩容时会预留空间,避免频繁扩容。

同时,缩容的时候并不会立马释放多余空间,防止后续又要扩容。

四 小结

大致就这些东西,其实也不难。

松哥最近也录了一个 Redis 视频课,基于目前最新版的 Redis 来讲解,从用法到原理到经典面试题都有涉及,感兴趣的小伙伴可以看下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2073377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实验11 编写子程序《汇编语言》- 王爽

1. 需求 编写一个子程序,将包含任意字符,以 0 结尾的字符串中的小写字母转变成大写字母,描述如下。 名称:letterc 功能:将以 0 结尾的字符串中的小写字母转变成大写字母 参数:ds:di 指向字符串首地址 …

快速排序模版

1.霍尔法 #include <iostream> using namespace std; int partition(int *arr,int left,int right){int pivotIndexleft;while(left<right){while(left<right && arr[right]>arr[pivotIndex]){right--;}while(left<right && arr[left]<a…

新160个crackme - 040-DaNiEl-RJ.1

运行分析 需要破解Name和Serial PE分析 Delphi程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida搜索字符串&#xff0c;找到关键字符串进入 对关键函数进行动调分析&#xff0c;注释和变量重命名如上还需要破解sub_4036E8 通过对比sub_4036E8函数的返回值和Nam…

python面向对象—封装、继承、多态

封装 当定义为私有成员变量时&#xff0c;引用或者打印都不可行。 私有成员对于类对象没有办法直接使用&#xff0c;但是我们类中其他成员却是可以访问这些私有成员的。 封装总结&#xff1a; 私有成员的定义我们已经了但是有什么实际的意义吗&#xff1f; 继承 继承表示&…

系规学习第19天

1.知识管理流程的目标是将运维生产过程中产生的各类信息所包含的知识最大限度地提取、保留&#xff0c;通过评审后加以应用&#xff0c;包括&#xff1a;实现知识共享&#xff0c;实现知识转化&#xff0c;避免知识流失&#xff0c;提高运维响应速度和质量&#xff0c;挖掘、分…

scrapy--图片管道-ImagesPipeline

免责声明:本文仅做演示与分享~ 目录 介绍 ImagesPipeline pipelines.py items.py zz.py settings.py 介绍 scrapy 还提供了处理图片、视频、音频等媒体文件的插件&#xff0c;如&#xff1a; - scrapy-images&#xff1a;用于下载和处理图片 - scrapy-video&#xff1…

<C++> 二叉树进阶OJ题

目录 1. 二叉树创建字符串 2. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先 3. 二叉树搜索树转换成排序双向链表 4. 根据一棵树的前序遍历与中序遍历构造二叉树 5. 根据一棵树的中序遍历与后序遍历构造二叉树 6. 二叉树的前序遍历&#xff0c;非递归迭代实现 7. 二…

13.全志H3-底板测试和测试记录

上面是我的微信和QQ群&#xff0c;欢迎新朋友的加入。 前段时间&#xff0c;做了一个H3的双DDR方案&#xff0c;记录一下测试过程。 1.硬件速率检测 1.取掉SD卡&#xff0c;不接调试串口&#xff0c;按住复位按键&#xff0c;上电 设备管理器会弹出USB设备&#xff0c;打开硬…

Python|日志记录详解(1)

引言 作为一名Python程序员&#xff0c;记录程序运行时的关键信息是一种有益的做法&#xff0c;这有助于深入理解你的代码。这种记录行为被称作日志记录&#xff0c;它是一个非常实用的工具&#xff0c;是编程工具箱中不可或缺的一部分。日志记录能够帮助你捕捉到在开发过程中可…

哈里和梅根的批评者似乎并不理解“不可征服运动会”的全球影响力

哈里王子和梅根马克尔的批评者似乎无法理解为什么这对夫妇继续像王室之旅一样环游世界。答案很简单&#xff1a;不可征服运动会。苏塞克斯夫妇通过这项体育赛事获得了成功&#xff0c;它为“国际受伤、受伤和生病的军人和女性提供了康复之路”。各国正在争夺未来运动会的主办权…

Photoshop用户必备:PS全套插件分享(PS插件全家桶)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 PS全套插件 📒🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 你是否时常为Photoshop中复杂的操作流程感到困扰,渴望拥有一把钥匙,能瞬间解锁设计效率与创意的新世界?今天,我将给大家分享一款让众多设计师梦寐以求的…

Elasticsearch用法

&#x1f4a5; 该系列属于【SpringBoot基础】专栏&#xff0c;如您需查看其他SpringBoot相关文章&#xff0c;请您点击左边的连接 目录 一、初识elasticsearch 1. 安装Elasticsearch和Kibana 2. 倒排索引 3. IK分词器 4. 基础概念 二、索引库操作 1. Mapping映射属性 2…

IM项目:进阶版即时通讯项目---语音识别和验证码服务

文章目录 语音识别基本功能模块划分流程图实现逻辑解析proto文件 验证码服务 本篇主要是对于该项目的语音识别和验证码服务模块的一个梳理&#xff0c;项目会直接使用部分封装好的内容&#xff0c;可以查看前面的文档或在本文档中进行查看和学习 由于这两个模块非常相似&#…

模型 卡茨管理模型

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。技术、人际、概念&#xff1a;管理技能三支柱。 1 卡茨管理模型的应用 1.1 产品经理能力模型&#xff1a;基于卡茨管理模型的应用 在现代企业管理中&#xff0c;产品经理的角色越来越受到重视。根据…

HTML简单了解和基础知识记录

参考视频 html的用途 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;&#xff0c;用来显示网页的文字和框架结构&#xff0c;可以认为是网页的骨架。 标签/元素 用于定义文字图片连接等&#xff0c;分…

超简单Java邮件发送-为你的小程序实现邮箱验证码登录

本项目基于Apache Commons Email for Jakarta开发。 超简单实现邮箱发送&#xff0c;并以此扩展出邮箱验证码功能(请读者扩展实现)。 构建工具&#xff1a;Maven 演示邮箱&#xff1a;outlook 准备 请确保你的邮箱开启了SMTP服务&#xff0c;并获取相关参数&#xff0c;类似…

51单片机——模块化编程

1、模块化编程介绍 传统方式编程&#xff1a;所有的函数均放在main.c里&#xff0c;若使用的模块比较多&#xff0c;则一个文件内会有很多的代码&#xff0c;不利于代码的组织和管理&#xff0c;而且很影响编程者的思路。 模块化编程&#xff1a;把各个模块的代码放在不同的.…

诊断知识:agedDTCLimit的使用

文章目录 前言agedDTCLimit的定义agedDTCLimit的使用图解agedDTCLimit总结 前言 ECU中的存储空间一般无法将所有的DTC同时记录故障数据&#xff0c;所以故障发生之后记录的数据&#xff0c;需要在一段时间后未出现故障则自动清除&#xff0c;以保证新的故障出现时&#xff0c;…

苍穹外卖-day05(SpringBoot+SSM的企业级Java项目实战)

苍穹外卖-day05 课程内容 Redis入门 Redis数据类型 Redis常用命令 在Java中操作Redis 店铺营业状态设置 功能实现&#xff1a;营业状态设置 效果图&#xff1a; 选择营业中&#xff0c;客户可在小程序端下单&#xff1a; 选择打烊中&#xff0c;客户无法在小程序端下单&…