【Redis】数据结构---String

news2024/11/26 17:36:27

文章目录

    • String(字符串)
      • 1.Redis 键(key)
      • 2.String(字符串)
        • 2.1常用命令
        • 2.2.String底层结构
      • 3.空间分配策略
        • 3.1空间预分配
        • 3.2惰性空间释放
        • 3.3为什么SDS的最大长度是512M?
      • 4.SDS面试题

String(字符串)

1.Redis 键(key)

  • keys *查看当前库所有key (匹配:keys *1)
  • exists key判断某个key是否存在
  • type key 查看你的key是什么类型
  • del key 删除指定的key数据
  • unlink key 根据value选择非阻塞删除。仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。
  • expire key 10 10秒钟:为给定的key设置过期时间
  • ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期

image-20221130014337304

执行上面的操作

image-20221130015234931

2.String(字符串)

String是Redis最基本的类型,一个key对应一个value。

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

2.1常用命令

set 添加键值对

image-20221130021209021

关于set的其他参数

  • NX:当数据库中key不存在时,可以将key-value添加数据库
  • *XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
  • EX:key的超时秒数
  • PX:key的超时毫秒数,与EX互斥

get 查询对应键值

append 将给定的 追加到原值的末尾

strlen 获得值的长度

setnx 只有在 key 不存在时 设置 key 的值

image-20221130022154240

数字类型的命令:

incr

  • 将 key 中储存的数字值增1
  • 只能对数字值操作,如果为空,新增值为1

decr

  • 将 key 中储存的数字值减1
  • 只能对数字值操作,如果为空,新增值为-1

incrby / decrby <步长>将 key 中储存的数字值增减。自定义步长。

  • 注意:INCR类型的命令是原子的,Redis单命令的原子性主要得益于Redis的单线程。

image-20221130022352456

mset …

  • 同时设置一个或多个 key-value对

mget …

  • 同时获取一个或多个 value

image-20221130022635543

msetnx …

  • 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
  • 该命令具有原子性:其中有一个key是存在的,则都创建失败

image-20221130022855031

getrange <起始位置><结束位置>

  • 获得值的范围,类似C++中string类的substr。

setrange <起始位置>

  • 用 覆写所储存的字符串值,从<起始位置>开始(索引从0****开始)。

image-20221130023035175

setex <过期时间>

  • 设置键值的同时,设置过期时间,单位秒。

getset

  • 以新换旧,设置了新值同时获得旧值。

2.2.String底层结构

Redis是用C语言写的,但是对应Redis的Sting,并不是C 语言中的字符串(即以空字符’\0’结尾的字符数组);Redis自定义了数据结构SDS(simple dynamic string)【简单动态字符串】,并将 SDS 作为 Redis的默认字符串表示。

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

image-20221130024613783

  • len为字符串的实际长度,保证了获取字符串长度时为O(1)操作
  • free为buf数组中剩余的空间大小
  • buf 保存字符串的数组
  • 如果长度不够,会主动申请空间
  • redis实际开辟的空间为len+free

优点:

减少修改字符串的内存重新分配次数

C语言字符串由于不记录字符串长度,所以如果要修改字符串,必须重新分配内存(先释放再申请)。因为如果没有重新分配,字符串长度增大时会造成内存缓冲区溢出,字符串长度减小时会造成内存泄露。

对于SDS,由于len属性和free属性的存在,对于修改字符串SDS实现了空间预分配和惰性空间释放两种策略:

  • **空间预分配:**对字符串进行空间扩展的时候,扩展的内存比实际需要的多,这样可以减少连续执行字符串增长操作所需的内存重分配次数。
  • **惰性空间释放:**对字符串进行缩短操作时,程序不立即使用内存重新分配来回收缩短后多余的字节,而是使用 free 属性将这些字节的数量记录下来,等待后续使用。

二进制安全

  • C字符串以空字符作为字符串结束的标识,而对于一些二进制文件(如图片等),内容可能包括空字符串,因此C字符串无法正确存取;
  • 而所有 SDS 的API 都是以处理二进制的方式来处理 buf 里面的元素,**并且 SDS 不是以空字符串来判断是否结束,而是以 len 属性表示的长度来判断字符串是否结束。**所以SDS可以保存图片、音频等文件内容。

3.空间分配策略

3.1空间预分配

C++中数组在进行扩容时,往往会申请一个更大的数组,然后把数组拷贝过去。Redis同样基于这种策略提高了空间预分配机制。

当执行字符串增长操作并且需要扩展内存时,程序不仅仅会给SDS分配必需的空间还会分配额外的未使用空间,其长度存到free属性中。具体如下:

  • **如果修改后len长度将小于1M,这时分配给free的大小和len一样;**例如修改过后为10字节, 那么给free也是10字节,buf实际长度变成了10+10+1 = 21byte(别忘记了\0的存在)
  • **如果修改后len的长度大于等于1M,这时分配给free的长度为1M;**例如修改过后为30M,那么给free是1M.buf实际长度变成了30M+1M+1byte

image-20221130031707362

3.2惰性空间释放

惰性空间释放用于字符串缩短的操作。当字符串缩短是,程序并不是立即使用内存重分配来回收缩短出来的字节,而是使用free属性记录起来,并等待将来使用。

image-20221130031932892

3.3为什么SDS的最大长度是512M?

Redis字符串使用int类型表示长度,一共有32个比特位。2^32字节=512M

4.SDS面试题

1.SDS如何兼容C语言字符串?如何保证二进制安全?

C99中提到,结构体的最后一个成员如果是一个数组,大小不确定,那么就是一个柔性数组。

SDS对象中的buf是一个柔性数组,上层调用时,SDS直接返回了buf。由于buf是直接指向内容的指针,所以兼容C语言函数。而当真正读取内容时,SDS会通过len来限制读取长度,而非“\0”,所以保证了二进制安全。

2.SDS是如何扩容的?

空间预分配。先判断扩容长度与free的大小关系,如果够就直接拼接字符串,如果不够使用空间预分配的方式扩容。

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

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

相关文章

使用并行流的注意事项

遇到的问题&#xff1a;当时用并行流的时候期望结果7&#xff0c;但是偶尔会有结果不对的情况。。。 如下代码&#xff1a; public static void main(String[] args) {long startSystem.currentTimeMillis();List<String> alist new ArrayList<String>(Arrays.a…

【读书笔记】打开心智

打开心智 0&#xff0c;写在前面 什么是打开心智&#xff1f;我认为是通过更好的认识人类&#xff0c;认识自己&#xff0c;了解自己的本性&#xff0c;然后顺应本性指导和改变自己对事物的看法&#xff0c;约束自己的行为的过程。这也是一个认识心智到打开心智的过程。其实我…

代码随想录刷题|LeetCode 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II

目录 121. 买卖股票的最佳时机 思路 暴力解法 贪心算法 动态规划 买卖股票的最佳时机 贪心算法 动态规划 122.买卖股票的最佳时机II 思路 分析递推公式 买卖股票的最佳时机II 贪心算法 动态规划 121. 买卖股票的最佳时机 题目链接&#xff1a;力扣 思路 暴力解法 暴力解答会超…

矩池云|GPU 分布式使用教程之 TensorFlow

GPU 分布式使用教程之 TensorFlow TensorFlow 提供了6种策略实现分布式计算&#xff0c;各个策略详情请参考官方文档。本文档使用 MirroredStrategy 实现单机多卡分布式&#xff0c;MultiWorkerMirroredStrategy 实现多机多卡分布式计算。 选择机器 单机多卡分布式&#xff1…

【MySQL进阶】多表连接的原理

【MySQL进阶】多表连接的原理 文章目录【MySQL进阶】多表连接的原理前言一&#xff1a;连接简介1&#xff1a;连接的本质2&#xff1a;连接过程简介二&#xff1a;连接的原理1&#xff1a;嵌套循环连接&#xff08;Nested-Loop Join&#xff09;2&#xff1a;使用索引加快连接速…

MySQL 8.*版本 修改root密码报错

1、mysql.sock报错 解决办法&#xff1a; 1、根据报错提示&#xff0c;是无法找到/tmp下面的mysql.sock。 2、全局搜索该文件&#xff1a;mysql.sock。 使用命令&#xff1a;find / -iname "mysql.sock" 为mysql.sock该文件创建软连接&#xff0c;命令如下&#x…

基于Java Web的传智播客crm企业管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Redis企业版数据库如何支持实时金融服务?

一、数字化转型正在颠覆银行业和金融业 随着金融科技初创公司和互联网巨头利用前沿技术重塑客户对金融服务的预期&#xff0c;金融服务行业正在经历大规模的数字化颠覆。 对于非接触式支付、移动银行、信贷决策、欺诈检测等服务&#xff0c;金融业客户要求“实时体验”&#…

使用tinode架设自己的私有聊天服务

需求 众所周知的原因&#xff0c;使用公用的即时聊天工具并不安全&#xff0c;比如某企鹅家的"wei xin"&#xff0c;我们需要一个自己的安全的聊天工具&#xff0c;比如我们需要传递账号以及密码等&#xff1b; 方案1&#xff1a; 使用网页工具将文本加密&#xf…

一、【redux】redux简介 mini版求和Demo

文章目录1、学习文档2、redux是什么3、什么情况下需要使用redux4、redux工作流程5、redux的三个核心概念5.1、action5.2、reducer5.3、store6、redux的核心API6.1、createStore()6.2、store对象6.3、applyMiddleware()6.4、combineReducers()7、求和Demo&#xff08;纯react版&…

拖死项目的不是团队,可能是失败的管理

项目中的活动&#xff0c;归根结底是由人来完成的&#xff0c;如何发挥项目成员的能力&#xff0c;对于项目的成败起着至关重要的作用。如何充分地发挥团队成员的能力&#xff0c;对项目经理也是一个挑战。 在团队管理者我们会遇见这些难题&#xff1a; 1、团队凝聚力不足&a…

配置CentOS

一、启动虚拟机 1、登录虚拟机 出现[rootlocalhost]#提示符&#xff0c;表明登录成功 2、查看IP 命令&#xff1a; ip addr 3、是否ping通外网 命令&#xff1a;ping www.baidu.com 二、配置静态IP地址 1、修改网卡配置文件 命令&#xff1a;vi /etc/sysconfig/net…

UBoot怎么跳转到Kernel:uboot与linux的交界

不知道你是否有这种感觉&#xff0c;就是学习了一段时间Uboot&#xff0c;学习了一段时间kernel&#xff0c;也知道Uboot是引导程序。但是总是连不起来。 我为什么来的这样的感受是因为&#xff0c;我最近在学习安全相关的东西。但是这个安全的东西应用在kernel里面进行&#…

路径规划算法之刚体变换

目录 1 一般概念 1.1 基元的变换 1.2 一个参数化的变换族 2 2D变换 2.1 translation 2.2 rotation 2.3 Combining translation and rotation 3 3D变换 3.1 Yaw, pitch, and roll rotations 3.2 Determining yaw, pitch, and roll from a rotation matrix 3.3 The ho…

模拟电路设计(35)---几种脉宽调制型开关电路

Forward单端正激变换器 在buck变换器开关与负载之间插入隔离变压器&#xff0c;这种隔离型buck变换器叫做Forward单端正激变换器。如下图所示&#xff1a; Forward单端正激变换器 简单分析可知&#xff0c;滤波电感L在开关管关断期间&#xff0c;通过续流二极管为负载提供电流…

Android JNI编程并生成so库

这里写自定义目录标题Android JNI编程并生成so库Android Studio配置下载配置NDK配置NDK路径编写native方法和c文件编写配置文件生成so库使用so库Android JNI编程并生成so库 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编…

Python——字符串

1、再Python中&#xff0c;使用单引号或者双引号括起来的&#xff0c;就是字符串 2、字符串也可以使用六个单引号或者六个双引号括起来。 3、在Python3中&#xff0c;字符串分为两种类型&#xff0c;第一种是str&#xff0c;是unicode字符串&#xff0c;第二种是bytes&#x…

springboot酒店客房管理系统设计

随着我国市场经济的快速发展以及人们生活水平的不断提高&#xff0c;酒店&#xff0c;宾馆之间的竞争也越来越激烈&#xff0c;为了在这场竞争中取得显著的优势&#xff0c;就必须在管理上加以改善。在某种意义上&#xff0c;酒店客房方面的信息化已经成为现代化酒店的重要标志…

Python学习笔记第三十七天(NumPy 广播(Broadcast))

Python学习笔记第三十七天NumPy 广播(Broadcast)NumPy 广播(Broadcast) 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式&#xff0c; 对数组的算术运算通常在相应的元素上进行。 如果两个数组 a 和 b 形状相同&#xff0c;即满足 a.shape b.shape&…

gurobi 基于python的gurobipy库使用,具有一维变量和二维变量的复杂模型求解

写在前面 可以参考下pulp和scip两篇的&#xff0c;比较详细&#xff0c;尤其pulp篇。举一反三&#xff0c;很好入门。 步骤 定义问题&#xff1a;m Model(name) 定义变量&#xff1a;x m.addVars(range(len), vtypeGRB.BINARY) 定义目标函数&#xff1a;m.setObjective&…