Redis:String 类型 内部实现、编码、命令及应用场景

String 类型是一种键值对key-value的数据结构,其中键是唯一的,值是字符串。它可以存储任何类型的数据,如文本、数字、二进制数据等。String 类型的值最大可以存储 512MB 的数据。

内部实现

Redis 没有直接使用 C 语言的字符串,而是自己实现了简单动态字符串(SDS)。SDS 是 Redis 中 String 类型的基础数据结构,它有以下特点:

  • 二进制安全 :C 语言字符串以 \0 作为字符串结束的标识,这使得它不能保存二进制数据。而 SDS 用一个 len 属性来记录字符串的长度,所以可以保存任意二进制数据。
  • 获取字符串长度的时间复杂度为 O (1) :C 语言字符串获取长度需要遍历整个字符串,时间复杂度为 O (n)。SDS 通过 len 属性直接获取长度,时间复杂度为 O (1)。
  • 避免缓冲区溢出:SDS 在修改字符串时,会先检查空间是否足够,如果不够会自动扩展空间。

简化的 SDS 结构示例:

c 复制代码
struct sdshdr {
    int len;  // 记录 buf 数组中已使用字节的数量,即字符串长度
    int free; // 记录 buf 数组中未使用字节的数量
    char buf[]; // 字节数组,用于保存字符串
};
特性 SDS (Redis 动态字符串) C语言原生字符串
结构 自定义结构,包含长度、分配空间等元信息 \0 结尾的字符数组
长度记录 独立记录字符串长度,获取长度为 O(1) 通过遍历计算字符串长度,获取长度为O(n)
二进制安全 支持任意二进制数据 ,包括 \0 不支持,遇到 \0 时认为字符串结束
动态扩展 自动扩展或缩减内存,减少内存分配次数 无动态扩展能力,需手动管理内存
内存分配策略 使用预分配策略,预留额外空间以减少扩展时的内存重新分配次数 每次重新分配内存需要拷贝数据
内存碎片 减少碎片,扩展时预留空间,缩减时可以主动释放多余内存 手动分配内存,易造成碎片
API安全性 提供丰富且安全的操作接口 (避免越界、溢出) 使用不当易越界或内存溢出
多种数据存储 支持存储普通字符串、二进制数据或其他自定义结构 仅支持以 \0 结尾的字符序列
内存浪费 可能浪费少量预分配的内存 没有预分配,可能节省内存

内部编码

不同的内部编码对 Redis 操作的性能有着显著影响。内部编码的选择直接决定了在进行读写操作、修改操作时的效率。

  • int 编码 :SDS 里的 buf 数组存储的是整数的二进制表示,而非字符形式。这一编码形式不仅减少了内存开销,还让操作性能得到提升。像 INCRDECR 这类数值操作,直接对整数进行计算,无需类型转换,时间复杂度为 O (1),高效完成操作。
  • embstr 编码:将 RedisObject 和 SDS 结构连续存于同一块内存中,是内部实现针对短字符串存储的优化方式。由于内存的连续性,在读取和写入短字符串时,只需进行一次内存分配和释放操作,减少了系统调用的开销,提高了操作性能。
  • raw 编码:RedisObject 和 SDS 结构分开存储,能处理任意长度的字符串,满足了存储长字符串的需求。不过,这种编码的内存结构相对复杂,操作时可能涉及更多的内存访问和数据拷贝,所以性能差一些。

常用命令

添加

SET

复制代码
set key value [EX seconds] [PX milliseconds] [NX|XX]
  • 将键 key 的值设置为 value。若键已存在,其值会被新值覆盖;若不存在,则创建新键值对。
  • 参数
    • EX seconds:设置键的过期时间,单位为秒。
    • PX milliseconds:设置键的过期时间,单位为毫秒。
    • NX:仅在键不存在时进行设置。
    • XX:仅在键已存在时进行更新。

MSET

复制代码
mset key value [key value ...]
  • 一次性设置多个键值对。

查找

GET

复制代码
get key
  • 获取键 key 对应value的值。若键不存在,返回 nil

MGET

复制代码
mget key [key ...]
  • 一次性获取多个键的值。若某个键不存在,对应位置返回 nil

删除

DEL

bash 复制代码
del key [key ...]
  • 删除一个或多个指定的键。

修改

APPEND

复制代码
append key value
  • value 追加到键 key 对应字符串的末尾。若键不存在,会先创建该键并将其值设置为 value

GETRANGE

复制代码
getrange key start end
  • 返回键 key 对应字符串中从 startend 位置的子字符串。索引从 0 开始,支持负数索引,-1 表示最后一个字符。

SETRANGE

复制代码
setrange key offset value
  • 从键 key 对应字符串的 offset 位置开始,用 value 覆盖原字符串的相应部分。若 offset 超出原字符串长度,会在中间填充空字符 \x00

数字操作

INCR

复制代码
incr key
  • 将键 key 对应的值(需为整数)递增 1。若键不存在,会先将其值初始化为 0,再进行递增操作。

INCRBY

复制代码
incrby key increment
  • 将键 key 对应的值(需为整数)增加指定的 increment 值。若键不存在,会先将其值初始化为 0,再进行增加操作。

DECR

复制代码
decr key
  • 将键 key 对应的值(需为整数)递减 1。若键不存在,会先将其值初始化为 0,再进行递减操作。

DECRBY

复制代码
decrby key increment
  • 将键 key 对应的值(需为整数)减少指定的 decrement 值。若键不存在,会先将其值初始化为 0,再进行减少操作。

INCRBYFLOAT

复制代码
incrbyfloat key increment
  • 将键 key 对应的值(可以是整数或浮点数)增加指定的 increment 值。若键不存在,会先将其值初始化为 0,再进行增加操作。

应用场景

缓存数据:把数据库查询结果中的对象(如用户信息、商品信息等)序列化为字符串后存储在 Redis 中。以对象的唯一标识(如用户 ID、商品 ID)作为键,序列化后的字符串作为值。这样可以避免频繁查询数据库,提升系统性能。

计数器 :例如记录用户的登录次数、文章的阅读量、点赞数等。以用户 ID 或文章 ID 作为键,使用INCR命令每次用户登录或文章被阅读、点赞时对相应的键进行加 1 操作。

共享会话(Session):Redis 常被用于存储和管理会话数据,以实现多个服务器之间的会话共享,提高系统的可扩展性和可靠性。

,提升系统性能。

计数器 :例如记录用户的登录次数、文章的阅读量、点赞数等。以用户 ID 或文章 ID 作为键,使用INCR命令每次用户登录或文章被阅读、点赞时对相应的键进行加 1 操作。

共享会话(Session):Redis 常被用于存储和管理会话数据,以实现多个服务器之间的会话共享,提高系统的可扩展性和可靠性。

分布式锁 :在分布式系统中,多个节点可能同时访问共享资源。可以利用 Redis 的SET命令结合NX参数来实现分布式锁。例如,当一个节点需要访问某个资源时,尝试使用SET lock_key "lock_value" NX命令来获取锁,如果返回成功,表示获取到锁,可以执行相应的操作;如果返回失败,表示锁已被其他节点获取,需要等待或进行其他处理。操作完成后,使用DEL命令释放锁。

相关推荐
影子24013 小时前
Navicat导出mysql数据库表结构说明到excel、word,单表导出方式记录
数据库·mysql·excel
java_heartLake4 小时前
PostgreSQL15深度解析(从15.0-15.12)
数据库·postgresql
nuc-1276 小时前
sqli-labs学习记录8
数据库·学习·sqli-labs
余华余华7 小时前
计算机等级考试数据库三级(笔记3)
服务器·数据库·oracle
南風_入弦8 小时前
Oracle logminer详解
数据库·oracle·恢复
小安同学iter9 小时前
SpringBoot (二) 日志系统
数据库·spring boot·后端
Chandler249 小时前
Redis:事务
数据库·redis·缓存
是阿建吖!10 小时前
【MySQL】事务
数据库·mysql
Asuka0710 小时前
MySQL数据库和表的操作
数据库·mysql
MasterNeverDown10 小时前
Docker Desktop 安装 Redis:轻松搭建本地缓存服务
redis·缓存·docker