Redis 数据结构和使用详解(带示例)
Redis 支持的主要数据结构及其对应操作命令的详细解释,结合具体使用场景和示例:
1. 字符串(String)
-
用途:存储文本、数值或二进制数据,适用于缓存、计数器等。
-
常用命令:
SET key value:设置键值对。GET key:获取键对应的值。INCR key:将键的值递增1(原子操作)。EXPIRE key seconds:设置键的过期时间。
-
示例:
SET user:1001:name "Alice" # 存储用户名 GET user:1001:name # 返回 "Alice" INCR article:123:views # 文章阅读量+1 -
场景 1:缓存用户 Token
# 存储 Token,有效期 1 小时 SET user:1001:token "abc123" EX 3600 # 返回:OK# 获取 Token GET user:1001:token # 返回:"abc123"# 检查剩余过期时间 TTL user:1001:token # 返回:3590(剩余秒数) -
场景 2:计数器(文章阅读量)
# 初始化阅读量 SET article:2001:views 0 # 返回:OK# 阅读量 +1 INCR article:2001:views # 返回:1(递增后的值)# 批量递增(+5) INCRBY article:2001:views 5 # 返回:6 -
场景 3:分布式锁
# 尝试获取锁(有效期 10 秒) SET order:lock "process123" NX PX 10000 # 返回:OK(获取成功)或 nil(失败)# 释放锁(需值匹配) EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 order:lock process123 # 返回:1(删除成功)或 0(失败)
2. 哈希(Hash)
-
用途:存储对象字段,适合保存用户信息、商品属性等结构化数据。
-
常用命令:
HSET key field value:设置哈希字段值。HGET key field:获取哈希字段值。HGETALL key:获取所有字段和值。
-
示例:
HSET user:1001 age 30 email "alice@example.com" # 存储用户信息 HGET user:1001 age # 返回 "30" HGETALL user:1001 # 返回所有字段和值 -
场景 1:存储用户信息
# 添加用户字段 HSET user:1001 name "Alice" age 30 email "alice@example.com" # 返回:3(添加的字段数)# 获取单个字段 HGET user:1001 name # 返回:"Alice"# 获取所有字段 HGETALL user:1001 # 返回: # 1) "name" # 2) "Alice" # 3) "age" # 4) "30" # 5) "email" # 6) "alice@example.com" -
场景 2:商品库存管理
# 设置商品库存 HSET product:5001 stock 100 price 2999 # 返回:2# 扣减库存(原子操作) HINCRBY product:5001 stock -1 # 返回:99# 获取价格 HGET product:5001 price # 返回:"2999" -
场景 3:配置中心
# 存储服务配置 HSET service:config timeout 5000 retry 3 enable_cache true # 返回:3# 修改配置 HSET service:config timeout 10000 # 返回:0(字段已存在,仅更新)# 删除配置字段 HDEL service:config retry # 返回:1
3. 列表(List)
-
用途:实现消息队列、最新消息列表(如微博时间线)。
-
常用命令:
LPUSH key value:从列表左侧插入元素。RPOP key:从列表右侧弹出元素。LRANGE key start end:获取列表范围内的元素。
-
示例:
LPUSH news:latest "Article 1" # 插入最新新闻 LPUSH news:latest "Article 2" LRANGE news:latest 0 4 # 获取前5条新闻 -
场景 1:消息队列
# 生产者推送任务 LPUSH task:queue "send_email:user1" "generate_report:user2" # 返回:2(队列长度)# 消费者获取任务 RPOP task:queue # 返回:"send_email:user1"# 查看队列剩余任务 LRANGE task:queue 0 -1 # 返回:1) "generate_report:user2" -
场景 2:最新消息列表
# 插入最新新闻 LPUSH news:latest "Article 3" "Article 2" "Article 1" # 返回:3# 获取前 2 条新闻 LRANGE news:latest 0 1 # 返回: # 1) "Article 1" # 2) "Article 2" -
场景 3:阻塞队列
# 消费者阻塞等待任务(超时 10 秒) BRPOP task:queue 10 # 返回(如果有任务): # 1) "task:queue" # 2) "generate_report:user2"
4. 集合(Set)
-
用途:存储唯一元素,支持交集、并集操作(如共同好友、标签系统)。
-
常用命令:
SADD key member:添加元素到集合。SMEMBERS key:获取集合所有元素。SINTER key1 key2:计算多个集合的交集。
-
示例:
SADD user:1001:follows 2001 2002 # 用户1001关注2001和2002 SADD user:1002:follows 2001 2003 SINTER user:1001:follows user:1002:follows # 返回共同关注用户2001 -
场景 1:标签系统
# 添加文章标签 SADD article:3001:tags "tech" "redis" "database" # 返回:3# 查找共同标签 SINTER article:3001:tags article:3002:tags # 返回(假设 article:3002 有 "tech" 和 "cloud"): # 1) "tech" -
场景 2:抽奖活动
# 添加参与者 SADD lottery:2023 "user100" "user200" "user300" # 返回:3# 随机抽取 1 名中奖者 SRANDMEMBER lottery:2023 # 返回:"user200"(随机结果)# 移除并返回中奖者 SPOP lottery:2023 # 返回:"user100" -
场景 3:黑白名单
# 添加黑名单用户 SADD blacklist:ip "192.168.1.1" "192.168.1.2" # 返回:2# 检查 IP 是否在黑名单 SISMEMBER blacklist:ip "192.168.1.1" # 返回:1(存在)
5. 有序集合(Sorted Set)
-
用途:排行榜、优先级队列(按分数排序)。
-
常用命令:
ZADD key score member:添加带分数的成员。ZRANGE key start end [WITHSCORES]:按分数升序返回成员。ZREVRANGE key start end:按分数降序返回成员。
-
示例:
ZADD game:leaderboard 1500 "PlayerA" # 添加玩家分数 ZADD game:leaderboard 2000 "PlayerB" ZREVRANGE game:leaderboard 0 9 WITHSCORES # 返回前10名玩家 -
场景 1:游戏排行榜
# 添加玩家分数 ZADD game:leaderboard 1500 "PlayerA" 2000 "PlayerB" 1800 "PlayerC" # 返回:3# 获取前 3 名(降序) ZREVRANGE game:leaderboard 0 2 WITHSCORES # 返回: # 1) "PlayerB" # 2) "2000" # 3) "PlayerC" # 4) "1800" # 5) "PlayerA" # 6) "1500" -
场景 2:延时任务
# 添加任务(时间戳为分数) ZADD tasks:delayed 1672531200 "task1" 1672617600 "task2" # 返回:2# 获取当前需处理的任务(分数 <= 当前时间戳) ZRANGEBYSCORE tasks:delayed -inf 1672531200 # 返回:1) "task1" -
场景 3:热搜榜单
# 更新关键词热度 ZINCRBY hot:keywords 1 "redis" # 返回:"1"(当前分数)ZINCRBY hot:keywords 1 "java" # 返回:"1"# 获取 Top 10 热搜词 ZREVRANGE hot:keywords 0 9 WITHSCORES # 返回: # 1) "redis" # 2) "1" # 3) "java" # 4) "1"
6. 地理位置(GEO)
-
用途:存储和查询地理位置(附近的人、商家)。
-
常用命令:
GEOADD key longitude latitude member:添加地理坐标。GEODIST key member1 member2 [unit]:计算两地距离。GEORADIUS key longitude latitude radius unit:查找范围内的成员。
-
示例:
GEOADD restaurants 116.404269 39.913818 "RestaurantA" # 添加餐厅坐标 GEORADIUS restaurants 116.405 39.914 2 km WITHDIST # 查找2公里内的餐厅 -
场景 1:附近餐厅查询
# 添加餐厅坐标 GEOADD restaurants 116.404269 39.913818 "RestaurantA" 116.407531 39.915264 "RestaurantB" # 返回:2# 查找 1 公里内的餐厅 GEORADIUS restaurants 116.405285 39.912987 1 km WITHDIST # 返回: # 1) 1) "RestaurantA" # 2) "0.8923" -
场景 2:计算距离
# 计算两餐厅距离 GEODIST restaurants "RestaurantA" "RestaurantB" km # 返回:"0.312"(公里) -
场景 3:获取坐标
# 获取餐厅坐标 GEOPOS restaurants "RestaurantA" # 返回: # 1) 1) "116.404269" # 2) "39.913818"
7. 位图(Bitmap)
-
用途:位操作(如用户签到、活跃统计)。
-
常用命令:
SETBIT key offset value:设置位的值(0或1)。GETBIT key offset:获取位的值。BITCOUNT key:统计值为1的位数。
-
示例:
SETBIT user:1001:sign:202310 5 1 # 用户1001在10月6日签到 BITCOUNT user:1001:sign:202310 # 统计本月签到天数 -
场景 1:用户签到
# 用户 1001 在 10 月 1 日签到(偏移量 0) SETBIT user:1001:sign:202310 0 1 # 返回:0(之前位的值)# 检查 10 月 1 日是否签到 GETBIT user:1001:sign:202310 0 # 返回:1 -
场景 2:活跃用户统计
# 统计 10 月累计签到天数 BITCOUNT user:1001:sign:202310 # 返回:3(假设签到 3 天) -
场景 3:权限控制
# 设置权限位(位 0: 读,位 1: 写) SETBIT user:1001:permissions 0 1 SETBIT user:1001:permissions 1 0 # 检查写权限 GETBIT user:1001:permissions 1 # 返回:0(无权限)
8. HyperLogLog
-
用途:近似去重计数(如统计UV)。
-
常用命令:
PFADD key element:添加元素。PFCOUNT key:统计唯一元素数量。
-
示例:
PFADD daily_uv:20231001 "user1" "user2" # 记录当日访问用户 PFCOUNT daily_uv:20231001 # 返回近似UV数 -
场景 1:UV 统计
# 记录用户访问 PFADD daily_uv:20231001 "user1" "user2" "user1" # 返回:1(新增唯一用户数)# 获取当日 UV PFCOUNT daily_uv:20231001 # 返回:2 -
场景 2:合并多日 UV
# 合并 10 月 1 日和 2 日的 UV PFMERGE weekly_uv:20231001-07 daily_uv:20231001 daily_uv:20231002 # 返回:OK# 获取周 UV PFCOUNT weekly_uv:20231001-07 # 返回:5(假设两日共有 5 个唯一用户)
9. 流(Stream)
-
用途:消息队列(支持消费者组、消息持久化)。
-
常用命令:
XADD key * field1 value1:添加消息。XREAD COUNT num STREAMS key $:读取消息。XGROUP CREATE key groupname $:创建消费者组。
-
示例:
XADD order:stream * user "Alice" product "Phone" # 发布订单消息 XREAD COUNT 10 STREAMS order:stream 0 # 读取消息 -
场景 1:订单消息队列
# 发布订单消息 XADD orders:* user_id 1001 product_id 2001 status "created" # 返回:"1672531200000-0"(消息 ID)# 读取最新消息 XREAD COUNT 1 STREAMS orders:* # 返回: # 1) 1) "orders:*" # 2) 1) 1) "1672531200000-0" # 2) 1) "user_id" # 2) "1001" # 3) "product_id" # 4) "2001" # 5) "status" # 6) "created" -
场景 2:消费者组
# 创建消费者组 XGROUP CREATE orders:stream order_group $ # 返回:OK# 消费者读取消息 XREADGROUP GROUP order_group consumer1 COUNT 1 STREAMS orders:stream > # 返回:同上消息内容
10. 发布/订阅(Pub/Sub)
-
用途:消息广播(如实时通知、聊天室)。
-
常用命令:
PUBLISH channel message:发布消息到频道。SUBSCRIBE channel:订阅频道。
-
示例:
SUBSCRIBE news_updates # 订阅新闻频道 PUBLISH news_updates "Redis 7.0 released!" # 发布新闻 -
场景 1:实时通知
# 订阅新闻频道 SUBSCRIBE news # 返回: # 1) "subscribe" # 2) "news" # 3) (integer) 1# 发布新闻 PUBLISH news "Redis 7.0 released!" # 订阅者接收: # 1) "message" # 2) "news" # 3) "Redis 7.0 released!" -
场景 2:多频道订阅
# 订阅多个频道 PSUBSCRIBE news.* # 发布到 news.tech PUBLISH news.tech "New Redis features" # 订阅者接收: # 1) "pmessage" # 2) "news.*" # 3) "news.tech" # 4) "New Redis features"
总结
通过以上示例,可以得出如下总结:
| 数据结构 | 典型场景 | 核心命令 |
|---|---|---|
| String | 缓存、计数器 | SET, GET, INCR |
| Hash | 对象存储 | HSET, HGET, HGETALL |
| List | 消息队列、最新列表 | LPUSH, RPOP, LRANGE |
| Set | 标签、共同好友 | SADD, SMEMBERS, SINTER |
| Sorted Set | 排行榜、优先级任务 | ZADD, ZRANGE, ZREVRANGE |
| GEO | 地理位置查询 | GEOADD, GEORADIUS |
| Bitmap | 用户签到、布尔统计 | SETBIT, GETBIT, BITCOUNT |
| HyperLogLog | 大数据去重计数 | PFADD, PFCOUNT |
| Stream | 消息队列(支持消费者组) | XADD, XREAD, XGROUP |
| Pub/Sub | 实时消息广播 | PUBLISH, SUBSCRIBE |
通过合理选择数据结构和命令,可以高效解决缓存、实时统计、消息通信等多样化需求。
相关文章:
Redis 数据结构和使用详解(带示例)
Redis 支持的主要数据结构及其对应操作命令的详细解释,结合具体使用场景和示例: 1. 字符串(String) 用途:存储文本、数值或二进制数据,适用于缓存、计数器等。 常用命令: SET key value&#x…...
深度解读 Chinese CLIP 论文:开启中文视觉对比语言预训练
目录 论文概述1.论文摘要2.论文脑图3.论文创新3.1模型构建3.2训练方法3.3数据构建3.4部署优化 4.模型架构 论文解析1. 引言2. 方法2.1数据说明2.2预训练方法2.2.1模型初始化方法2.2.2两阶段预训练方法 2.3预训练细节2.3.1模型初始化2.3.2第一阶段预训练2.3.3第二阶段预训练2.3.…...
SpringBoot 2 后端通用开发模板搭建(异常处理,请求响应)
目录 一、环境准备 二、新建项目 三、整合依赖 1、MyBatis Plus 数据库操作 2、Hutool 工具库 3、Knife4j 接口文档 4、其他依赖 四、通用基础代码 1、自定义异常 2、响应包装类 3、全局异常处理器 4、请求包装类 5、全局跨域配置 补充:设置新建类/接…...
【Oracle专栏】sqlplus显示设置+脚本常用显示命令
Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.内容概述 本文主要针对oracle 运维中常用知识点进行整理,包括: 1)sqlplus模式下,为了方便查询设置相应的行宽、列宽、行数。…...
DeepSeek 助力 Vue3 开发:打造丝滑的页眉(Header)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
JVM线程分析详解
java线程状态: 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建…...
【备赛】点亮LED
LED部分的原理图 led前面有锁存器,这是为了防止led会受到lcd的干扰(lcd也需要用到这些引脚)。 每次想要对led操作,就需要先打开锁存器,再执行操作,最后关闭锁存器。 这里需要注意的是,引脚配置…...
【音视频】编解码相关概念总结
NALU RTP PS流 三者总体关系 NALU在RTP中的应用:视频流的RTP传输通常将NALU作为基本的单元进行传输。每个RTP包携带一个或多个NALU,这些NALU包含了视频编码数据。RTP协议通过其头部信息(如时间戳、序列号等)帮助接收端重新排列和…...
Python爬虫(四)- Selenium 安装与使用教程
文章目录 前言一、简介及安装1. Selenium 简介2. Selenium 安装 二、Selenium 基本使用1. 导入Selenium2. 启动浏览器3. 打开网页4. 获取页面标题5. 关闭浏览器6. 完整示例代码 三、Selenium WebDriver1. 简介2. 基本操作2.1 启动浏览器2.2 关闭浏览器2.3 打开网页2.4 关闭当前…...
Node.js项目启动流程以及各个模块执行顺序详解
Node.js项目启动流程以及各个模块执行顺序的问题。首先,我需要仔细阅读并理解我搜索到的资料,从中提取关键信息,然后综合这些信息组织成一个结构化的回答。 首先,根据我搜索到的资料都详细描述了Node.js的启动流程,涉及…...
各种类型网络安全竞赛有哪些 网络安全大赛的简称
本文是对入门学习的一些概念了解和一些常规场景记录 1.CTF(capture the flag)是夺旗赛的意思。 是网络安全技术人员之间进行攻防的比赛。 起源1996年DEFCON全球黑客大会,替代之前真实攻击的技术比拼。 (DEFCON极客大会诞生1993,…...
浅谈人工智能与深度学习的应用案例研究
人工智能与深度学习的应用案例研究 人工智能(AI)与深度学习技术正以惊人的速度渗透到社会生活的各个领域,从医疗健康到艺术创作,从金融风控到城市治理,其应用案例不断突破传统边界。以下是近年来具有代表性的六大应用方向及具体案例: 一、医疗健康:精准诊断与药物研发 医…...
vue2版本elementUI的table分页实现多选逻辑
1. 需求 我们需要在表格页上实现多选要求,该表格支持分页逻辑。 2. 认识属性 表格属性 参数说明类型可选值默认值data显示的数据array——row-key行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能与显示树形数据时&…...
AI数字人技术源码开发分享:革新短视频营销策略
集星幻影的AI数字人分身系统是一款融合了先进人工智能技术的综合性短视频营销解决方案。该系统整合了形象克隆、声音克隆、AI数字人分身生成、智能剪辑及文案创作等功能,旨在为用户打造虚拟人物资产并提供AI驱动的多模态交互服务。以下是该系统的主要功能概述&#…...
实验环境搭建集锦(docker linux ros2+强化学习环境+linux上单片机串口调试)
为了记住一些实验环境配置开的文章,边配置边记,免得之后忘了。 Docker环境搭建 yay -S docker //下载docker docker info //查看docker配置 sudo systemctl start docker //系统配置打开docker sudo systemctl enable docker //系统配置后台开启d…...
sql调优之数据库开发规范
数据库 数据库开发规范 也可用于PostgreSQL以及兼容PG的数据库 通用命名规则 【强制】 本规则适用于所有对象名,包括:库名、表名、列名、函数名、视图名、序列号名、别名等。 【强制】 对象名务必只使用小写字母,下划线,数字&…...
《Effective Objective-C》阅读笔记(上)
目录 高质量iOS之熟悉OC 了解OC语言的起源 在类的头文件中尽量少引入其他头文件 多用字面语法,少用与之等价的方法 字面数值 字面量数组 字面量字典 局限性 多用类型常量,少用#define预处理指令 用枚举表示状态、选项、状态码 高质量iOS之对象…...
ClkLog里程碑:荣获2024上海开源技术应用创新竞赛三等奖
2024年10月,ClkLog团队参加了由上海计算机软件技术开发中心、上海开源信息技术协会联合承办的2024上海数智融合“智慧工匠”选树、“领军先锋”评选活动——开源技术应用创新竞赛。我们不仅成功晋级决赛,还荣获了三等奖!这一成就不仅是对ClkL…...
【数据结构进阶】哈希表
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:数据结构 目录 前言 一、哈希表的概念 二、哈希函数的实现方法 1. 直接定址法 2. 除留余数法 三、哈希冲突 1. 开放定址法(闭散列࿰…...
STM32内存五区及堆栈空间大小设置(启动文件浅析)
前言 嘿,朋友们!今天咱们来聊聊STM32的内存五区和堆栈空间大小设置。这可是嵌入式开发里的“必修课”,要是没整明白,程序说不定就“翻车”了。别担心,我这就带你一步步搞懂这事儿,让你轻松上手,…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
