当前位置: 首页 > news >正文

Redis之String 类型入门与实战,由基础语法快速掌握再到缓存加速/验证码防刷/计数统计场景应用

文章目录

  • 本篇摘要
  • 一.Redis常用数据类型
    • **Redis基础数据结构与底层优化**
    • Redis底层实现细节与单线程模型
      • 单线程模型速度高 效率快原因
  • 二.Redis数据类型之string字符串
      • Redis字符串类型核心要点总结
    • 1.SET命令(核心字符串设置)
        • SET系列其他命令
    • 2.GET命令(核心字符串设置)
    • 3.数值增减类命令(针对存储数字的 String)
    • 4. APPEND 命令
    • 5.截取与范围操作类命令
    • 6.长度命令
    • 其他实用场景与注意事项
    • 7. Redis内部编码方式
    • 8.典型使⽤场景
      • 缓存
      • 计数(Counter)功能
      • 共享会话(Session)
      • ⼿机验证码
  • 三.本篇小结

本篇摘要

  • Redis 提供字符串等 5 种基础数据类型,采用动态编码优化存储;单线程模型借内存与 I/O 多路复用实现高效,核心功能精简且支持丰富操作命令。

在这里插入图片描述

欢迎拜访: 点击进入博主主页

本篇主题: Redis数据类型+String类型详解

制作日期: 2025.10.24

隶属专栏: 点击进入所属Redis专栏

一.Redis常用数据类型

Redis基础数据结构与底层优化

  1. 核心数据类型
    Redis提供5种基础数据结构(键值对形式),对应常见编程语言类似结构:

在这里插入图片描述

  • 字符串(String):C++的字符数组,用于存储文本或数字。
  • 哈希(Hash):C++的unordered_map,存储字段-值对(如用户信息的键值集合)。
  • 列表(List):C++的deque,有序存储元素(如消息队列)。
  • 集合(Set):C++的set,无序且唯一的元素集合。
  • 有序集合(Sorted Set):元素按分数排序的唯一集合。
  1. 底层优化机制

在这里插入图片描述

  • 编码优化:Redis承诺提供上述数据类型接口,但底层会根据场景自动选择最优实现(用户通常无需关心)。例如:
    • 哈希表在元素较少时,可能优化为**压缩列表(ziplist)**以节省空间;
    • 列表元素为整数时,可能采用特殊编码减少内存占用(如int);
    • 字符串长度不同时,可能选择短字符串编码(如embstr)或长字符串编码(如raw)。

在这里插入图片描述

  • 动态调整:通过object encoding key命令可查看某个key对应value的完整编码方式(如ziplisthashtable等),实际存储结构可能因数据特征变化而自动转换。
  1. 优化目标
    核心是通过底层编码调整,在保证操作时间复杂度不变的前提下,节省存储空间和计算时间(如减少内存碎片、提升访问效率)。

Redis底层实现细节与单线程模型

  1. 关键数据结构扩展

    • Quicklist:从Redis 3.2引入的新结构,结合双向链表与压缩列表(ziplist)优势——每个节点是一个小型的ziplist,而大链表又是个Quicklist,既保留链表的灵活插入/删除能力,又通过ziplist压缩存储提升空间效率。
    • 编码转换示例:哈希对象根据元素数量和大小,可能在ziplist(小规模)和hashtable(大规模)之间自动切换,平衡查询速度与存储成本。
  2. 单线程处理模型

在这里插入图片描述

  • 核心逻辑:Redis用单个线程处理所有命令请求(虽然服务进程可能有多线程,但命令执行是单线程的),通过I/O多路复用技术(如epoll/kqueue)高效管理大量并发连接。

在这里插入图片描述
在这里插入图片描述

  • 并发特性:多个客户端的命令操作宏观上并发执行,但微观上排队处理(类似食堂排队取餐)。若某个命令执行时间过长(如复杂计算或大key操作),会阻塞后续命令,影响整体性能。

单线程模型速度高 效率快原因

Redis访问内存,而传统数据库(如MySQL、Oracle、SQL Server)访问硬盘。内存的读写速度远快于硬盘,这是Redis性能好的硬件基础层面原因。

1. 核心功能复杂度更低:

  • Redis核心功能比数据库简单。数据库需支持数据插入、删除、查询等复杂功能(如各类约束、事务机制),这些额外功能会带来性能开销;Redis“干得活少”,功能相对精简,减少了不必要的消耗。

2. 单线程模型的优势:

  • 单线程避免了线程竞争带来的开销。Redis基本操作是“短平快”的内存数据操作,并非高CPU消耗型任务。即便改用多线程,也难大幅提升性能,反而可能因线程切换、竞争等增加额外开销,因此单线程更高效。

3.IO多路复用机制(处理网络IO的核心)

在这里插入图片描述

  • 原理:Redis用epoll实现IO多路复用,一个线程可管理多个socket
  • TCP场景示例:服务器为每个客户端分配socket,服务大量客户端时socket众多,但多数socket并非时刻传输数据(大部分时间“静默”)。
  • 多路复用的价值:同一时刻仅少数socket活跃,IO多路复用让单线程就能高效处理多个socket,无需为每个socket开线程,极大提升IO效率。

简言之,Redis单线程高效的核心是内存存储、功能精简、单线程避竞争、IO多路复用这几个因素共同作用的结果。

二.Redis数据类型之string字符串

Redis字符串类型核心要点总结

  1. 基础地位

    • 字符串是Redis最基础的数据类型,所有键的类型均为字符串
    • 其他四种数据结构(哈希、列表、集合、有序集合)均基于字符串构建,例如它们的元素或值本质也是字符串类型,因此掌握字符串类型是学习其他数据结构的基础。
  2. 值的多样性

    • 字符串类型的值支持多种格式:
      • 普通字符串:常规文本或类似JSON、XML的结构化字符串。
      • 数字类型:包括整型和浮点型(如计数器场景)。
      • 二进制流数据:支持图片、音频、视频等任意二进制内容。
    • 单值大小限制:单个字符串值的最大容量为 512MB
  3. 二进制安全存储

    • Redis内部直接按二进制流形式存储字符串,不处理字符集编码问题。
    • 客户端传入命令时使用何种字符编码(如UTF-8、GBK等),Redis就原样存储该编码,不做任何转换或校验(就比如我们输入汉字默认就是16进制编码)。

如:
在这里插入图片描述

1.SET命令(核心字符串设置)

  1. 功能

    • 将字符串类型的value设置到指定的key中;若key已存在,则覆盖原有值(无论原数据类型是什么),且原key的TTL(生存时间)会失效
    • 若key不存在,则创建新的键值对。
  2. 基础语法

    SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
    
    • 必选参数key(键名)、value(值,字符串类型)。
    • 可选参数:通过选项控制行为和过期时间。
  3. 有效版本:Redis 1.0.0 及以上版本支持。

  4. 时间复杂度:O(1)(单次操作效率高)。

  5. 选项说明

    • 过期时间设置

在这里插入图片描述

  • EX seconds:以秒为单位设置key的过期时间(如 EX 60 表示60秒后过期)。
  • PX milliseconds:以毫秒为单位设置key的过期时间(如 PX 5000 表示5000毫秒/5秒后过期)。
  • 条件设置

在这里插入图片描述

在这里插入图片描述

  • NX:仅当key不存在时才执行设置操作(若key已存在,则不执行,返回 (nil))。

在这里插入图片描述

  • XX:仅当key存在时才执行设置操作(若key不存在,则不执行,返回 (nil))。
  1. 注意事项
    • 带选项的SET命令功能可被其他命令替代(如 SETNX 替代 NXSETEX 替代 EX),未来Redis版本可能合并相关命令。
    • 若通过选项设置条件(如 NX/XX)但条件不满足,SET不会执行,返回 (nil);若设置成功,返回 OK
SET系列其他命令
  1. SETNX(仅当key不存在时设置)

    • 功能:当key不存在时,设置键值对;若key已存在,则不执行任何操作(相当于 SET key value NX)。
    • 语法SETNX key value
    • 返回值:设置成功返回 1,key已存在未执行则返回 0
  2. SETEX(设置值并指定秒级过期时间)

    • 功能:设置key的字符串值,并同时设置过期时间(单位:秒)。
    • 语法SETEX key seconds value
    • 等价于SET key value EX seconds
  3. SETPX(设置值并指定毫秒级过期时间)(也可以是PSETEX)

    • 功能:设置key的字符串值,并同时设置过期时间(单位:毫秒)。
    • 语法SETPX key milliseconds value
    • 等价于SET key value PX milliseconds
  4. SETXX(仅当key存在时设置)

    • 功能:当key存在时,设置键值对;若key不存在,则不执行任何操作(相当于 SET key value XX)。
    • 语法SETXX key value
    • 返回值:设置成功返回 OK,key不存在未执行则返回 (nil)
    • 说明SETXX 是通过 SET key value XX 实现的显式命令形式(与 NX 对应),用于确保仅更新已存在的键,避免误创建新键。
  5. MSET(批量设置多个键值对)

在这里插入图片描述

  • 功能:一次性设置多组键值对,提升操作效率,减少网络开销。
  • 语法MSET key1 value1 key2 value2 ...
  • 时间复杂度:O(N)(N为当前命令中的key数量,通常视为O(1),因N仅针对本次命令的key数)。
  • 示例
    # 批量设置多个键值对(如用户信息)
    MSET user:1:name "Alice" user:1:age 25 user:1:role "admin"
    
  • 对比优势:相比多次执行SET(需多次网络请求),MSET通过单次请求完成批量操作,显著降低延迟。

2.GET命令(核心字符串设置)

  1. GET命令(获取字符串值)

    • 功能:获取指定key的字符串类型值;若key不存在或值非字符串类型,则报错。
    • 限制:仅支持字符串类型的value(如key对应的值是哈希、列表等,使用GET会返回类型错误)。
  2. MGET(批量获取多个键的值)

在这里插入图片描述

  • 语法MGET key1 key2 ...
  • 功能:一次性获取多个key对应的字符串值,减少网络开销。
  1. n次GET vs 单次MGET效率对比
    • n次GET:客户端需多次发送请求/接收响应,网络开销大(每次get命令单独执行)。
    • 单次MGET:客户端一次性发送请求,服务端批量处理后返回所有结果,网络开销小、效率更高(如图中流程所示)。

在这里插入图片描述
在这里插入图片描述

  • 学会使⽤批量操作,可以有效提⾼业务处理效率,但是要注意,每次批量操作所发送的键的数量也不是⽆节制的,否则可能造成单⼀命令执⾏时间过⻓,导致Redis阻塞。

注意:高危操作警告(FLUSHALL)

在这里插入图片描述

  • 功能:清空Redis中所有键值对(类似数据库的 DROP DATABASE)。
  • 风险:生产环境使用会导致数据全部丢失,务必谨慎!
  • 提示FLUSHALL 是一个快速但危险的命令,会清除Redis上所有的数据,就像删除MySQL中的整个数据库一样。

3.数值增减类命令(针对存储数字的 String)

  1. INCR key(可加负等于DECR key)

在这里插入图片描述
如果减不存在就从0开始:

在这里插入图片描述

  • 作用:将 key 中存储的数字值 原子性递增 1。若 key 不存在,先初始化为 0 再递增。
  • 要求:key 对应的值必须是整数(或可转为整数的字符串),否则报错。
  1. DECR key

在这里插入图片描述

  • 作用:将 key 中存储的数字值 原子性递减 1。逻辑同 INCR,只是方向相反。
  1. INCRBY key increment(可加负等于ECRBY key decrement)

在这里插入图片描述

  • 作用:将 key 对应的数字值 原子性增加指定的 increment(可以是正/负整数)。
  • 示例:INCRBY counter 5counter 的值 +5;INCRBY views -2 则是 -2。
  1. DECRBY key decrement

    • 作用:将 key 对应的数字值 原子性减少指定的 decrement,逻辑与 INCRBY 对应递减场景。
  2. INCRBYFLOAT key increment(可加正可加负,无DECRBYFLOAT)

在这里插入图片描述

  • 作用:将 key 对应的数字值 原子性增加指定的浮点数 increment(支持小数),逻辑与 INCRBY 对应浮点数递增场景。若 key 不存在,先初始化为 0 再执行增加操作。
  • 要求key 对应的值必须是数字(整数或浮点数,或可转为数字的字符串),否则报错。
  • 示例INCRBYFLOAT price 1.5price 的值增加 1.5(如原值为 10.0,则变为 11.5);INCRBYFLOAT score 0.1 可用于精确分数累计。

在这里插入图片描述

(**说明:**与 INCRBY 仅支持整数增减不同,INCRBYFLOAT 专为浮点数设计,适用于需要小数精度的场景,如价格计算、评分累加等;当然了都是有对应操作范围的,不能无限进行操作(incrbyfloat行但是incby不行(2的64位))。)

4. APPEND 命令

在这里插入图片描述

  • 作用:如果 key 已存在且是字符串,就把 value 追加到原值的末尾;若 key 不存在,则等同于 SET key value
  • 返回值:追加后字符串的总长度。
  • 示例:SET greeting "Hello"APPEND greeting " World!" 后,greeting 变为 “Hello World!”,返回 12。

5.截取与范围操作类命令

  1. GETRANGE key start end

在这里插入图片描述

  • 作用:返回 key 对应字符串值中,从 startend(包含两端)的子字符串。
  • 索引规则:和大多数编程语言类似,0 表示第一个字符;负数表示从末尾开始(如 -1 是最后一个字符)。
  • 示例:SET sentence "Redis is awesome"GETRANGE sentence 0 4 返回 “Redis”;GETRANGE sentence -7 -1 返回 “esome”。
  1. SETRANGE key offset value

在这里插入图片描述

  • 作用:从 key 对应字符串的 offset 位置开始,用 value 覆盖后续字符;若 offset 超出原长度,原字符串会被“填充”(用 \x00 补齐到 offset 位置后再覆盖)。
  • 注意:offset 必须 ≥ 0;若 key 不存在,会先创建一个空字符串再操作。
  • 示例:SET hello "world"SETRANGE hello 1 "ello" 后,hello 变为 “wello”(原第 1 位 o 被覆盖,后面也跟着改了)。

6.长度命令

在这里插入图片描述

STRLEN key

  • 作用:返回 key 对应字符串值的 字节长度(注意:对非 ASCII 字符,如中文,一个汉字可能占 3 字节,需留意编码影响)。
  • 示例:SET name "张三" → 若 UTF-8 编码下每个汉字 3 字节,STRLEN name 可能返回 6。

其他实用场景与注意事项

  1. 原子性与并发安全
    Redis 的 INCR/DECR 等操作是单线程 + 原子性执行,所以在高并发下计数、库存扣减等场景可以直接用,无需额外加锁。

  2. String 的“二进制安全”与编码

这里比如我们放入汉字看看会咋样:

在这里插入图片描述

发现是16进制的存储方式(utf8一个汉字3个字节),我们只需要给它启动的时候--raw(保持原态)一下:

在这里插入图片描述

当我们截取的时候会遇到问题,这里还是都按照三字节截取吧:

在这里插入图片描述

Redis String 是二进制安全的,可以存储任意二进制数据(如图片、序列化对象等);但如果是文本,要注意编码(UTF-8 等)对长度、截取的影响。

  1. 过期时间配合
    很多时候会给 String 类型的 key 设置过期时间(如 EXPIRE key seconds),常用于缓存、限流令牌等场景。

4.对应表格

在这里插入图片描述

7. Redis内部编码方式

字符串类型的内部编码有3种:

  • int:8个字节的⻓整型。
  • embstr:⼩于等于39个字节的字符串。
  • raw:⼤于39个字节的字符串。

Redis会根据当前值的类型和⻓度动态决定使⽤哪种内部编码实现。

如下:

在这里插入图片描述

8.典型使⽤场景

典型应用场景包括高频数据缓存、会话管理和计数器功能。

缓存

在这里插入图片描述

  • 用户请求首先到达Web服务层。

  • 高频/临时数据优先从Redis缓存层读取,大幅提升响应速度。

  • 缓存未命中时,回源至MySQL持久化存储查询,并将结果回填至Redis。

  • 通过精心设计的缓存更新策略(如失效策略、双删策略)确保数据的最终一致性。

具体做法:

  1. 业务假设:根据用户uid获取用户信息。
  2. 从Redis获取信息:根据uid生成Redis键“user:info:”,尝试从Redis中获取对应的值。若缓存命中(value不为null),将获取到的JSON格式值反序列化为UserInfo对象并返回。
  3. 从MySQL获取信息:若Redis缓存未命中(value为null),从MySQL数据库中根据uid查询用户信息。若数据库中也不存在该uid对应的用户信息,返回404;若存在,将查询到的UserInfo对象序列化为JSON格式,写入Redis缓存并设置过期时间为1小时(3600秒),然后返回该用户信息。

计数(Counter)功能

在这里插入图片描述

  • 用户播放视频后,视频网站获取视频数据,同时执行Redis的incr命令增加对应视频播放计数,之后以异步方式将播放量同步到统计数据仓库。

共享会话(Session)

在这里插入图片描述

  1. Session分散存储问题:在分布式Web服务中,用户Session信息(如登录信息)保存在各自服务器。但因负载均衡,用户请求可能被分配到不同服务器,无法保证每次请求都在同一台,导致用户刷新访问时可能需重新登录,影响体验。
    在这里插入图片描述

  2. Redis集中管理Session方案:使用Redis集中管理用户Session信息,只要保证Redis高可用和可扩展性,无论用户请求被负载均衡到哪台Web服务器,都能从Redis查询、更新Session信息,解决上述问题。

⼿机验证码

在这里插入图片描述

一分钟失效原理

当把验证码存到 Redis 时,同时给这个数据设置一个 60 秒(一分钟)的过期时间。用 SET 命令加 EX 参数就能实现,比如 SET 验证码键 手机验证码值 EX 60。时间一到,Redis 就会自动把这个验证码数据从内存里删掉,之后再查就查不到了,也就失效了。

一分钟不得超过 5 次原理

用 Redis 的计数功能,以手机号等能标识用户的信息作为键。每次用户请求验证码,就用 INCR 命令让这个键对应的数字加 1,代表请求次数加 1。同时给这个键设置 60 秒过期时间,比如用 EXPIRE 命令。每次请求时,先 INCR 加 1,再用 GET 命令看看当前数字。要是数字大于 5,就说明一分钟请求超 5 次了,拒绝请求;小于等于 5 就正常处理。等一分钟过了,Redis 自动删掉这个键,下次请求又重新开始计数。

过程如下(伪代码):

String 发送验证码(phoneNumber) {String key = "shortMsg:limit:" + phoneNumber;// 设置过期时间为1分钟 (60秒)// 使用 NX, 只在不存在 key 时才能设置成功boolean r = Redis 执行命令: set key 1 ex 60 nx;if (r == false) {// 说明之前设置过该手机的验证码了long c = Redis 执行命令: incr key;if (c > 5) {// 说明超过了一分钟5次的限制了// 限制发送return null;}}// 说明要么之前没有设置过手机的验证码; 要么次数没有超过5次String validationCode = 生成随机的6位数的验证码();String validationKey = "validation:" + phoneNumber;// 验证码5分钟 (300秒) 内有效Redis 执行命令: set validationKey validationCode ex 300;// 返回验证码, 随后通过手机短信发送给用户return validationCode;
}// 验证用户输入的验证码是否正确
boolean 验证验证码(phoneNumber, validationCode) {String validationKey = "validation:" + phoneNumber;String value = Redis 执行命令: get validationKey;if (value == null) {// 说明没有这个手机的验证码记录, 验证失败return false;}if (value == validationCode) {return true;} else {return false;}
}

请记住:

技术是工具,业务是目标——好方案既要懂技术实现,更要理解业务需求(甚至通过优化业务解决技术瓶颈)。

三.本篇小结

本文围绕Redis核心功能展开,首先介绍了其五大基础数据类型(字符串、哈希、列表、集合、有序集合)及底层优化机制(如编码自适应调整、Quicklist结构等),重点讲解了单线程模型的高效原理(内存存储、I/O多路复用、避免线程竞争)。随后深入解析字符串类型的核心操作(SET/GET/MSET、数值增减、追加截取等)、内部编码(int/embstr/raw)及典型应用场景(缓存加速、计数器、分布式Session、手机验证码防刷)。通过伪代码示例演示了验证码“一分钟失效+限次5次”的实战逻辑,并强调“技术需服务于业务需求”的核心思想——理解业务场景才能设计出高效合理的技术方案。

http://www.dtcms.com/a/523633.html

相关文章:

  • 【Qt | .pro文件】Qt项目文件详解:pro文件与pri文件
  • SpringAI2-Spring AI-聊天模型:ChatClient,流式编程,ChatModel
  • [MySQL] 事务和视图
  • 建设网站的特色wordpress域名网站搬家
  • 记录画图笔记
  • 【江苏政务服务网-注册_登录安全分析报告】
  • redisson介绍
  • 20251020二分总结
  • Android 基于清单文件mate-data数据共享
  • Android中Window和LayoutParams的常用属性及常用方法介绍
  • MySQL的安装与卸载
  • 单调栈详解【C/C++】
  • 智慧用电平台让安全走在事故前面
  • 自己的商标名称可以做网站名称吗单页手机网站源码
  • 做网站设计的电脑需要什么配置公司网站首页图片素材
  • Kubernetes网络通信与Pod基础详解:从架构图看K8s核心组件
  • freeRTOS学习日记
  • 划分字母区间---超全详细解
  • 【机器学习】k近邻法
  • 如何使用vscode和express开发node.js
  • Metasploit网络嗅探实战:从数据包捕获到协议分析的完整指南
  • CICD实战(11) - 使用Arbess+GitLab实现PHP项目自动化部署
  • 南京需要做网站的公司施工企业汛期应急预案
  • HarmonyOS 超级终端与服务卡片开发:打造无缝多设备交互体验
  • TeamViewer 手机版:一键远程控制,深度管理,提升多设备管理效率
  • Day70 基于 Mailbox 机制的多线程传感器数据处理系统设计与实现
  • ORM 使用说明
  • 为什么要做手机网站百媚导航app入口app入口
  • 第八章-Tomcat调试与监控
  • 算法基础篇(8)贪心算法