Redis List 的详细介绍

news2025/4/22 1:38:28

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 和端口 6379
            Jedis jedis = new Jedis("localhost", 6379);
    
            // 定义 Redis List 的 key
            String 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 节点,减少单节点内存压力。

四、性能与调优建议

  1. 优先使用 LPUSH/RPUSH+LTRIM​:

    • 实现固定长度列表(如最新 100 条消息),避免无限增长。
  2. 避免大范围 LRANGE操作

    • 获取全部数据时,使用 LRANGE 0 -1​ 可能导致阻塞,建议分页或迭代遍历。
  3. 合理配置 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​。


使用案例 :

  • 博客信息展示 列表

    Editor _ Mermaid Chart-2025-04-17-092414

    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}:articles
            String 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 与端口 6379
            Jedis 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);
            // 分页获取用户文章列表:获取第一页,页面大小为 10
            List<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();
        }
    }
    

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

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

相关文章

使用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 瑞吉外卖系统开发&#xff08;五&#xff09; 删除分类 分类列表中每条分类信息右侧提供了一个“删除”按钮&#xff0c;当需要将已经存在的分类信息删除时&#xff0c;可以通过单击“删除”按钮实现。 请求路径为/category&#xff0c;携带参数id&#xf…

【Web部署问题】在Tomcat中部署web项目出现http状态-404 -未找到详细解决方案

部署完tomcat记得在选中要运行的工件。 如果没有工件&#xff0c;或者工件有缺失东西&#xff0c;去这里配置工件&#xff0c;

Linux——Shell编程之正则表达式与文本处理器(笔记)

目录 基础正则表达式 1:基础正则表达式示例 &#xff08;4&#xff09;查找任意一个字符“.”与重新字符“*” &#xff08;5&#xff09;查找连续字符范围“{ }” 文本处理器 一、sed工具 二、awk工具 &#xff08;1&#xff09;按行输出文本 &#xff08;2&#xff0…

05-DevOps-Jenkins自动拉取构建代码

新建Gitlab仓库 先在Gitab上创建一个代码仓库&#xff0c;选择创建空白项目 安装说明进行填写&#xff0c;然后点击创建项目 创建好的仓库是空的&#xff0c;什么都没有 新建一个springboot项目&#xff0c;用于代码上传使用。 只是为了测试代码上传功能&#xff0c;所以代码…

SRS transcode支持 h264_nvenc 硬件解码方案

文章目录 SRS transcode支持 h264_nvenc 硬件解码方案1、修改文件2、重新编译3、使用 SRS transcode支持 h264_nvenc 硬件解码方案 SRS 是开源的流媒体服务&#xff0c;但在使用 GPU 服务器时&#xff0c;想要通过硬件加速&#xff0c;目前官方是不支持的&#xff0c;所以简单…

阿里云服务器搭建开源版禅道

一&#xff0c;下载地址&#xff1a;禅道11.5版本发布&#xff0c;主要完善细节&#xff0c;修复bug&#xff0c;新增动态过滤机制 - 禅道下载 - 禅道项目管理软件 下载地址二&#xff1a; 禅道21.6.stable 实现旧编辑器撰写的文档无感升级至新版编辑器 - 禅道下载 - 禅道项目…

怎么用面向对象和状态机架构,设计一个通用的按键检测功能?

说起按键检测&#xff0c;在座的各位&#xff0c;哪个没被它折磨过&#xff1f; 我刚入门时&#xff0c;为了实现一个简单的按键功能&#xff0c;硬生生写了几十行代码&#xff0c;各种 if...else 嵌套&#xff0c;逻辑绕得我自己都头晕。 更可气的是&#xff0c;辛辛苦苦写完…

Java基础系列-LinkedList源码解析

文章目录 简介LinkedList 插入和删除元素的时间复杂度&#xff1f;LinkedList 为什么不能实现 RandomAccess 接口&#xff1f; LinkedList 源码分析Node 定义初始化获取元素插入元素删除元素遍历链表 简介 LinkedList 是一个基于双向链表实现的集合类&#xff0c;经常被拿来和…

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信号时&#xff0c;十分重要的一环就是LVDS输入信号线在经过PCB输入到FPGA中后&#xff0c;本来该严格对齐的信号线会出现时延&#xff0c;所以需要在FPGA内部对其进行延时对齐后再进行解析。 Xilinx 7系器件中用于输入信号延时的组件为IDELAYE2可编程原语&#xff0…

【Oracle专栏】函数中SQL拼接参数 报错处理

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 最近同事反馈了一个很奇怪的问题,即有一个函数,入参是当前年月,主要作用是通过SQL语句将不合规的数据插入到指定表中,插入数据时带上入参的年月参数。当前问题:单独测试SQL没有问题可以执行成功,…

自然语言处理(NLP)领域大图

以下是一份自然语言处理&#xff08;NLP&#xff09;与大模型领域的领域大图&#xff0c;涵盖技术框架、发展脉络、交叉融合点和应用场景的完整解析&#xff1a; 1. 核心技术体系 基础分析层级 词法分析&#xff1a;分词、词性标注、命名实体识别句法分析&#xff1a;依存句法…

【Linux我做主】GDB调试工具完全指南

Linux下GDB调试工具完全指南&#xff1a;25个核心命令详解与实战示例 github地址 有梦想的电信狗 前言 GDB&#xff08;GNU Debugger&#xff09;是Linux开发中不可或缺的调试工具&#xff0c;尤其在定位代码逻辑错误和内存问题时表现卓越。本文基于实际开发经验&#xff0…

Pycharm 如何删除某个 Python Interpreter

在PyCharm中&#xff0c;点击右下角的“Interpreter Settings”按钮&#xff0c;或者通过菜单栏选择“File” > “Settings”&#xff08;macOS用户选择“PyCharm” > “Preferences”&#xff09;。在设置窗口中&#xff0c;导航到“Project: [Your Project Name]” >…

Day3:个人中心页面布局前端项目uniapp壁纸实战

接下来我们来弄一下个人中心页面布局user.vue <template><view class"userLayout"><view class"userInfo"><view class"avatar"><image src"../../static/Kx.jpg" mode"aspectFill"></im…

正则表达式反向引用的综合应用魔法:从重复文本到简洁表达的蜕变

“我....我要....学学学学....编程 java!” —— 这类“重复唠叨”的文本是否让你在清洗数据时头疼不已&#xff1f; 本文将带你一步步掌握正则表达式中的反向引用技术&#xff0c;并结合 Java 实现一个中文文本去重与清洗的实用工具。 结合经典的结巴实例。如何高效地将这样的…

FFmpeg+Nginx+VLC打造M3U8直播

一、视频直播的技术原理和架构方案 直播模型一般包括三个模块&#xff1a;主播方、服务器端和播放端 主播放创造视频&#xff0c;加美颜、水印、特效、采集后推送给直播服务器 播放端&#xff1a; 直播服务器端&#xff1a;收集主播端的视频推流&#xff0c;将其放大后推送给…

Windows串口通信

Windows串口通信相比较Android串口通信,在开发上面相对方便一些。原理都是一样,需要仔细阅读厂商设备的串口通信协议。结合串口调试助手进行测试,测试通过后,编写代码实现。 比如近期就接触到了一款天平,其最大测量值为100g,测量精度0.001g。 拿到手之后我就先阅读串口通…