浅谈 Redis 数据类型

浅谈 Redis 数据类型

(一)String 类型

Redis 的 String 类型 是二进制安全的,可以用来存储 文本字符串、int 类型数据和 bitmap 位图 等数据。

1. 字符串操作

  • 适用于存储 文本、JSON、序列化数据 等任意二进制安全的内容

    命令作用示例
    SET设置键值SET name "Alice"
    GET获取值GET name"Alice"
    APPEND追加内容APPEND name " Smith""Alice Smith"
    STRLEN获取字节长度STRLEN name11
    GETRANGE截取子串GETRANGE name 0 4"Alice"
    SETRANGE覆盖部分内容SETRANGE name 6 "Taylor""Alice Taylor"
    MSET/MGET批量操作MSET k1 "v1" k2 "v2"
  • 二进制安全:可存储图片、序列化对象等任意数据

  • 自动编码:短字符串用 embstr 编码(内存连续),长字符串用 raw 编码

SETNX 操作实现分布式锁

SETNX key value
  • key 不存在 时,设置其值为 value,并返回 OK(成功);若 key 已存在,则不做任何操作,返回 nil(失败)

  • 为防止锁持有者崩溃后锁无法释放,需设置超时(通过 EXPIRE

  • 任务完成后,主动删除键以释放锁(通过 DEL

  • **【风险1】**若 SETNX 成功,但 EXPIRE 未执行(如客户端崩溃),锁会永久占用

    【解决方案】使用 ​SET 命令的 NXEX 选项​​ 原子性加锁和设置过期时间

    SET key value NX EX 10      # 原子操作:仅当不存在时设置,并过期时间为 10 秒
    
  • **【风险2】**任务未在过期时间内完成,锁被提前释放

    **【解决方案】**看门狗机制:启动后台线程定期续期

    EVAL "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('EXPIRE', KEYS[1], ARGV[2]) else return 0 end" 1 key value 10         # 每 10 秒执行一次该 LUA 脚本以续期 
    

2. 数值操作

  • 当 String 的值是 整数或浮点数 时,Redis 提供专用命令进行原子增减
命令作用示例
INCR原子 +1INCR counter1
INCRBY原子 +NINCRBY counter 56
DECR原子 -1DECR counter5
DECRBY原子 -NDECRBY counter 32
INCRBYFLOAT原子 +浮点数INCRBYFLOAT price 1.5"3.5"
  • 编码优化:数值用 int 编码(固定 8 字节),浮点数用 raw
  • 原子性:无需事务即可避免并发冲突。

3. bitmap 位图操作

  • Bitmap 是 String 的扩展,通过 位(bit)操作 实现布尔统计,可用于布隆过滤器、用户状态统计等场景
命令作用示例
SETBIT设置某位为 0/1SETBIT login:2023 100 1(用户 100 登录)
GETBIT获取某位的值GETBIT login:2023 1001
BITCOUNT统计 1 的数量BITCOUNT login:202350(50 人登录)
BITOP位运算(AND/OR/XOR)BITOP AND result login:day1 login:day2
BITPOS查找第一个 0/1 位BITPOS login:2023 1100
  • 内存高效:1 亿用户登录状态仅需约 12MB
  • 高性能:位运算复杂度 O(n),适合批量处理

4. 二进制安全与 Encoding 加速机制

  • Redis 的 String 类型基于简单动态字符串实现,数据按字节数组存储,不预设编码格式,读写时不会做任何转换
  • Redis 为 String 类型设计了多种编码格式(encoding),根据数据内容动态选择最优编码以节省内存和提高性能。通过 OBJECT ENCODING key 可查看编码类型
编码类型适用场景优化原理
int存储 64 位有符号整数(如 123直接使用整数存储,避免字符串转换。
embstr短字符串(≤44 字节,Redis 7+)内存连续分配,减少碎片,CPU 缓存友好。
raw长字符串(>44 字节)或二进制数据标准 SDS 动态分配,支持大容量数据。

(二) List 类型

Redis 的 List 类型 是一个双向链表数据结构,支持在头部和尾部高效插入、删除元素,因此可以灵活实现 栈(Stack)、队列(Queue)、数组(Array)阻塞队列(Blocking Queue) 的语义。

  • LPUSH + LPOP
  • 队列RPUSH + LPOP
  • 数组LINDEX + LSET
  • 阻塞队列RPUSH + BRPOP

以下是详细用法解析:

1. List 作为栈(Stack)

特点:后进先出(LIFO),通过 LPUSH + LPOP 实现
​适用场景​​:函数调用栈、撤销操作(Undo)记录
​操作命令​​:

# 入栈(左侧插入)
LPUSH stack "task1"
LPUSH stack "task2"  # 栈内顺序: ["task2", "task1"]# 出栈(左侧弹出)
LPOP stack  # 返回 "task2",栈剩余: ["task1"]# 查看栈顶元素(不弹出)
LINDEX stack 0  # 返回 "task1"

2. List 作为队列(Queue)

特点:先进先出(FIFO),通过 RPUSH + LPOP 实现
​适用场景​​:任务队列、消息缓冲
​操作命令​​:

# 入队(尾部插入)
RPUSH queue "msg1"
RPUSH queue "msg2"  # 队列顺序: ["msg1", "msg2"]# 出队(头部弹出)
LPOP queue  # 返回 "msg1",队列剩余: ["msg2"]# 查看队列长度
LLEN queue  # 返回 1

3. List 作为数组(Array)

特点:支持按索引访问和修改,通过 LINDEX + LSET 实现
​适用场景​​:随机访问列表元素、动态数组
​操作命令​​:

# 初始化数组
RPUSH array "a" "b" "c"  # 数组: ["a", "b", "c"]# 按索引读取(索引从0开始)
LINDEX array 1  # 返回 "b"# 按索引修改
LSET array 1 "B"  # 数组变为: ["a", "B", "c"]# 获取全部元素
LRANGE array 0 -1  # 返回 ["a", "B", "c"]

4. List 作为阻塞队列(Blocking Queue)

特点:消费者阻塞等待新元素,通过 BRPOP/BLPOP 实现
​适用场景​​:实时消息系统、任务调度(避免轮询)
​操作命令​​:

# 生产者入队(尾部插入)
RPUSH bqueue "job1" "job2"# 消费者阻塞出队(从头部获取,超时时间5秒)
BRPOP bqueue 5  
# 1) 如果队列不为空,立即返回元素(如 "job1")
# 2) 如果队列为空,阻塞 5 秒后返回nil(若期间有新元素插入则立即返回)

(三)Hash 类型

Redis 的 Hash 类型 是一个 键值对集合,适合存储对象。它比 String 类型更节省内存,且支持 字段级操作(单独读写某个字段而无需序列化整个对象)。

1. Hash 的底层结构

  • ziplist(压缩列表):当字段数和字段值较小时使用,内存连续,节省空间
  • hashtable(哈希表):字段较多或值较大时自动转换,查询效率 O(1)

2. 核心操作命令

(1)设置与获取字段值

命令作用示例
HSET设置字段值HSET user:1 name "Alice" age 30
HGET获取字段值HGET user:1 name"Alice"
HMSET批量设置字段HMSET user:1 name "Alice" age 30
HMGET批量获取字段HMGET user:1 name age["Alice", "30"]
HGETALL获取所有字段和值HGETALL user:1["name", "Alice", "age", "30"]
  • 示例
HSET product:1001 name "iPhone" price 999 stock 50
HGET product:1001 price  # 返回 "999"
HGETALL product:1001     # 返回所有字段和值

(2)字段增减与删除

命令作用示例
HINCRBY字段值整数增减HINCRBY user:1 age 1
HINCRBYFLOAT字段值浮点数增减HINCRBYFLOAT account:1 balance 50.5
HDEL删除字段HDEL user:1 age
HEXISTS判断字段是否存在HEXISTS user:1 name1(存在)
  • 示例
HINCRBY product:1001 stock -1  # 库存减1
HDEL product:1001 price        # 删除价格字段

(3)查询与统计

命令作用示例
HKEYS获取所有字段名HKEYS user:1["name", "age"]
HVALS获取所有字段值HVALS user:1["Alice", "30"]
HLEN获取字段数量HLEN user:12
HSTRLEN获取字段值的字节长度HSTRLEN user:1 name5("Alice"占 5 字节)
  • 示例
HKEYS product:1001   # 返回 ["name", "price", "stock"]
HLEN product:1001    # 返回 3

(4)原子操作

命令作用示例
HSETNX字段不存在时才设置HSETNX user:1 email "alice@example.com"
HSCAN增量迭代字段(大数据量时避免阻塞)HSCAN user:1 0
  • 示例
HSETNX user:1 email "alice@example.com"  # 仅当 email 不存在时设置

3. 对象的三种存储策略:单 key 存储、多 key 存储、使用 hash 类型

(1)序列化为字符串(单 Key 存储)

SET user:1000 '{"name":"Alice","age":30,"email":"alice@example.com"}'

(2)每个字段单独存储(多 Key 存储)

SET user:1000:name "Alice"
SET user:1000:age 30
SET user:1000:email "alice@example.com"

(3)使用 Hash 类型

HSET user:1000 name "Alice" age 30 email "alice@example.com"

(4)三种策略比较

维度序列化为字符串多 Key 存储Hash 类型
读写效率整体读写快,部分更新慢部分读写快,整体查询慢部分和批量读写均快
内存占用低(单个 Key)高(每个 Key 有元数据)中(小 Hash 用 zip list)
原子性高(整个对象原子操作)低(需事务)中(单字段操作原子)
字段级 TTL不支持支持不支持
适用字段规模任意少量字段中小规模字段
复杂结构支持支持(JSON 等序列化方式)需额外设计需序列化字段值

(四)Set 类型

Redis 的 Set 类型 是一个 无序、去重的集合,底层基于哈希表实现,支持插入、删除元素以及多个集合的交并差集运算,同时提供了随机返回指定个数元素的功能。

1. Set 的核心特性

  • 无序性:元素没有固定顺序,遍历时顺序不确定
  • 唯一性:自动去重,重复插入的元素会被忽略

2. 常用命令

(1)基本操作

命令作用示例
SADD添加元素(自动去重)SADD tags "redis" "db"
SREM删除元素SREM tags "db"
SMEMBERS获取所有元素SMEMBERS tags
SISMEMBER判断元素是否存在SISMEMBER tags "redis"1(存在)
SCARD获取集合元素数量SCARD tags2
SRANDMEMBER随机返回元素(可指定数量)SRANDMEMBER tags 2
  • 示例
SADD users:1000:followers "user1" "user2" "user3"
SMEMBERS users:1000:followers  # 返回 ["user1", "user2", "user3"]
SISMEMBER users:1000:followers "user1"  # 返回 1(存在)

(2)集合运算

命令作用示例
SINTER返回多个集合的交集SINTER set1 set2
SUNION返回多个集合的并集SUNION set1 set2
SDIFF返回第一个集合与其他集合的差集SDIFF set1 set2
SINTERSTORE存储交集到新集合SINTERSTORE result set1 set2
SUNIONSTORE存储并集到新集合SUNIONSTORE result set1 set2
SDIFFSTORE存储差集到新集合SDIFFSTORE result set1 set2
  • 示例
SADD group1 "user1" "user2" "user3"
SADD group2 "user2" "user3" "user4"
SINTER group1 group2  # 返回 ["user2", "user3"](共同成员)
SDIFF group1 group2   # 返回 ["user1"](仅在 group1 中的成员)

(3)随机返回元素

  • Redis 的 Set 类型提供了 随机返回元素 的功能,适用于 抽奖、随机推荐、随机选取样本 等场景
SRANDMEMBER key count
  • key:Set 的键名
  • count:指定返回的元素数量
    • count > 0:返回 不重复 的元素(最多返回整个 Set 的大小)
    • count < 0:返回元素可能 重复(适用于允许重复抽奖的场景)

(五)Sorted Set 类型

Redis 中的 Sorted Set 类型 也是一种集合类型,集合中的元素可以按照自定义分值排序,底层基于跳表实现。

1. 特点

  • 唯一性:成员(member)不可重复,但分数(score)可重复
  • 有序性:按 score 排序(默认升序),相同 score 按字典序排序

2. 核心命令

  • 成员操作命令

    命令功能
    ZADD key score member添加/更新成员(支持NX/XX/INCR选项)
    ZREM key member删除指定成员
    ZINCRBY key increment member增加成员分数
    ZSCORE key member获取成员分数
  • 查询命令

    命令功能
    ZRANGE key start stop按分数升序返回成员(WITHSCORES显示分数)
    ZREVRANGE key start stop按分数降序返回成员
    ZRANGEBYSCORE key min max返回分数在 [min,max] 区间的成员
  • 排名统计命令

    命令功能
    ZRANK key member获取成员升序排名(从 0 开始)
    ZREVRANK key member获取成员降序排名
    ZCARD key返回成员总数
    ZCOUNT key min max统计分数范围内的成员数
  • 集合运算命令

    计算多个有序集合的并集存储(交集存储)

    ZUNIONSTORE/ZINTERSTORE destkey numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

    • 必选参数

      • destkey:存储结果的键名
      • numkeys:参与计算的集合数量(后续需对应数量的 key
      • key:参与计算的集合键名(至少一个)
    • 可选参数

      • WEIGHTS:为每个集合的分值设置权重(默认权重为 1
      • AGGREGATE:合并重复成员的分值策略(SUM 求和、MIN 取最小、MAX 取最大,默认 SUM
    • 示例

    ZADD scores1 10 "Alice" 20 "Bob"
    ZADD scores2 5 "Alice" 30 "Charlie"
    ZUNIONSTORE result 2 scores1 scores2 WEIGHTS 2 3 SUM
    
    • Alice 的分值: 10 * 2 + 5 * 3 = 35

    • Bob 的分值 = 20 * 2 = 40

    • Charlie 的分值 = 30 * 3 = 90

    1) "Alice"   35
    2) "Bob"     40
    3) "Charlie" 90
    

3. 底层实现

Sorted Set 是 Redis 中最复杂的数据结构之一。它通过 跳表和哈希表 的混合实现,兼顾了高效查询和动态排序的能力。

编码方式数据结构触发条件特点
ziplist压缩列表 [member1, score1, member2, score2, ...]元素数量 ≤ zset-max-ziplist-entries(默认128)且所有元素长度 ≤ zset-max-ziplist-value(默认64字节)内存紧凑,但增删效率低(O(n))
skiplist + dict跳表 + 哈希表不满足 ziplist 条件时自动转换支持高效查询和范围操作(O(log n))
  • 哈希表与跳表的协同

    跳表保证有序性,哈希表加速单成员查询,两者互补

  • 内存与 CPU 的权衡

    小数据用 ziplist 节省内存,大数据用 skiplist 提升操作效率

(1)跳表的结构

  • 跳表(Skip List)是一种基于 多层有序链表 的数据结构,通过 概率平衡 实现高效的动态操作(平均 O(log n) 时间复杂度)

  • 跳表由多层链表组成,每层链表都是有序的,但高层链表是低层链表的【快速通道】:

    • 最底层链表:包含所有元素的有序链表

    • 高层链表:每层节点数约为下一层的一半,形成跳跃路径

(2)查找原理:平均 O(log n)(最坏 O(n)

  • 从最高层头节点开始,向右遍历:

    • 若当前节点的下一个节点值 ≤ 目标值,则继续向右

    • 若下一个节点值 > 目标值,则向下移动到下一层

  • 重复上述过程,直到最底层,找到目标节点或确认不存在

(3)插入原理:平均 O(log n)

  • 查找插入位置,记录每一层的前驱节点,即插入位置左侧的节点
  • 随机生成层高,每个新插入节点的层数由 概率决定,通常采用 “抛硬币”策略
    1. 初始层高:新节点至少在第 0 层(最底层,包含所有节点)
    2. 逐层晋升:每次“抛硬币” 若为“正面”(概率通常为 50%)则层数 +1;否则停止
    3. Redis 优化:降低晋升概率(p=0.25)和限制最大层数(32),平衡性能与内存开销
  • 在每一层(从生成的最高层到最底层)链表中插入新节点,并更新前后节点的指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day1 时间复杂度

一 概念 在 C 中&#xff0c;时间复杂度是衡量算法运行时间随输入规模增长的趋势的关键指标&#xff0c;用于评估算法的效率。它通过 大 O 表示法&#xff08;Big O Notation&#xff09; 描述&#xff0c;关注的是输入规模 n 趋近于无穷大时&#xff0c;算法时间增长的主导因…

PAC文件:智能代理配置的瑞士军刀

在日常上网和企业网络环境中&#xff0c;我们经常需要配置代理服务器来访问特定资源、增强安全性或管理网络流量。Windows和macOS系统自带的代理配置通常提供全局代理或简单的排除列表&#xff0c;这在某些复杂场景下显得不够灵活。例如&#xff0c;我们可能只想代理某个特定的…

获取高德地图JS API的安全密钥和Key的方法

要使用高德地图JavaScript API&#xff0c;您需要获取API Key和安全密钥(securityJsCode)。以下是获取步骤&#xff1a; 1. 注册高德开放平台账号 首先访问高德开放平台&#xff0c;如果没有账号需要先注册。 2. 创建应用获取Key 登录后进入"控制台" 点击"应…

携程酒店 phantom-token token1004 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 部分python代码 搞APP搞的心态有点崩…

小红书多账号运营效率优化:技术方案与自动化实践

目录 一、效率瓶颈与流程优化方向 二、技术实现方案与效率提升路径 1. 多账号统一管理&#xff1a;环境隔离与批量操作 2. 自动化任务设计&#xff1a;RPA与脚本化执行 四、效果验证与数据对比 五、总结与开源工具推荐 六、下载地址&#xff1a; 一、效率瓶颈与流程优化…

FastDDS Transport功能模块初步整理

一. 总体结构 二. 主要类的功能 2.1 TransportDescriptor和TransportInterface ​ FastDDS中整个Transport类的设计遵循的是设计模式中的建造者模式&#xff0c;其中&#xff0c;TransportDescriptor就是建造者&#xff0c;而TransportInterface则是建造出来的产品。 ​ Tra…

zabbix最新版本7.2超级详细安装部署(一)

如果文章对你有用&#xff0c;请留下痕迹在配置过程中有问题请及时留言&#xff0c;本作者可以及时更新文章 目录 1、提前准备环境 2、zabbix7.2安装部署 3、安装并配置数据库 4、为Zabbix server配置数据库 5、为Zabbix前端配置PHP 6、启动Zabbix server和agent进程 7、关闭防…

CodeBlocks调试报错

尝试打断点&#xff0c;并且点击红色箭头启动debugger时&#xff0c;控制台报错 Active debugger config: GDB/CDB debugger:Default Building to ensure sources are up-to-date Selecting target: Debug Adding source dir: C:\Users\Lenovo\Desktop\exercise\ Adding source…

Manus 开放注册:AI 智能体领域的新起点

2025 年 5 月 13 日成为了一个具有特殊意义的日子 —— 备受瞩目的 AI 智能体平台 Manus&#xff08;Manus&#xff09;正式宣布开放注册。这一消息犹如一颗重磅炸弹&#xff0c;瞬间在全球科技圈引起了广泛关注和热烈讨论。在此之前&#xff0c;Manus 一直以其独特的魅力和极高…

车载网关作为车辆网络系统的核心枢纽

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 钝感力的“钝”&#xff0c;不是木讷、迟钝&#xff0c;而是直面困境的韧劲和耐力&#xff0c;是面对外界…

俄罗斯方块算法2025.5.10

问题描述 俄罗斯方块&#xff08;Tetris&#xff09;作为风靡全球38年的现象级益智游戏&#xff0c;其简单易学但难于精通的特性使其成为游戏史上的不朽经典。以下是其核心游戏规则解析及我们的要求&#xff1a; 游戏界面由20行10列的可视区域组成&#xff0c;7种不同形状的四…

Femap许可网络配置

电磁仿真领域&#xff0c;Femap以其卓越的性能和广泛的应用场景&#xff0c;成为众多工程师和科研人员的首选工具。为了满足多用户协作的需求&#xff0c;Femap提供了灵活的网络配置方案。本文将详细介绍Femap许可网络配置的方法和优势&#xff0c;帮助您轻松实现多用户高效协作…

计算机视觉----时域频域在图像中的意义、傅里叶变换在图像中的应用、卷积核的频域解释

1、时域&#xff08;时间域&#xff09;——自变量是时间,即横轴是时间,纵轴是信号的变化。其动态信号x&#xff08;t&#xff09;是描述信号在不同时刻取值的函数。 2、频域&#xff08;频率域&#xff09;——自变量是频率,即横轴是频率,纵轴是该频率信号的幅度,也就是通常说…

主流高防服务器技术对比与AI防御方案实战

1. 高防服务器核心能力对比 当前市场主流高防服务商&#xff08;如阿里云、腾讯云、华为云&#xff09;的核心防御能力集中在流量清洗与静态规则防护&#xff0c;但面临以下挑战&#xff1a; 静态防御瓶颈&#xff1a;传统方案依赖预定义规则&#xff0c;对新型攻击&#xff…

常时间运行的程序 导致系统卡顿 自动监控系统CPU和内存利用率 自动选择 内存回收 软件重启 电脑重启

长时间运行安防系统&#xff0c;导致CPU或内存利用率超80%&#xff0c;使得电脑变的缓慢、卡顿的问题。定时获取CPU和内存利用率的数据&#xff0c;在不同时间段&#xff08;如凌晨与平时&#xff09;&#xff0c;根据利用率的不同的阈值&#xff0c;进行&#xff1a;内存回收(…

OpenCV播放摄像头视频

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 播放摄像头视频和播放视频文件类似&#xff0c;也是通过类VideoCapture来实现&#xff0c;只不过调用open的时候传入的是摄像头的索引号。如果计算机安装了一个摄像头&#xff0c;则open的第一个参数通常是0&…

操作系统:内存管理

目录 1、主要目标 2、核心概念和技术 2.1 物理内存与虚拟内存 2.2 内存分页机制 2.3 页面置换算法 3、监控与性能优化 3.1 查看物理内存 3.2 查看虚拟内存 3.3 性能问题 1> 内存不足&#xff08;OOM&#xff09; 2> 内存泄漏 3> 内存碎片 3.4 性能优化策…

专题四:综合练习( 找出所有子集的异或总和再求和)

以leetcode1863题为例 题目分析&#xff1a; 找到每个子集&#xff0c;然后子集中的元素异或之后全部相加 算法原理分析&#xff1a; 画决策树&#xff1a;第一层为这个子集有一个元素 第二层这个子集有两个元素 从上往下罗列&#xff0c;把所有子集都罗列出来&#xf…

【python】—conda新建python3.11的环境报错

1.报错 conda create -n py3.11 python3.11 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ Collecting package metadata: done Solving environment: failed PackagesNotFoundError: The following packages are not available from current channel…

RabbitMQ事务机制

在RabbitMQ中&#xff0c;生产者为了确保消息发送成功&#xff0c;一种是使用 confirm 确认机制&#xff0c;另一种就是使用事务机制&#xff0c;事务机制就是允许生产者在发送消息时&#xff0c;将多个消息操作作为一个原子单元进行处理&#xff0c;要么所有操作都成功执行&am…