Redis 7.x 系列【6】数据类型之字符串(String)

news2024/10/6 10:33:37

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • 1. 前言
    • 2. 常用命令
      • 2.1 SET
      • 2.2 GET
      • 2.3 MSET
      • 2.4 MGET
      • 2.5 GETSET
      • 2.6 STRLEN
      • 2.7 SETEX
      • 2.8 SETNX
      • 2.9 INCR
      • 2.10 DECR
    • 3. SDS(简单动态字符串)
      • 3.1 二进制安全
      • 3.2 查询字符串长度效率高
      • 3.3 缓冲区溢出保护
      • 3.4 空间预分配
      • 3.5 惰性空间释放
    • 4. 应用场景
      • 4.1 存储常规数据
      • 4.2 计数器
      • 4.3 分布式锁

1. 前言

在官方文档中,可以看到 Redis 支持很多种数据类型,以解决不同场景下的各种问题。接下来,会详细介绍 Redis 中的各种数据类型, 主要是介绍一些常用的,包括:

  • String
  • List
  • Hash
  • Set
  • Sorted setZSet
  • Bitmap
  • HyperLogLog
  • Geospatial
  • Stream

String字符串是编程语言里最常用的数据类型,使用双引号表示。

比如JAVA

	String str="1234";

比如C语言:

    char str[] = "1234";

Redis 中, String 类型是最基本的数据类型,是二进制安全的,可以存储任意类型的数据,文本、数字、图片或者序列化的对象 。
在这里插入图片描述

注意Key的类型只能为字符串,Value的类型为字符串时,默认情况下的最大值是 512M

2. 常用命令

String 相关的所有命令:

命名描述
APPENDvalue 追加到 key 原来的值的末尾
DECRkey 中储存的数字值减一
DECRBYkey 所储存的值减去给定的减量值 ( decrement )
GET设置指定 key 的值
GETDEL获取 key 的值并删除该 key
GETEX获取 key 的值,并可选择设置其过期时间
GETRANGE返回 key 中字符串值的子字符
GETSET将给定 key 的值设为 value ,并返回 key 的旧值
INCRkey 中储存的数字值增一
INCRBYkey 所储存的值加上给定的增量值 ( increment )
INCRBYFLOATkey 所储存的值加上给定的浮点增量值 ( increment )
LCS实现了最长公共子序列算法,可用于评估字符串的相似程度
MGET获取所有(一个或多个)给定 key 的值
MSET同时设置一个或多个 key-value
MSETNX同时设置一个或多个 key-value
PSETEX以毫秒为单位设置 key 的生存时间
SET设置指定 key 的值
SETEX设置 key 的值为 value 同时将过期时间设为 seconds
SETNX只有在 key 不存在时设置 key 的值
SETRANGE从偏移量 offset 开始用 value 覆写给定 key 所储存的字符串值
STRLEN返回 key 所储存的字符串值的长度
SUBSTR返回字符串值的子字符串,由偏移量开始和结束(两者都包含在内)决定

2.1 SET

用于给指定的 Key 设置字符串值,如果 Key 已经保存了一个值,那么这个操作会直接覆盖原来的值,并且忽略原始类型。当 SET 命令执行成功后,之前设置的过期时间都将失效。

示例:

127.0.0.1:6379> SET mykey "Hello World"
OK
127.0.0.1:6379> SET mykey "Hello World" EX 60
OK

2.2 GET

用于获取指定 Key 的字符串值,如果 Key 不存在, 那么返回特殊值 nil, 如果键 Key的值不是字符串类型, 返回错误, 因为 GET 命令只能用于字符串值。

示例:

127.0.0.1:6379> GET mykey
"Hello World"
127.0.0.1:6379> GET mykey_nil
(nil)

2.3 MSET

SET 命令一样,会用新值替换旧值, MSET 是原子操作,所有 Key 的值同时设置,客户端不会看到有些 Key 值被修改,而另一些 Key 值没变。总是返回 OK ,因为 MSET 不会失败。

基本语法:

MSET key1 value1 key2 value2 .. keyN valueN 

示例:

127.0.0.1:6379> MSET key1 "Hello" key2 "World"
OK
127.0.0.1:6379> GET key1
"Hello"
127.0.0.1:6379> GET key2
"World"

2.4 MGET

用于获取所有给定 Key 的值,返回一个列表,值的类型是字符串,如果某个 Key 不存在或者值不是字符串,那么这个 Key 返回特殊值 nil

基本语法:

MGET KEY1 KEY2 .. KEYN

示例:

127.0.0.1:6379> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)

2.5 GETSET

用于给指定的 Key 设置字符串值, 并返回设置之前的旧值。如果 Key 没有旧值返回 nil,如果 Key 对应的值存在但不是字符串类型时,返回一个错误。

示例:

127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GETSET mykey "World"
"Hello"
127.0.0.1:6379> GET mykey
"World"

2.6 STRLEN

用于获取指定 Key 所储存的字符串值的长度,当储存的不是字符串类型时,返回错误。

基本语法:

STRLEN KEY_NAME

示例:

127.0.0.1:6379> SET mykey "Hello world"
OK
127.0.0.1:6379> STRLEN mykey
(integer) 11
127.0.0.1:6379> STRLEN mykey_nil
(integer) 0

2.7 SETEX

用于给指定的 Key 设置字符串值,并将 Key 的生存时间设置为多少秒。如果键 Key 已经存在,将覆盖已有的值。

基本语法:

SETEX key seconds value

示例:

127.0.0.1:6379> SETEX mykey 60 "Hello"
OK
127.0.0.1:6379> TTL mykey
(integer) 52
127.0.0.1:6379> GET mykey
"Hello"

2.8 SETNX

SETNXSET if Not eXists 的缩写,在指定的 Key 不存在时,设置指定的值,这种情况下等同 SET 命令,当 Key 存在时,什么也不做。

返回值为整数:

  • 1Key 存在
  • 0Key 不存在

SETNX 命令是原子性的,常用于实现分布式锁,添加成功表示获取到锁,添加失败表示未获取到锁(后续详解介绍)。

示例:

redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"

2.9 INCR

用于将指定的 Key 储存的数字值增一,如果 Key 不存在,那么值会先被初始化为 0 ,然后再执行 INCR 操作,返回值为执行操作之后 Key 的值。如果值包含错误的类型,或字符串类型的值不能表示为数字,将会返回一个错误 ERR ERR hash value is not an integer

操作的值限制在 64 位(bit)有符号数字表示之内。本质上这是一个字符串操作,因为 Redis 没有专门的整数类型,储在 Key 中的字符串被转换为十进制有符号整数,在此基础上加 1 。常用于计数器、限流(后续详解介绍)。

基本语法:

 INCR KEY_NAME 

示例:

127.0.0.1:6379> SET mykey "10"
"OK"
127.0.0.1:6379> INCR mykey
(integer) 11
127.0.0.1:6379>  GET mykey
"11"

2.10 DECR

用于将指定的 Key 储存的数字值减去一,如果 Key 不存在,那么值会先被初始化为 0 ,然后再执行 DECR 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,将会返回一个错误。操作的值限制在 64 位(bit)有符号数字表示之内,返回值为执行操作之后 Key 的值

基本语法:

 DECR KEY_NAME 

示例:

127.0.0.1:6379> DECR mykey
(integer) 9
127.0.0.1:6379> SET mykey "234293482390480948029348230948"
"OK"
127.0.0.1:6379>DECR mykey
ERR ERR value is not an integer or out of range

3. SDS(简单动态字符串)

SDSSimple Dynamic String 的首字母缩写,翻译为简单的动态字符串,是 Redis 自定义的一种表示字符串的特殊数据结构。相较于传统的C语言字符串,SDS 具有更多的功能和更高的性能,当前也会占用更多的内存。

Redis 3.2 之前的版本:

struct sdshdr {
    int len; // 记录buf数组中已使用字节的数量,即字符串的实际长度
    int free; // 存储剩余(空闲)的空间
    char buf[]; // 存储实际数据
};

Redis 3.2 之后的版本,SDS 变成了 5 种数据结构,不同类型的存储空间大小不一样:

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; // 已用空间的长度,占 4 个字节,不包括 ‘\0’;
    uint8_t alloc; // 实际分配长度,占 4 个字节,不包括 ‘\0’;
    unsigned char flags; // 标记当前 buf[] 类型( sdshdr8/16/32/64)
    char buf[]; // 存储实际数据
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

相比于C语言字符串,SDS 有以下优点:

  • 二进制安全
  • 查询字符串长度效率高
  • 缓冲区溢出保护
  • 空间预分配
  • 惰性空间释放

3.1 二进制安全

C 语言中,用字符 \0 表示字符串的结束,如果字符串中本身就有 \0 字符,字符串就会被截断,即非二进制安全,例如 hello \0 world 会被截断解析为 hello

SDS 不受 \0 字符影响,能够准确存储任意二进制数据,因为它基于 len 属性而非遇到 \0 来判断字符串的结束位置。

3.2 查询字符串长度效率高

C 语言中,获取一个字符串长度时,需对整个字符串进行遍历,直至遇到结束符号。在高并发场景下频繁遍历字符串,势必会造成性能瓶颈。

SDS 中于 len 属性记录了字符串的长度,可以直接通过 STRLEN 命令获取长度即可。

3.3 缓冲区溢出保护

C 语言中,字符串本身不记录可用空间大小,在进行字符串拼接等操作时,如果没有检查就可能会导致缓冲区溢出。

SDS 中于 free 属性记录了额外未使用的空间大小,每次进行字符串操作前都会检查剩余空间是否足够,不足时会自动扩容,有效避免了缓冲区溢出问题。

3.4 空间预分配

C 语言中,每次修改字符串长度(增加或减少)时,通常需要重新分配内存,这可能导致频繁的内存操作。

SDS 优化了字符串增长操作,当修改字符串并需对 SDS 的空间进行扩展时,不仅会为 SDS分配修改所必要的空间,还会分配额外的未使用空间(free属性),下次再修改就先检查未使用空间free是否满足,满足则不用在扩展空间。有效的减少字符串连续增长操作,减少所产生的内存重分配次数。

3.5 惰性空间释放

惰性空间释放策略则用于优化 SDS 字符串缩短操作,当缩短 SDS 字符串后,并不会立即执行内存重分配来回收多余的空间,而是用 free 属性将这些空间记录下来,如果后续有增长操作,则可直接使用。

4. 应用场景

4.1 存储常规数据

String 可以存储任意类型的数据,文本、数字、图片或者序列化的对象 。

常用实际场景:

  • 图形、短信验证码
  • 令牌

例如,存储短信验证码并设置过期时间为 60 秒:

localhost:0>SET 13688889999 80906 EX 60
"OK"
localhost:0>GET 13688889999
"80906"

4.2 计数器

INCR 用于将指定的 Key 储存的数字值增一, DECR 用于将指定的 Key 储存的数字值减去一。

常用实际场景:

  • 阅读数
  • 点赞
  • 分布式ID
  • 网站访问量
  • 记录接口访问次数,实现防止重复提交、简单限流

例如,使用 INCR 记录网站每日访问量:

localhost:0>SET web_views:20240617 0
"OK"
localhost:0>INCR web_views:20240617
"1"
localhost:0>GET web_views:20240617
"1"

4.3 分布式锁

SETNX 命令是原子性的,常用于实现分布式锁,添加成功表示获取到锁,添加失败表示未获取到锁(后续详解介绍)。

例如,执行 SETNX 添加锁,返回 1 表示成功获取到锁:

localhost:0>SETNX my_lock yes
"1"

其他线程执行SETNX,返回 0 表示获取锁失败:

localhost:0>SETNX my_lock yes
"0"

执行完成后,删除锁,其他线程再次获取则成功:

localhost:0>DEL my_lock
"1"
localhost:0>SETNX my_lock yes
"1"

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

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

相关文章

0625_ARM2

练习: 汇编实现1-100累加,结果保存在r0 .text .global _start start:mov r0,#0mov r1,#1b loop loop:add r0,r0,r1add r1,r1,#1cmp r1,#101bne loop .end思维导图:

EPLAN页属性批量修改

在使用EPLAN软件时,项目数据量大的时候,需要修改页属性,每一页单独修改会很繁琐,这里介绍如何批量修改页属性: 在EPLAN里点击“工具----从外部编辑属性------导出数据” 这里按图示可定义保存位置,和输出方…

感谢5年前的自己

感谢CSDN提醒,惊讶发现在CSDN上写作已经5年了,感叹时光如梭,感谢CSDN提供了这个技术交流分享平台,让我可以在这个平台上搜索到许多疑难问题的解决方案,也让自己在分享中不断加深问题解决方法的理解 初衷 写作初衷大概…

2024年软考架构设计师终于PASS啦

文章目录 系统架构设计师是什么考试要求考试科目个人心得综合知识上午案例下午论文 系统架构设计师是什么 系统架构设计师,属于计算机技术与软件(高级)专业技术资格。考试合格人员能够根据系统需求规格说明书,结合应用领域和技术…

数据增强 data augmentation(在PyTorch中,data_transforms通常用于数据集处理,并且经常用于数据增强)

数据增强是一种在训练深度学习模型时,通过对输入数据进行变换和修改的方法,以增加训练数据集的大小和多样性,从而提高模型的泛化能力和性能。 PS: PyTorch中,data_transforms具体使用代码可以查看这篇文章: pytor…

QT学习积累——float 接收 两个 int类型的值相除的结果,即 float f = int(1)/ int(2)= 0

目录 引出除法的一个坑 总结自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重载带参数的按钮触发信号触发信号拓展 lambda表达式返回值mutable修饰案例 引出 QT学习积累——float 接收 两个 int类型的值相除的结果,即 float f int&#xf…

网络安全事件研判

研判(入侵检测) 研判我理解为人工层面对入侵检测事件进行再分析,即借助已有的设备告警根据经验判断是否为真实攻击 研判工作要充分利用已有安全设备(需要提前了解客户的网络拓扑以及部署设备情况),分析其近…

幂法 Euler法

一、实验原理 根据幂法,Euler法的相关知识和算法编程完成本实验 二、实验内容 见第7章PPT:用规范化幂法计算下面矩阵的按模最大特征值及对应的特征向量 见第8章PPT:分别用简单欧拉法和改进欧拉法对如下初值问题作验证性计算 三、实验过程&a…

rga_mm: RGA_MMU unsupported Memory larger than 4G!解决

目录 报错完整log如下:解决方案:报错完整log如下: [ 3668.824164] rga_mm: RGA_MMU unsupported Memory larger than 4G! [ 3668.824305] rga_mm: scheduler core[4] unsupported mm_flag[0x0]! [ 3668.824320] rga_mm: rga_mm_map_buffer map dma_buf err

音视频入门基础:H.264专题(4)——NALU Header:forbidden_zero_bit、nal_ref_idc、nal_unit_type简介

音视频入门基础:H.264专题系列文章: 音视频入门基础:H.264专题(1)——H.264官方文档下载 音视频入门基础:H.264专题(2)——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…

昇思25天学习打卡营第1天|新手上路

这里写自定义目录标题 打卡昇思MindSpore扫盲快速入门 打卡 昇思MindSpore扫盲 第一节基本是一个mindspore的科普扫盲。大概介绍一通mindspore的一些架构,feature,以及其对比于其他同类框架的优势。简单扫读了一遍大概有点印象直接跳过。 快速入门 这…

Spring IOC架构设计解析

一、spring famework 模块解析 二、SpringIOC容器:Core Container: Beans、Core、Context、Expression 三、BeanFactory (该接口定义了容器最基本的功能方法)和 ApplicationContext(对容器提供了更丰富的功能扩展,大部分应用中所使用的基于它实现&…

【机器学习-10】 | Scikit-Learn工具包进阶指南:Scikit-Learn工具包之支持向量机模块研究

🎩 欢迎来到技术探索的奇幻世界👨‍💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…

高考英语3500词

DAY1 DAY2 DAY3 DAY4 DAY5 DAY6 DAY7 DAY8 DAY9 DAY10 DAY11 DAY12 DAY13 DAY14 DAY15 DAY16 DAY17 DAY18 DAY19 DAY20 DAY21 DAY22 DAY23 DAY24 DAY25 DAY26 DAY27 DAY28 DAY29 DAY30 DAY31 DAY32 DAY33 DAY34 DAY35 DAY36 DAY37 DAY38 DAY39 DAY40

更进一步|瑞数信息位居2023年中国私有云WAF市场份额Top2!

更进一步|瑞数信息位居2023年中国私有云WAF市场份额Top2! 近日,IDC《中国云Web应用防火墙市场份额,2023:WAAP成为共同演进方向》报告正式发布。报告聚焦2023年中国云Web应用防火墙市场的规模、厂商份额以及技术发展变…

Python光束三维二维标量场和算法

🎯要点 🎯矢量计算和绘图:🖊二维,三维 | 🖊转换矢量图 | 🖊矢量和矩阵计算 | 🖊矢量空间变换和计算 | 🖊解矢量线性方程 | 🎯数学和物理矢量计算&#xff1a…

ppdetection-2.7

1, pip install -r requirement.txt 2、 ValueError: paddle.load can not parse the file:C:\Users\HX/.cache/paddle/weights\deepsort_pcb_pyramid_r101.pdparams. 重新下载模型 3、 declarative() got an unexpected keyword argument看一下参数是否写对,比如…

树莓派选型深度指南:架构、性能与应用场景全解析

树莓派作为全球最受欢迎的单板计算机,凭借其低廉的价格、强大的性能和丰富的扩展性,吸引了无数电子爱好者、开发者和教育工作者的青睐。然而,面对琳琅满目的树莓派型号,新手往往不知从何下手。 本文将深入对比几款市面上最热门的…

卸载 ubuntu-wsl2-systemd-script,使用 WSLg 图形用户界面

目录 全新安装 - 以前没有安装 WSL现有 WSL 安装卸载 ubuntu-wsl2-systemd-script使用 Linux GUI参考链接在 Windows 上使用 Linux 开发环境,最好的做法是使用 WSL2。在 WSL 和早期的 WSL2 版本中,并不支持图形用户界面。因此如果想要使用 GUI 程序,需要自行解决。具体方法可…

Notepad++爱国版重磅更新:集成18大高人气插件

Notepad最新版的言论与导向存在价值观问题,经重新编译修正为“统一祖国,振兴中华”版本,传导正确的价值观和爱国情怀。 Notepad功能可以通过各种插件来增强,下面是18大高人气插件 AutoCodepage 功能:在加载、重命名或更…