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

Redis 入门必学:String 字符串类型完全指南

文章目录Redis String 字符串完全指南从入门到实战引言一、String 的基本概念比你想的更强大1.1 什么是字符串类型1.2 字符串的命名规范二、常见命令掌握 CRUD 基本功2.1 SET 与 GET最基本的存取操作SET 命令详解GET 命令详解2.2 MGET 与 MSET批量操作的性能利器为什么批量操作更快命令详解2.3 SETNX分布式锁的基石分布式锁的简单实现2.4 SET、SETNX、SETXX 执行流程对比三、计数命令高性能计数的秘密3.1 INCR 与 DECR最简单的递增递减3.2 INCRBY 与 DECRBY自定义步长3.3 INCRBYFLOAT浮点数递增3.4 为什么 Redis 计数比数据库快四、其他实用命令字符串处理的瑞士军刀4.1 APPEND字符串追加4.2 GETRANGE 与 SETRANGE字符串切片与覆盖GETRANGE获取子字符串SETRANGE覆盖子字符串4.3 STRLEN获取字符串长度4.4 命令时间复杂度小结五、内部编码String 的三种存储方式5.1 三种内部编码详解5.2 查看内部编码5.3 为什么选择这三种编码int 编码embstr 编码raw 编码六、典型使用场景学以致用6.1 场景一缓存层Cache6.2 场景二计数器Counter6.3 场景三Session 共享6.4 场景四手机验证码七、命令速查表总结与下一步行动下一步行动建议Redis String 字符串完全指南从入门到实战引言在上一篇文章中我们已经掌握了 Redis 的全局命令和单线程架构的核心概念。这些知识为我们打下了坚实的基础。今天我们正式进入 Redis 五种数据结构的學習。首先登场的是字符串String类型——它不仅是 Redis 最基础的数据结构更是其他四种数据结构的基石。为什么这么说呢因为Redis 中所有的键key都是字符串类型而其他数据结构hash、list、set、zset的元素本质上也是字符串。这意味着学好 String就等于拿到了打开 Redis 大门的钥匙。本文我们将深入学习String 的基本概念与三大存储形式6 个最常用的字符串操作命令5 个计数器命令让你的应用具备高性能计数能力4 个实用字符串处理命令String 的三种内部编码及其选择策略4 个经典实战应用场景 核心概念Redis 的字符串是二进制安全的。这意味着你可以存储任何数据——普通文本、JSON、XML、数字甚至图片、音频、视频的二进制数据。一个字符串的最大容量是512MB。一、String 的基本概念比你想的更强大1.1 什么是字符串类型当我们用SET key value存储一个值时创建的就是字符串类型。你可能觉得这很简单——不就是存个字符串吗但 Redis 的 String 类型远比你想象的强大。让我用一个表格来展示 String 能存储的三种形式┌─────────────────────────────────────────────────────────┐ │ String 类型值的三种形式 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 普通字符串 │ hello world / 张三 │ │ 数字 │ 103、3.14159、-256 │ │ 二进制数据 │ 图片/音频/视频的二进制流 │ │ │ │ ⚠️ 最大容量512MB足够存一张高清图片 │ └─────────────────────────────────────────────────────────┘1.2 字符串的命名规范虽然 Redis 对键名没有强制要求除了不能使用一些特殊字符但为了防止键冲突和项目可维护性推荐使用以下格式设计键名推荐格式业务名:对象名:唯一标识:属性 实际示例 vs:user_info:6379 # 用户表主键为6379的用户 vs:user_info:6379:name # 该用户的名字字段 video:play_count:5253 # 视频5253的播放量 最佳实践如果只有一个业务使用 Redis可以省略业务名前缀如果键名过长团队可以使用统一的缩写规则如user:6379:friends:messages:5217→u:6379:fr:m:5217键名过长会增加内存消耗影响 Redis 性能二、常见命令掌握 CRUD 基本功 核心概念CRUDCreate、Read、Update、Delete是所有数据操作的起点。Redis String 类型提供了简洁而强大的命令来完成这些操作。2.1 SET 与 GET最基本的存取操作SET和GET是 Redis 中使用频率最高的两个命令它们构成了字符串操作的基础。SET 命令详解SET key value[EX seconds|PX milliseconds][NX|XX]SET命令有四个重要选项需要掌握选项含义使用场景EX seconds设置过期时间秒缓存场景设定数据保鲜期PX milliseconds设置过期时间毫秒精细控制过期时间的场景NX只在 key 不存在时设置实现分布式锁XX只在 key 存在时设置原子更新操作示例# 基本设置redisSET mykeyHelloOK# 设置带过期时间10秒后自动删除redisSET mykeyWill expireEX10OK# NX只在键不存在时设置适合做分布式锁redisSET lock:order:12345lockedNXOK# 设置成功# XX只在键存在时更新redisSET mykeyWorldXXOK# 更新成功GET 命令详解GET keyGET非常简洁但有两个重要特性需要注意key 不存在时返回 nil不是报错如果 key 对应的值不是字符串类型会报错# key 不存在redisGET nonexistent(nil)# 基本读取redisSET mykeyHelloOKredisGET mykeyHello# 尝试读取哈希类型的 key会报错redisHSET myhash field1value(integer)1redisGET myhash(error)WRONGTYPE Operation against a key holding the wrong kind of value 关键提示WRONGTYPE错误是新手最容易踩的坑之一。记住不同数据类型的命令不能混用。如果不确定一个 key 是什么类型先用TYPE key查看。2.2 MGET 与 MSET批量操作的性能利器当你需要读取或写入多个键时批量操作能显著提升性能。为什么批量操作更快想象一下这个场景你需要读取 1000 个用户的信息。方式一使用 1000 次 GET时间 1000次网络往返 × 1ms/次 1000次命令执行 × 0.1ms/次 1100ms方式二使用 1 次 MGET时间 1次网络往返 × 1ms/次 1000次命令执行 × 0.1ms/次 101ms性能差距10 倍以上命令详解# 批量获取MGET key[key...]# 批量设置MSET key value[key value...]示例# 批量设置redisMSET key1Hellokey2Worldkey3RedisOK# 批量获取redisMGET key1 key2 key3 nonexistent1)Hello2)World3)Redis4)(nil)# 不存在的 key 返回 nil⚠️ 注意事项批量操作的键数量不是越多越好。如果一次发送太多键可能导致 Redis 单命令执行时间过长而阻塞。建议每次批量操作控制在100-1000 个键之间。2.3 SETNX分布式锁的基石SETNXSET if Not eXists是一个条件设置命令——只在 key 不存在时才设置。这个特性使得它成为实现分布式锁的理想选择。SETNX key value返回值1 设置成功key 之前不存在0 没有设置key 已经存在示例# key 不存在设置成功redisSETNX mykeyHello(integer)1# key 已存在设置失败redisSETNX mykeyWorld(integer)0# 验证值没有被覆盖redisGET mykeyHello分布式锁的简单实现defacquire_lock(lock_name,expire_seconds10): 尝试获取分布式锁 keyflock:{lock_name}# 使用 SETNX 过期时间 原子性地获取锁resultredis.set(key,locked,nxTrue,exexpire_seconds)returnresultTruedefrelease_lock(lock_name): 释放分布式锁 keyflock:{lock_name}redis.delete(key)2.4 SET、SETNX、SETXX 执行流程对比为了帮助理解这三个命令的区别让我用流程图展示它们的执行逻辑┌─────────────────┐ │ SET key value │ └────────┬────────┘ │ ┌────────▼────────┐ │ 无论 key 是否 │ │ 存在都直接设置 │ └─────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ SET key value NX │ │ (等价于 SETNX key value) │ ├─────────────────────────────────────────────────────────────┤ │ ┌────────▼────────┐ │ key 是否存在 │ └────────┬────────┘ │ ┌──────────────┴──────────────┐ │ │ ┌──────▼──────┐ ┌──────▼──────┐ │ 存在 │ │ 不存在 │ ├─────────────┤ ├─────────────┤ │ 设置失败 │ │ 设置成功 │ │ 返回 nil │ │ 返回 OK │ └─────────────┘ └─────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ SET key value XX │ ├─────────────────────────────────────────────────────────────┤ │ ┌────────▼────────┐ │ key 是否存在 │ └────────┬────────┘ │ ┌──────────────┴──────────────┐ │ │ ┌──────▼──────┐ ┌──────▼──────┐ │ 存在 │ │ 不存在 │ ├─────────────┤ ├─────────────┤ │ 设置成功 │ │ 设置失败 │ │ 返回 OK │ │ 返回 nil │ └─────────────┘ └─────────────┘三、计数命令高性能计数的秘密 核心概念Redis 的计数器命令INCR/DECR 系列是高性能计数场景的首选。相比传统数据库的UPDATE counter counter 1Redis 的原子递增操作既简单又高效没有任何并发冲突问题。3.1 INCR 与 DECR最简单的递增递减# 递增 1INCR key# 递减 1DECR key重要特性如果 key不存在则视为 value 0然后执行递增/递减如果 key 对应的值不是整数或超出 64 位有符号整型范围会报错# key 不存在从 0 开始递增redisEXISTS mykey(integer)0redisINCR mykey(integer)1# 已存在的值递增redisSET mykey10OKredisINCR mykey(integer)11# 递减操作redisDECR mykey(integer)10# 非整数值会报错redisSET mykeynot_a_numberOKredisINCR mykey(error)value is not an integer or out of range# 超大整数会报错64位有符号整型范围-2^63 ~ 2^63-1redisSET mykey9223372036854775808OKredisINCR mykey(error)value is not an integer or out of range3.2 INCRBY 与 DECRBY自定义步长如果每次递增/递减不是 1而是需要自定义步长使用这两个命令# 递增指定数值INCRBY key increment# 递减指定数值DECRBY key decrement# 从 0 开始递增 5redisINCRBY mykey5(integer)5# 递减 3redisDECRBY mykey3(integer)23.3 INCRBYFLOAT浮点数递增如果要处理小数计数使用INCRBYFLOATINCRBYFLOAT key incrementredisSET mykey10.50OKredisINCRBYFLOAT mykey0.110.6# 支持负数实现递减redisINCRBYFLOAT mykey-55.6# 科学计数法也支持redisSET mykey5.0e3OKredisINCRBYFLOAT mykey2.0e25200 关键提示在 Redis 6.0 之前INCRBYFLOAT 的返回值可能包含尾随零如 “10.6000000000000001”。6.0 版本已经修复了这个问题返回更简洁的结果。3.4 为什么 Redis 计数比数据库快很多系统使用数据库的UPDATE counter counter 1来计数这会遇到以下问题┌─────────────────────────────────────────────────────────┐ │ 数据库计数 vs Redis 计数的对比 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 数据库方案 │ │ 1. 读取当前值 │ │ 2. 计算新值 │ │ 3. 写入新值 │ │ ⚠️ 问题高并发下可能出现「丢失更新」 │ │ │ │ Redis 方案 │ │ 1. 一个 INCR 命令原子完成递增 │ │ ✅ 优点单线程执行无并发问题天然解决 │ │ │ └─────────────────────────────────────────────────────────┘CASCompare-And-Swap问题传统数据库为了解决并发更新需要使用 CAS 机制这会增加 CPU 开销。而 Redis 的单线程架构天然避免了这个问题——所有命令顺序执行不存在任何竞争条件。四、其他实用命令字符串处理的瑞士军刀4.1 APPEND字符串追加如果 key 已存在且是字符串APPEND会将 value追加到原有字符串的末尾APPEND key value返回值追加后字符串的总长度# key 不存在效果等同于 SETredisEXISTS mykey(integer)0redisAPPEND mykeyHello(integer)5# key 已存在追加到末尾redisAPPEND mykey World(integer)11redisGET mykeyHello World 使用技巧APPEND的时间复杂度是 O(1)因为短字符串的追加可以认为是常数时间。这使得它成为构建长字符串的高效方式避免了每次都使用SET覆盖整个值。4.2 GETRANGE 与 SETRANGE字符串切片与覆盖GETRANGE获取子字符串GETRANGE key start end左闭右闭区间包含 start 和 end支持负数索引-1 表示最后一个字符-2 表示倒数第二个redisSET mykeyThis is a stringOK# 获取前4个字符redisGETRANGE mykey03This# 获取最后3个字符redisGETRANGE mykey-3-1ing# 获取整个字符串redisGETRANGE mykey0-1This is a string# 超出范围会自动调整redisGETRANGE mykey0100This is a stringSETRANGE覆盖子字符串SETRANGE key offset value从指定偏移量开始用 value 覆盖原字符串的一部分redisSET key1Hello WorldOKredisSETRANGE key16Redis(integer)11redisGET key1Hello Redis⚠️ 注意事项SETRANGE和GETRANGE的时间复杂度是 O(N)其中 N 是子字符串的长度。对于很长的字符串这些操作可能比较慢。但在实际使用中字符串通常比较短可以视为 O(1)。4.3 STRLEN获取字符串长度STRLEN keyredisSET mykeyHello worldOKredisSTRLEN mykey(integer)11# key 不存在redisSTRLEN nonexistent(integer)04.4 命令时间复杂度小结命令时间复杂度说明SETO(1)固定时间GETO(1)固定时间MGETO(N)N 为键数量MSETO(N)N 为键数量SETNXO(1)固定时间INCR/DECRO(1)固定时间INCRBY/DECRBYO(1)固定时间INCRBYFLOATO(1)固定时间APPENDO(1)追加字符串很短时STRLENO(1)固定时间GETRANGEO(N)N 为子串长度SETRANGEO(N)N 为 value 长度五、内部编码String 的三种存储方式 核心概念你用TYPE命令看到的string只是 Redis 对外展示的面孔。Redis 内部会根据数据的长度和类型自动选择最高效的编码方式来存储数据。这种优化对用户完全透明你不需要手动指定。5.1 三种内部编码详解编码类型存储形式触发条件int8字节长整型值是可以用 64 位有符号整数表示的数字embstr短字符串嵌入式值是长度 ≤ 39 字节的字符串raw长字符串值是长度 39 字节的字符串5.2 查看内部编码使用OBJECT ENCODING命令可以查看任意 key 的内部编码# 整数值 → int 编码redisSET key6379OKredisOBJECT ENCODING keyint# 短字符串 → embstr 编码redisSET keyhelloOKredisOBJECT ENCODING keyembstr# 长字符串 → raw 编码redisSET keyone string greater than 39 bytes ........OKredisOBJECT ENCODING keyraw5.3 为什么选择这三种编码int 编码优点紧凑、省内存、可直接做数学运算 适用计数器等纯数字场景embstr 编码优点连续内存分配一次分配 key value 元数据 缺点只能用于短字符串 适用短字符串、JSON 数据raw 编码优点可存储任意长度的字符串 缺点内存分配两次key 和 value 分离 适用长字符串、二进制数据 最佳实践理解内部编码帮助你在设计系统时做出更好的决策如果存储的是计数器直接用数字Redis 会自动选择最高效的int编码如果存储的是短 JSON 或配置数据长度 ≤ 39 字节时使用embstr更高效如果存储的是长文本或二进制数据Redis 会自动切换到raw编码六、典型使用场景学以致用6.1 场景一缓存层Cache场景描述在 Redis MySQL 的经典架构中Redis 作为缓存层大幅降低数据库压力。用户请求 → Web服务 → 缓存命中? │ ┌───────────┴───────────┐ │ │ 命中 未命中 │ │ 直接返回 查询MySQL 性能极佳 写入Redis 返回数据Python 实现示例importjsondefget_user_info(uid): 获取用户信息优先从缓存获取 keyfuser:info:{uid}# 1. 尝试从 Redis 获取valueredis.get(key)ifvalue:# 缓存命中user_infojson.loads(value)returnuser_info# 2. 缓存未命中查询数据库user_infodb.query(fSELECT * FROM user_info WHERE uid {uid})ifnotuser_info:returnNone# 3. 写入缓存设置1小时过期redis.setex(key,3600,json.dumps(user_info))returnuser_info效果每个用户信息一个小时只会有一次 MySQL 查询6.2 场景二计数器Counter场景描述视频播放次数、商品浏览量、接口调用次数等高频计数场景。实现defincr_video_play_count(video_id): 视频播放量 1 keyfvideo:play_count:{video_id}returnredis.incr(key)defget_video_play_count(video_id): 获取视频播放量 keyfvideo:play_count:{video_id}countredis.get(key)returnint(count)ifcountelse0架构图用户播放视频 → 触发 incr 命令 → Redis 自增 → 返回新播放量 │ ↓ 异步同步到数据仓库 不影响用户响应⚠️ 重要提示真实的计数系统还需要考虑防作弊同一用户多次播放如何计数数据持久化Redis 宕机后数据如何恢复多维度计数按天/按小时/总计如何实现高可用Redis 挂了怎么办6.3 场景三Session 共享场景描述分布式 Web 服务中多台服务器需要共享用户 Session。问题没有共享 Session 时用户可能被负载均衡到不同服务器导致刷新就需要重新登录。解决方案使用 Redis 集中管理 Session。┌─────────────────────────────────────────────────────────┐ │ 共享 Session 架构 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 用户 │ │ │ │ │ ▼ │ │ 负载均衡器Load Balancer │ │ / | \ │ │ ▼ ▼ ▼ │ │ Web服务1 Web服务2 Web服务3 │ │ \ | / │ │ └──────┼──────┘ │ │ │ │ │ ▼ │ │ ┌──────────┐ │ │ │ Redis │ ← 所有 Session 存储在这里 │ │ └──────────┘ │ │ │ └─────────────────────────────────────────────────────────┘效果无论用户被均衡到哪台服务器都能获取到同一个 Session。6.4 场景四手机验证码场景描述限制用户获取短信验证码的频率如每分钟不超过 5 次。流程用户请求验证码 → 检查发送频率限制 → 超过限制 → 是 → 拒绝 │ 否 ↓ 生成6位验证码 → 存储到Redis5分钟有效 ↓ 发送短信给用户Python 实现importrandomdefsend_verification_code(phone): 发送手机验证码 limit_keyfsms:limit:{phone}code_keyfsms:code:{phone}# 1. 检查发送频率1分钟5次限制ifredis.exists(limit_key):countredis.incr(limit_key)ifcount5:returnNone# 超过限制else:# 第一次设置限制key过期时间1分钟redis.setex(limit_key,60,1)# 2. 生成6位验证码codef{random.randint(0,999999):06d}# 3. 存储验证码5分钟有效redis.setex(code_key,300,code)returncodedefverify_code(phone,input_code): 验证用户输入的验证码 code_keyfsms:code:{phone}real_coderedis.get(code_key)ifnotreal_code:returnFalse# 验证码过期或不存在returnreal_codeinput_code七、命令速查表命令作用时间复杂度SET key value [EX|PX] [NX|XX]设置值可带选项O(1)GET key获取值O(1)MGET key [key ...]批量获取O(N)MSET key value [key value ...]批量设置O(N)SETNX key value不存在时设置O(1)INCR key递增 1O(1)DECR key递减 1O(1)INCRBY key n递增 nO(1)DECRBY key n递减 nO(1)INCRBYFLOAT key n浮点递增O(1)APPEND key value追加字符串O(1)STRLEN key获取长度O(1)GETRANGE key start end获取子串O(N)SETRANGE key offset value覆盖子串O(N)总结与下一步行动本文我们从 Redis String 的基础概念出发深入学习了✅ String 的三大存储形式普通字符串、数字、二进制数据✅ CRUD 基本功SET/GET/MGET/MSET/SETNX 的用法和适用场景✅ 高性能计数INCR/DECR 系列命令实现无锁计数✅ 字符串处理APPEND/GETRANGE/SETRANGE/STRLEN 实用工具✅ 内部编码int/embstr/raw 三种编码及选择策略✅ 四大实战场景缓存、计数器、Session 共享、手机验证码下一步行动建议 动手练习在本地启动 Redis用redis-cli练习本文所有命令 扩展阅读学习 Redis Hash哈希数据类型它是更适合存储对象的数据结构 挑战任务尝试用 Redis 实现一个简单的限流器Rate Limiter⚠️ 常见误区不要存储过大的数据String 最大 512MB但过大的值会影响网络传输和内存使用键名不要太长虽然支持但会增加内存消耗区分数据类型命令不同数据类型的命令不能混用混用会报错MGET 不要一次太多批量操作键太多可能导致 Redis 阻塞
http://www.gsyq.cn/news/1382907.html

相关文章:

  • 从零开始的web前端开发11
  • 基于Arduino与PID算法的高精度智能温控器设计与实现
  • 10款主流网盘深度对比:不限速之外,哪款更适合长期当“主力盘”?
  • Navicat连接和SQL文件都丢了?用这个注册表备份还原法,5分钟搞定恢复
  • Mac鼠标滚轮卡顿终结者:3分钟让外接鼠标获得触控板般丝滑体验
  • 大厂 Java 面试翻车实录:面试官大战水货程序员谢飞机,3轮连环拷问从 Java 核心问到 DDD
  • 哪些降重方法对知网最新算法有效?实测5款工具,避开“降重后AIGC疑似率反而上升”的坑
  • 20252821 2025-2026-2 《网络攻防实践》第8周作业
  • 华为光猫配置解密工具终极指南:5分钟快速掌握配置解密全流程
  • ImageForge - 用对话的方式,打造专业图像处理工具
  • 小白也能秒懂!CSS三种定位方式,看完就能上手写
  • 软件项目管理(5):AI 辅助开发下的审查与上线门禁
  • 程序员第一次买 AI 会员:ChatGPT、Claude、Gemini、Grok 到底该怎么选
  • 告别安装失败:详解 Quartus 13.0 和谐过程中 sys_cpt.dll 与 license.dat 的那些坑
  • 5分钟快速上手:全网资源一键下载的终极解决方案
  • 开关电源环路补偿
  • QMCDecode:突破QQ音乐加密限制,轻松解锁音乐自由的终极方案
  • 【优】B+树,Mysql优化 慢查询 执行计划 优化表结构 避免死锁 大量插入数据大数据后果
  • 通过Taotoken模型广场快速选型与测试找到适合特定任务的最佳模型
  • 开发AI应用时如何利用Taotoken平衡效果需求与API调用成本
  • 云服务器代理商:2026 年 OpenAI 智能体平台全解析 从 GPT-5.5 到 Enterprise Agent
  • 美国海派专线的运输时效受哪些因素影响? - 恒盛通物流
  • 成都摩托驾考技术全解析 专业驾校判定指南 - 奔跑123
  • 为学术研究项目构建可复现且成本可控的大模型实验平台
  • Unity InputSystem避坑指南:手机触摸屏多点触控冲突?教你用屏幕分区完美解决移动与视角控制
  • 强化学习PPO算法优化与T-PPO框架实践
  • 基于PIN光电二极管的高灵敏度辐射计设计与实现
  • python练习:人生模拟器(简易版)
  • DeepSeek重构模式推荐不是建议,是SLA级保障:实测降低重构回滚率83.6%(附A/B测试原始数据)
  • 别再死磕代码了!用这些‘非主流’工具(zsteg/minimodem)轻松搞定CTF隐写题