【赵渝强老师】Redis中的字符串

简介: 本文详解Redis核心字符串结构SDS(Simple Dynamic String):相比C原生字符串,SDS以O(1)复杂度获取长度、杜绝缓冲区溢出、支持二进制数据,并通过柔性数组高效管理内存。同时系统介绍SET/GET/APPEND等12个常用字符串命令及实战示例。(239字)

b435.png

Redis的优势之一在于提供了丰富的数据类型,它不仅仅支持基本的Key-Value类型数据,还提供list、set、zset和hash等数据结构的存储。Redis没有直接使用C语言传统的字符串表示方式,而是自己构建了一种名为简单动态字符串的抽象类型,并将该类型用作Redis的默认字符串表示。简单动态字符串的英文是Simple Dynamic String,缩写为SDS。视频讲解如下:


Redis使用SDS表示字符串的优势在于:

  • 获取字符串的长度的事件复杂度为o(1)。
  • API安全,即通过API操作sds不会造成缓冲区溢出。
  • 每次修改字符串不一定需要进行内存分配,提高性能。
  • 可以保存文本和二进制数据。


SDS字符串的结构声明如下:

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


SDS字符串结构中的buf是一个柔性数组(Flexible Array Member),又称伸缩性数组成员,这种数组主要是为了结构体而产生的。因为开发时,偶尔需要在结构体中存放长度可变的数组,一般情况下会定义一个数组指针,在需要时分配内存使用,这样有个缺点就是,内存利用的效率很低,所以柔性数组作用就像动态数组一样,可以在结构体中存放一个长度动态的字符串。下图展示了一个使用SDS存储的字符串。

image.png


下面是在Redis中如何操作字符串。

  • SET key value
    设置指定key的值
# 对不存在的键进行设置
redis 127.0.0.1:6379> SET key "value"
OK
redis 127.0.0.1:6379> GET key
"value"
# 对已存在的键进行设置
redis 127.0.0.1:6379> SET key "new-value"
OK
redis 127.0.0.1:6379> GET key
"new-value"
  • GET key
    获取指定key的值
# 对不存在的 key 或字符串类型 key 进行 GET
redis> GET db
(nil)
redis> SET db redis
OK
redis> GET db
"redis"
# 对不是字符串类型的 key 进行 GET
redis> DEL db
(integer) 1
redis> LPUSH db redis mongodb mysql
(integer) 3
redis> GET db
(error) ERR Operation against a key holding the wrong kind of value
  • GETRANGE key start end
    返回 key 中字符串值的子字符
redis> SET mykey "This is my test key"
OK
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey 0 -1
"This is my test key"
  • GETSET key value
    将给定key的值设为value ,并返回key的旧值(old value)
redis> DEL db
(integer) 1
redis> GETSET db mongodb    # 没有旧值,返回 nil
(nil)
redis> GET db
"mongodb"
redis> GETSET db redis      # 返回旧值 mongodb
"mongodb"
redis> GET db
"redis"
  • MGET key1 [key2..]
    获取所有(一个或多个)给定key的值
redis> SET key1 "hello"
OK
redis> SET key2 "world"
OK
redis> MGET key1 key2 someOtherKey
1) "Hello"
2) "World"
3) (nil)
  • SETEX key seconds value
    将值value关联到key ,并将key的过期时间设为seconds(以秒为单位)
redis> SETEX mykey 10 redis
OK
redis> TTL mykey
10
redis> GET mykey
"redis
  • SETNX key value
    只有在key不存在时设置 key 的值
redis> EXISTS job                # job 不存在
(integer) 0
redis> SETNX job "programmer"    # job 设置成功
(integer) 1
redis> SETNX job "code-farmer"   # 尝试覆盖 job ,失败
(integer) 0
redis> GET job                   # 没有被覆盖
"programmer"
  • SETRANGE key offset value
    用value参数覆写给定key所储存的字符串值,从偏移量offset开始
redis> SET key1 "Hello World"
OK
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
  • STRLEN key
    返回key所储存的字符串值的长度
# 获取字符串的长度
redis> SET mykey "Hello world"
OK
redis> STRLEN mykey
(integer) 11
# 不存在的 key 长度为 0
redis> STRLEN nonexisting
(integer) 0
  • MSET key value [key value ...]
    同时设置一个或多个key-value对
redis> MSET key1 "Hello" key2 "World"
OK
redis> GET key1
"Hello"
redis> GET key2
1) "World"
  • MSETNX key value [key value ...]
    同时设置一个或多个key-value对,当且仅当所有给定key都不存在
# 对不存在的 key 进行 MSETNX
redis> MSETNX rmdbs "MySQL" nosql "MongoDB" key-value-store "redis"
(integer) 1
redis> MGET rmdbs nosql key-value-store
1) "MySQL"
2) "MongoDB"
3) "redis"
# MSET 的给定 key 当中有已存在的 key
redis> MSETNX rmdbs "Sqlite" language "python"  
(integer) 0                     # rmdbs键已经存在,操作失败
redis> EXISTS language          # 因为MSET是原子性操作,language没有被设置
(integer) 0
redis> GET rmdbs                # rmdbs也没有被修改
"MySQL"
  • PSETEX key milliseconds value
    这个命令和SETEX命令相似,但它以毫秒为单位设置key的生存时间,而不是像SETEX命令那样,以秒为单位
redis> PSETEX mykey 1000 "Hello"
OK
redis> PTTL mykey
999
redis> GET mykey
1) "Hello"
  • APPEND key value
    如果key已经存在并且是一个字符串,APPEND命令将指定的value追加到该key原来值(value)的末尾
# 对不存在的 key 执行 APPEND
redis> EXISTS myphone               # 确保myphone不存在
(integer) 0
redis> APPEND myphone "nokia"       # 对不存在的key进行APPEND ,等同于SET myphone "nokia"
(integer) 5                         # 字符长度
# 对已存在的字符串进行 APPEND
redis> APPEND myphone " - 1110"     # 长度从5个字符增加到12个字符
(integer) 12
redis> GET myphone
"nokia - 1110"
相关文章
|
NoSQL 网络协议 数据库
为什么 Lettuce 会带来更长的故障时间
本文详述了阿里云数据库 Tair/Redis 将使用长连接客户端在非预期故障宕机切换场景下的恢复时间从最初的 900s 降到 120s 再到 30s的优化过程,涉及产品优化,开源产品问题修复等诸多方面。
72254 11
为什么 Lettuce 会带来更长的故障时间
|
10月前
|
人工智能 安全 API
Nacos 安全护栏:MCP、Agent、配置全维防护,重塑 AI Registry 安全边界
Nacos安全新标杆:精细鉴权、无感灰度、全量审计!
3986 122
|
7月前
|
网络协议 Java 数据格式
【赵渝强老师】Docker容器的跨节点通信
本文详解Docker容器跨主机通信的三种方案,重点介绍基于Overlay网络的实现:通过ZooKeeper注册中心配置Docker集群,创建overlay网络,使不同主机上的容器能用虚拟IP直接互通,并提供完整部署步骤与验证方法。(239字)
588 3
|
3月前
|
消息中间件 存储 安全
RocketMQ 高可用创新论文入选 ACM FSE:无需复制业务数据,实现有状态服务秒级接管
面向云上有状态服务高可用,提出无需额外业务数据复制的秒级故障接管机制,在不牺牲成本和稳态性能的前提下,实现云上有状态消息服务的快速恢复。
316 17
|
10月前
|
存储 缓存 调度
阿里云Tair KVCache仿真分析:高精度的计算和缓存模拟设计与实现
在大模型推理迈向“智能体时代”的今天,KVCache 已从性能优化手段升级为系统级基础设施,“显存内缓存”模式在长上下文、多轮交互等场景下难以为继,而“以存代算”的多级 KVCache 架构虽突破了容量瓶颈,却引入了一个由模型结构、硬件平台、推理引擎与缓存策略等因素交织而成的高维配置空间。如何在满足 SLO(如延迟、吞吐等服务等级目标)的前提下,找到“时延–吞吐–成本”的最优平衡点,成为规模化部署的核心挑战。
2307 40
阿里云Tair KVCache仿真分析:高精度的计算和缓存模拟设计与实现
|
存储 NoSQL MongoDB
阿里云MongoDB 8.0最新发布
MongoDB 8.0 在性能优化、工作负载管理、数据库扩展、安全性增强及向量搜索能力等方面实现了多项突破。新版本大幅提升主从复制效率,降低延迟,并支持灵活的分片迁移与在线重分片。同时,新增 query shape 和持久化索引过滤器功能,帮助用户精细化管理高并发场景。此外,社区版引入全文与向量搜索,助力 AI 应用开发。阿里云作为国内首家支持 MongoDB 8.0 的厂商,提供高可用、弹性扩展和智能运维等云原生特性,满足多样化业务需求。
1493 26
|
NoSQL 应用服务中间件 API
Redis是如何建立连接和处理命令的
本文主要讲述 Redis 是如何监听客户端发出的set、get等命令的。
1946 160
|
9月前
|
存储 NoSQL 数据库
【上海站】SGLang和ta的朋友们:共探大模型推理新范式
本次Meetup聚焦大模型推理性能突破,SGLang、阿里云Tair KVCache、NVIDIA与千问APP团队联合分享:SGLang路线图、Tair分层存储重构、低延迟优化及投机采样等实战方案,共探无限上下文与降本增效新路径。除了技术干货,现场参与还可获得定制的开工礼包,快来提前预定席位吧!
1050 2
|
12月前
|
存储 缓存 Java
重构一个类,JVM竟省下2.9G内存?
通过重构核心类,将 `HashMap<Long, HashSet<String>>` 优化为 `Long2ObjectOpenHashMap<int[]>`,结合数据分布特征与紧凑存储,JVM 堆内存从 3.13GB 降至 211MB,降幅达 94%,验证了高效数据结构在海量场景下的巨大价值。
1050 24
重构一个类,JVM竟省下2.9G内存?
|
9月前
|
存储 运维 NoSQL
20,000核算力护航!Tair Serverless KV 助力鹰角新游《明日方舟:终末地》全球公测
上海鹰角网络(2017年成立)以《明日方舟》等精品二次元游戏闻名,2024年推出新作《明日方舟:终末地》,融合3D策略、基建经营与异步社交。为应对海量实时数据与全球流量高峰,其选用阿里云Tair Serverless KV数据库——兼具个位数毫秒响应、磁盘级持久化、全自动弹性伸缩及全球化运维能力,支撑3000万+下载的稳定运行。
1093 0