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

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 结构示例:

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),高效完成操作。
image.png
  • embstr 编码:将 RedisObject 和 SDS 结构连续存于同一块内存中,是内部实现针对短字符串存储的优化方式。由于内存的连续性,在读取和写入短字符串时,只需进行一次内存分配和释放操作,减少了系统调用的开销,提高了操作性能。

image.png

  • raw 编码:RedisObject 和 SDS 结构分开存储,能处理任意长度的字符串,满足了存储长字符串的需求。不过,这种编码的内存结构相对复杂,操作时可能涉及更多的内存访问和数据拷贝,所以性能差一些。
image.png

常用命令

添加

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

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命令释放锁。


http://www.kler.cn/a/612476.html

相关文章:

  • ESP32-C3物联网方案,智能设备创新升级,无线交互控制通信应用
  • Rk3568驱动开发_设备树点亮LED_10
  • 【机器学习】基础知识
  • 数据库基础知识点(系列三)
  • deepseek+在线markdown生成pdf文件
  • Spring Boot 项目常见漏洞与安全最佳实践
  • Maven工具学习使用(五)——生命周期和插件
  • 【基础】Windows 中通过 VSCode 使用 GCC 编译调试 C++
  • 【深度学习】Cross-Attention(交叉注意力)机制详解与应用
  • python将整个txt文件写入excel的一个单元格?
  • Github 2025-03-24 开源项目周报 Top12
  • 从技术架构和生态考虑,不是单纯的配置优化,还有哪些方式可以提高spark的计算性能
  • Linux 系统检测进程死锁的方法
  • Python----计算机视觉处理(Opencv:模板匹配)
  • leetcode_704. 二分查找_java
  • 1字节(8位)表示8个状态位
  • spring @Autowired对属性、set方法,构造器的分别使用,以及配合 @Autowired 和 @Qualifier避免歧义性的综合使用案例
  • 通过 ECNWP 洋流、海浪可视化开发的方法和架构
  • 【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】
  • Windows10清理机器大全集