Redis List 的详细介绍
Redis List 的详细介绍
以下是 Redis List 的详细介绍,从基础命令、内部编码和使用场景三个维度展开:
一、基础命令
Redis List 支持双向操作(头尾插入/删除),适用于队列、栈等场景,以下是核心命令分类:
1. 插入与删除
-
LPUSH / RPUSH:从左侧(头部)或右侧(尾部)插入元素。
LPUSH mylist "A" # 头部插入 "A",返回列表长度 RPUSH mylist "B" # 尾部插入 "B",返回列表长度 -
LPOP / RPOP:从头部或尾部移除并返回元素。
LPOP mylist # 移除头部元素 "A" RPOP mylist # 移除尾部元素 "B" -
LINSERT:在指定元素前/后插入新元素。
LINSERT mylist BEFORE "B" "A" # 在 "B" 前插入 "A" -
LREM:删除指定数量的匹配元素。
LREM mylist 2 "A" # 删除最多2个 "A"
2. 查询与截断
-
LRANGE:获取指定索引范围内的元素。
LRANGE mylist 0 -1 # 获取所有元素 -
LINDEX:获取指定位置的元素。
LINDEX mylist 0 # 返回头部元素 -
LLEN:获取列表长度。
LLEN mylist # 返回列表元素总数 -
LTRIM:保留指定范围内的元素,其余删除。
LTRIM mylist 0 4 # 仅保留前5个元素
3. 阻塞操作
-
BLPOP / BRPOP:阻塞式弹出元素,适用于消息队列。
BLPOP task_queue 10 # 阻塞10秒等待头部元素
二、内部编码
Redis List 的底层实现根据数据规模动态选择编码方式:
1. listpack(Redis 7.0+)
-
条件:当所有元素满足以下条件时使用 listpack(连续内存结构):
- 元素数量 ≤
list-max-listpack-size(默认 512)。 - 每个元素的大小 ≤
list-max-listpack-value(默认 64 字节)。
- 元素数量 ≤
-
特点:
- 内存紧凑,无指针开销,适合小规模数据。
- 规避了 ziplist 的连锁更新问题(见 Redis 7.0+ 的改进)。
2. quicklist(Redis 3.2+)
-
触发条件:超出 listpack 容量时自动切换。
-
结构:由多个 listpack 节点组成的双向链表,平衡内存与操作效率。
- 每个 listpack 节点存储多个元素。
- 支持头尾快速插入/删除(时间复杂度 O(1))。
-
配置调优:
list-max-listpack-size -2 # 默认每个 listpack 节点大小 8KB list-compress-depth 0 # 压缩深度(0 表示不压缩)
三、使用场景
1. 消息队列
-
生产者:
LPUSH 插入任务到队列头部。 -
消费者:
BRPOP 阻塞获取任务,避免轮询。# 生产者 LPUSH task_queue "task1" # 消费者 BRPOP task_queue 0 # 0 表示无限阻塞
2. 最新消息排行榜
-
插入:
LPUSH 将新消息加入列表头部。 -
展示:
LRANGE 0 9 获取最新的 10 条消息。 -
清理:
LTRIM 0 99 保留最近 100 条消息。package com.example.redis.list;/*** 描述: 消息绑** @author ZHOUXIAOYUE* @date 2025/4/17 15:07*/ import redis.clients.jedis.Jedis; import java.util.List; public class LatestNewsBoard {public static void main(String[] args) {// 连接 Redis 服务,默认地址 localhost 和端口 6379Jedis jedis = new Jedis("localhost", 6379);// 定义 Redis List 的 keyString listKey = "latest:news";for (int x= 0; x < 100; x++) {// 模拟插入一条新消息String newMessage = "Breaking News: Redis 使用场景持续扩展!"+x;// 使用 LPUSH 命令将消息插入到列表头部jedis.lpush(listKey, newMessage);System.out.println("新消息已插入: " + newMessage);}// 使用 LLEN 命令获取// 数据清理:使用 LTRIM 保留最近 100 条消息jedis.ltrim(listKey, 0, 99);System.out.println("消息列表已清理,保留最近 100 条记录。");// 展示最新 10 条消息:使用 LRANGE 命令获取列表中 0~9 范围内的消息List<String> latestMessages = jedis.lrange(listKey, 0, 9);System.out.println("最新的 10 条消息如下:");for (String message : latestMessages) {System.out.println(message);}// 关闭 Redis 连接jedis.close();} }
3. 历史记录
-
用户操作日志:
LPUSH 记录用户行为,LTRIM 限制记录数量。LPUSH user:1001:logs "click_button_A" LTRIM user:1001:logs 0 99 # 保留最近 100 条日志
4. 栈(LIFO)
-
入栈:
LPUSH,出栈:LPOP。LPUSH my_stack "data1" LPOP my_stack # 返回 "data1"
5. 数据分片存储
- 大列表拆分为多个 quicklist 节点,减少单节点内存压力。
四、性能与调优建议
-
优先使用
LPUSH /RPUSH +LTRIM:- 实现固定长度列表(如最新 100 条消息),避免无限增长。
-
避免大范围
LRANGE 操作:- 获取全部数据时,使用
LRANGE 0 -1 可能导致阻塞,建议分页或迭代遍历。
- 获取全部数据时,使用
-
合理配置 quicklist:
- 调整
list-max-listpack-size 平衡内存与性能(默认 8KB)。 - 启用压缩(
list-compress-depth)节省内存,但会增加 CPU 开销。
- 调整
总结
-
核心优势:支持双向操作、阻塞弹出、动态分片存储。
-
适用场景:消息队列、实时排行榜、操作日志、栈/队列实现。
-
版本差异:
- Redis 3.2+ 使用 quicklist,替代旧版的 ziplist + linkedlist。
- Redis 7.0+ 使用 listpack 替代 ziplist,提升安全性和性能。
-
命令选择:高频写入用
LPUSH/RPUSH,阻塞消费用BRPOP,精确控制用LTRIM。
使用案例 :
-
博客信息展示 列表
package com.example.redis.list;/*** 描述:** @author ZHOUXIAOYUE* 每篇文章使用哈希结构存储(字段:title、timestamp、content),文章的 key 格式为 "article:{id}"。* 每个用户有自己的文章列表,列表 key 格式为 "user:{id}:articles",列表中存储文章 id,利用 LPUSH 添加文章(最新的在列表头部)。* 分页获取用户文章列表,示例中获取用户 id=1 的前 10 篇文章(即列表索引 0~9),再根据文章 id 获取对应的文章详细信息。* @date 2025/4/17 16:35*/ import redis.clients.jedis.Jedis; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.ArrayList; public class UserArticlesPagination {// 定义文章类static class Article {private String id;private String title;private String timestamp;private String content;public Article(String id, String title, String timestamp, String content) {this.id = id;this.title = title;this.timestamp = timestamp;this.content = content;}public String getId() {return id;}public String getTitle() {return title;}public String getTimestamp() {return timestamp;}public String getContent() {return content;}}// 添加文章,将文章哈希存储,并将文章 id 插入到用户的文章列表中public static void addArticle(Jedis jedis, String userId, Article article) {// 定义文章的 key 格式: article:{id}String articleKey = "article:" + article.getId();Map<String, String> articleMap = new HashMap<>();articleMap.put("title", article.getTitle());articleMap.put("timestamp", article.getTimestamp());articleMap.put("content", article.getContent());// 使用 HMSET 存储文章哈希jedis.hmset(articleKey, articleMap);// 将文章 id 添加到用户文章列表中,列表 key 格式: user:{id}:articlesString userArticlesKey = "user:" + userId + ":articles";// 使用 LPUSH 保证最新文章位于列表头部jedis.lpush(userArticlesKey, article.getId());}// 分页获取用户的文章列表,并返回文章详情集合public static List<Map<String, String>> getUserArticles(Jedis jedis, String userId, int page, int pageSize) {String userArticlesKey = "user:" + userId + ":articles";// 计算起始和结束索引(分页从 1 开始)int start = (page - 1) * pageSize;int end = start + pageSize - 1;// 获取文章 id 列表List<String> articleIds = jedis.lrange(userArticlesKey, start, end);List<Map<String, String>> articles = new ArrayList<>();// 根据文章 id 获取文章详情for (String articleId : articleIds) {String articleKey = "article:" + articleId;Map<String, String> articleData = jedis.hgetAll(articleKey);// 如果文章数据存在,则加入结果列表if (!articleData.isEmpty()) {articles.add(articleData);}}return articles;}public static void main(String[] args) {// 连接 Redis 服务,默认地址 localhost 与端口 6379Jedis jedis = new Jedis("localhost", 6379);// 假设用户 id 为 "1",添加几篇文章测试String userId = "1";Article article1 = new Article("101", "Redis 入门", "2023-10-01 10:00:00", "Redis 是一个键值存储系统...");Article article2 = new Article("102", "Redis 高级特性", "2023-10-02 11:30:00", "Redis 支持多种数据结构...");Article article3 = new Article("103", "Redis 实战案例", "2023-10-03 14:20:00", "通过案例来掌握 Redis 应用...");addArticle(jedis, userId, article1);addArticle(jedis, userId, article2);addArticle(jedis, userId, article3);// 分页获取用户文章列表:获取第一页,页面大小为 10List<Map<String, String>> articles = getUserArticles(jedis, userId, 1, 10);System.out.println("用户 " + userId + " 的文章列表:");for (Map<String, String> articleData : articles) {System.out.println("标题:" + articleData.get("title") + ", 时间:" + articleData.get("timestamp"));System.out.println("内容:" + articleData.get("content"));System.out.println("--------------------------");}// 关闭 Jedis 连接jedis.close();} }
相关文章:
Redis List 的详细介绍
Redis List 的详细介绍 以下是 Redis List 的详细介绍,从基础命令、内部编码和使用场景三个维度展开: 一、基础命令 Redis List 支持双向操作(头尾插入/删除),适用于队列、栈等场景,以下是核心命令分类&a…...
使用virtualbox的HostOnly建立共享网络-实现虚拟机上网
目录 环境描述解决方案具体步骤1.新建一个virtual host-only ethernet adapter2.设置windows的wifi信号网络共享3.确认winows宿主网络信息3.1.wifi适配器的信息3.2.虚拟网卡的信息3.3.确认virtualbox中虚拟网卡的ip地址 4.虚拟机网卡设置5.虚拟机网络设置5.1.本地连接设置5.2.u…...
springboot+vue3+mysql+websocket实现的即时通讯软件
项目演示 即时通讯软件项目演示 业务架构 技术栈 后端 选用编程语言 Javaweb框架SpringBootdb MySQL 持久存储nosql 缓存 Redis全双工通信框架 WebSocket 前端 前端框架Vue3TypescriptUI样式 Css、ElementPlus网页路由 vue-router全双工通信框架Websocket 功能完成情况 已实…...
基于 Spring Boot 瑞吉外卖系统开发(五)
基于 Spring Boot 瑞吉外卖系统开发(五) 删除分类 分类列表中每条分类信息右侧提供了一个“删除”按钮,当需要将已经存在的分类信息删除时,可以通过单击“删除”按钮实现。 请求路径为/category,携带参数id…...
AES (高级加密标准)
原理详解 AES是一种对称加密算法,使用相同的密钥进行加密和解密。它采用替代-置换网络(SPN)结构,主要步骤包括: 密钥扩展:从初始密钥派生多轮密钥 初始轮:AddRoundKey(轮密钥加) 主轮ÿ…...
详解Windows(一)——系统盘下目录及文件详解
引言 你是否曾经好奇过电脑里那些神秘的文件夹都是干什么用的?为什么有些文件是.exe而有些是.dll?不同的图片格式.jpg和.png到底有什么区别?如果你对这些问题感到困惑,这篇文章就是为你准备的。今天,我们将以通俗易懂…...
基于Spring MVC的客户端真实IP获取方案解析
文章目录 基于Spring MVC的客户端真实IP获取方案解析概述核心方法解析代码实现工作流程 IP获取优先级策略IP有效性验证异常处理与日志使用场景注意事项扩展建议 基于Spring MVC的客户端真实IP获取方案解析 概述 在Web应用开发中,准确获取客户端真实IP地址是常见的…...
【Web部署问题】在Tomcat中部署web项目出现http状态-404 -未找到详细解决方案
部署完tomcat记得在选中要运行的工件。 如果没有工件,或者工件有缺失东西,去这里配置工件,...
Linux——Shell编程之正则表达式与文本处理器(笔记)
目录 基础正则表达式 1:基础正则表达式示例 (4)查找任意一个字符“.”与重新字符“*” (5)查找连续字符范围“{ }” 文本处理器 一、sed工具 二、awk工具 (1)按行输出文本 (2࿰…...
Linux 进程控制(自用)
非阻塞调用waitpid 这样父进程就不会阻塞,此时循环使用我们可以让父进程执行其他任务而不是阻塞等待 进程程序替换 进程PCB加载到内存中的代码和数据 替换就是完全替换当前进程的代码段、数据段、堆和栈,保存当前的PCB 代码指的是二进制代码不是源码&a…...
05-DevOps-Jenkins自动拉取构建代码
新建Gitlab仓库 先在Gitab上创建一个代码仓库,选择创建空白项目 安装说明进行填写,然后点击创建项目 创建好的仓库是空的,什么都没有 新建一个springboot项目,用于代码上传使用。 只是为了测试代码上传功能,所以代码…...
【Spring学习】
Spring学习 简介 Spring 是一个开源的 Java 企业级开发框架,最核心的特点是: IOC(控制反转)AOP(面向切面编程) 它有完整的生态: 🚀 Spring Boot:用于快速构建服务&a…...
网络基础与 HTTP 协议
一、网络基础 (一)TCP/IP 协议族 TCP/IP 协议族是互联网通信的核心协议,它包含了多个层次的协议,共同协作实现网络通信。 1. IP 协议 IP(Internet Protocol)协议位于网络层,主要负责将数据包…...
SRS transcode支持 h264_nvenc 硬件解码方案
文章目录 SRS transcode支持 h264_nvenc 硬件解码方案1、修改文件2、重新编译3、使用 SRS transcode支持 h264_nvenc 硬件解码方案 SRS 是开源的流媒体服务,但在使用 GPU 服务器时,想要通过硬件加速,目前官方是不支持的,所以简单…...
阿里云服务器搭建开源版禅道
一,下载地址:禅道11.5版本发布,主要完善细节,修复bug,新增动态过滤机制 - 禅道下载 - 禅道项目管理软件 下载地址二: 禅道21.6.stable 实现旧编辑器撰写的文档无感升级至新版编辑器 - 禅道下载 - 禅道项目…...
【刷题Day21】TCP(浅)
说说 TCP 的四次挥手? TCP的四次挥手事用于安全关闭一个已建立的连接的过程,它确保双方都能完成数据传输并安全地释放连接资源。 简述步骤: 第一次挥手(FIN --> ACK):客户端主动关闭连接,…...
怎么用面向对象和状态机架构,设计一个通用的按键检测功能?
说起按键检测,在座的各位,哪个没被它折磨过? 我刚入门时,为了实现一个简单的按键功能,硬生生写了几十行代码,各种 if...else 嵌套,逻辑绕得我自己都头晕。 更可气的是,辛辛苦苦写完…...
Java基础系列-LinkedList源码解析
文章目录 简介LinkedList 插入和删除元素的时间复杂度?LinkedList 为什么不能实现 RandomAccess 接口? LinkedList 源码分析Node 定义初始化获取元素插入元素删除元素遍历链表 简介 LinkedList 是一个基于双向链表实现的集合类,经常被拿来和…...
day47—双指针-平方数之和(LeetCode-633)
题目描述 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a^2 b^2 c 。 示例 1: 输入:c 5 输出:true 解释:1 * 1 2 * 2 5示例 2: 输入:c 3 输出:f…...
qwen 14B模型配置文件,层名称weight_map. 28GB
qwen 14B模型配置文件,层名称weight_map. 28GB 目录 qwen 14B模型配置文件,层名称weight_map. 28GBmetadata(元数据)weight_map(权重映射)lm_head.weightmodel.layersmlp.{proj_type}.weightpost_attention_layernormself_attn.{proj_type}.{bias_or_weight}model.norm.w…...
LVDS系列8:Xilinx 7系可编程输入延迟(一)
在解析LVDS信号时,十分重要的一环就是LVDS输入信号线在经过PCB输入到FPGA中后,本来该严格对齐的信号线会出现时延,所以需要在FPGA内部对其进行延时对齐后再进行解析。 Xilinx 7系器件中用于输入信号延时的组件为IDELAYE2可编程原语࿰…...
【Oracle专栏】函数中SQL拼接参数 报错处理
Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 最近同事反馈了一个很奇怪的问题,即有一个函数,入参是当前年月,主要作用是通过SQL语句将不合规的数据插入到指定表中,插入数据时带上入参的年月参数。当前问题:单独测试SQL没有问题可以执行成功,…...
自然语言处理(NLP)领域大图
以下是一份自然语言处理(NLP)与大模型领域的领域大图,涵盖技术框架、发展脉络、交叉融合点和应用场景的完整解析: 1. 核心技术体系 基础分析层级 词法分析:分词、词性标注、命名实体识别句法分析:依存句法…...
【Linux我做主】GDB调试工具完全指南
Linux下GDB调试工具完全指南:25个核心命令详解与实战示例 github地址 有梦想的电信狗 前言 GDB(GNU Debugger)是Linux开发中不可或缺的调试工具,尤其在定位代码逻辑错误和内存问题时表现卓越。本文基于实际开发经验࿰…...
Pycharm 如何删除某个 Python Interpreter
在PyCharm中,点击右下角的“Interpreter Settings”按钮,或者通过菜单栏选择“File” > “Settings”(macOS用户选择“PyCharm” > “Preferences”)。在设置窗口中,导航到“Project: [Your Project Name]” >…...
在 Debian 12 中恢复被删除的 smb.conf 配置文件
https://forum.ubuntu.com.cn/viewtopic.php?t494763 本文结合ai输出,内容中可能有些错误,但确实解决了我的问题,我采取保留完整输出的方式摘录。 在 Debian 12 中恢复被删除的 smb.conf 配置文件,需结合 dpkg 和 ucf(…...
Day3:个人中心页面布局前端项目uniapp壁纸实战
接下来我们来弄一下个人中心页面布局user.vue <template><view class"userLayout"><view class"userInfo"><view class"avatar"><image src"../../static/Kx.jpg" mode"aspectFill"></im…...
访问”和“初始化本质区别以及C++静态成员变量定义位置详解
💡 1.访问”和“初始化本质区别: ✅ 访问 protectedNum:Derived 作为 Base 的子类,是可以在自己的函数中访问 protectedNum 的。❌ 初始化 protectedNum:只能通过 Base 的构造函数来初始化,因为它是 Base …...
正则表达式反向引用的综合应用魔法:从重复文本到简洁表达的蜕变
“我....我要....学学学学....编程 java!” —— 这类“重复唠叨”的文本是否让你在清洗数据时头疼不已? 本文将带你一步步掌握正则表达式中的反向引用技术,并结合 Java 实现一个中文文本去重与清洗的实用工具。 结合经典的结巴实例。如何高效地将这样的…...
C实现md5功能
md5在线验证: 在线MD5计算_ip33.com 代码如下: #include "md5.h" #include <string.h> #include "stdio.h"/** 32-bit integer manipulation macros (little endian)*/ #ifndef GET_ULONG_LE #define GET_ULONG_LE(n,b,i) …...
