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

Redis中Big Key该如何解决?

目录

1、Big Key的产生

2、BigKey场景分析

3、Big Key的危害

4、检测 BigKey 

5、解决 BigKey 问题

Big Key拆分

(1)按时间/业务拆分

(2)按哈希(Hash)拆分

(3)按前缀树拆分

Big Key定期清理

Big key压缩

Big Key批处理

优化持久化配置

6、总结


 Big Key 问题是指某个键(key)的值(value)过大,这会导致 Redis 的性能下降

1、Big Key的产生

  • 业务设计不合理

在设计应用时,如果对数据结构的设计不够精细,可能会导致单个 key 存储的数据量过大,没有合理地拆分成多个较小的 key

如:存储了大量数据的字符串、哈希表(hash)、列表(list)等,这会导致在执行涉及该键的操作时消耗更多的时间和资源。

  • 未及时清理无用数据

如:忘记设置过期时间,没有定期删除过期或不再需要的数据,List结构中数据持续增加而没有弹出数据的机制,那么数据会越来越多

  • 数据类型选择不当

不同的数据类型有不同的内存使用特点。例如,使用字符串类型存储大量数据可能不如使用哈希(HASH)类型来得高效。
选择不适合的数据类型可能导致内存使用效率低下,进而产生 Big Key

如:文件二进制数据不使用 String 保存、使用 HyperLogLog 统计页面 UV、Bitmap 保存状态信息(0/1)

  • 动态增长管理不当

某些数据结构可能随着时间和用户行为的变化而不断增长,如果没有适当的管理机制来控制其增长,就可能导致 Big Key 的出现。

如:日志记录、历史数据存储、某个明星热点粉丝列表或者评论的列表等功能如果没有合理的清理策略,可能会导致 key 的数据量逐渐增大

2、BigKey场景分析

以以下常见的场景分析Big Key的问题以及解决方案:

1. 用户行为日志记录

场景描述:应用程序记录用户的行为日志,如点击事件、浏览历史等,通常会将这些数据存储在一个用户的键中。
问题产生:随着用户行为的增多,单一用户的日志数据量会逐渐增大,形成 BigKey。
解决方案:分割日志数据到多个键中,例如按照日期分割。定期归档或清理旧的日志数据

2. 产品目录或商品信息

场景描述:电商平台或零售系统中,每个商品可能包含大量的属性信息,如规格、价格、库存等。
问题产生:如果将所有商品信息都存储在一个键中,随着商品数量的增加,键的大小也会增加。
解决方案:将商品信息拆分为多个键,例如按类别或品牌存储。使用更高效的数据结构,如使用哈希表存储商品的属性

3. 社交网络的好友关系

场景描述:社交应用中,每个用户都有自己的好友列表。
问题产生:当用户的好友数量非常多时,存储好友列表的键可能会变得非常大。
解决方案:将好友列表拆分为多个键,例如按照字母顺序或好友活跃度进行分组。使用有序集合(Sorted Set)存储好友列表,便于快速查找和排序

4. 会话状态存储

场景描述:Web 应用程序中,会话状态通常需要在服务器端存储。
问题产生:如果每个用户的会话状态包含了大量数据,如购物车、登录信息等,会话状态键可能会变得非常大。
解决方案:将会话状态拆分为多个键,例如将购物车和其他状态分开。定期清理过期的会话状态。

3、Big Key的危害

  • 性能下降

对 BigKey 执行批量操作,如 HGETALLHSETALL,这些命令的时间复杂度通常是 O(N),其中 N 是键中元素的数量。当 N 很大时,这些操作会变得非常耗时,尤其是在 Redis 的单线程模型下

  • 内存占用

BigKey 占用过多的内存,可能导致 Redis 的整体内存使用过高,从而触发内存淘汰策略,影响其他键的性能

  • 网络拥塞

BigKey 在网络上传输时会占用较多带宽,特别是当客户端频繁读取或写入 BigKey 时,可能会导致网络拥塞。

  • 超时阻塞

Redis 的主要命令执行是在单线程中完成的,这意味着在执行 BigKey 相关操作时,其他客户端的请求会被阻塞,直到该操作完成

  • 备份和恢复时间增加

Big Key 会使 RDB 快照文件或 AOF 日志文件增大,从而增加备份和恢复所需的时间。

大量的 Big Key 存在时,可能会导致备份和恢复过程变得非常缓慢

  • 复制延迟/删除异常

在主从复制场景中,Big Key 的复制会消耗更多的时间,导致从节点的延迟增加

当Big Key 过期需要删除时,由于数据量过大,可能发生主库较响应时间过长,主从数据同步异常(删除掉的数据,从库还在使用)

4、检测 BigKey 

  • 使用 redis-cli 工具:可以通过 redis-cli 工具来检测 BigKey
  • 使用 Redis 自带的命令:Redis 提供了 BIGKEYS 命令来查询当前 Redis 中所有 key 的信息,帮助统计分析键值对的大小情况

 使用以下命令扫描Redis中所有的键,并返回前1000个Big Key

redis-cli --scan --pattern '*' --count 1000
redis-cli -a "password" -- bigkeys

5、解决 BigKey 问题

  • Big Key拆分

将大键拆分成多个小键,使用更合适的数据结构来存储数据

拆分方式:

(1)按时间/业务拆分

如果 Big Key 包含的是按时间顺序排列的数据,可以考虑按时间范围拆分

(2)按哈希(Hash)拆分

使用哈希函数将大 Key 拆分成多个小 Key,并将其存储在不同的 Redis 实例中

(3)按前缀树拆分

使用前缀树将大 Key 拆分成多个层级结构,每个层级的 Key 都更小

前缀树是一种树形数据结构,用于高效地存储和检索字符串集合

🌰:假设有一个 Big Key 用于存储每天的用户登录记录按照Hash拆分

按照Hash拆分:
HashExample中- 使用 HashMap 来存储键值对。
                           - insert 方法用于插入以 user: 开头的键值对。
                           - get 方法用于查找特定键的值。
                           - printKeysWithPrefix 方法用于打印所有以特定前缀开头的键

public class HashExample {private Map<String, String> hashTable;public HashExample() {hashTable = new HashMap<>();}// 插入键值对public void insert(String key, String value) {if (key.startsWith("user:")) {hashTable.put(key, value);} else {System.out.println("只允许以 'user:' 开头的键。");}}// 查找键public String get(String key) {return hashTable.get(key);}// 查找以特定前缀开头的所有键public void printKeysWithPrefix(String prefix) {System.out.println("以 '" + prefix + "' 开头的键:");for (String key : hashTable.keySet()) {if (key.startsWith(prefix)) {System.out.println(key + ": " + hashTable.get(key));}}}public static void main(String[] args) {HashExample hashExample = new HashExample();hashExample.insert("user:123", "User 123 Data");hashExample.insert("user:456", "User 456 Data");hashExample.insert("admin:001", "Admin Data"); // 不会插入// 查找以 "user:" 开头的所有键hashExample.printKeysWithPrefix("user:");}
}

按照前缀树拆分

那么按照前缀树实现来存储和查询以 "user:" 开头的键,该如何实现呢?

首先,需要定义一个前缀树节点的类

TrieNode类中每个节点包含一个字符的子节点映射( children )和一个布尔值( isEndOfKey ),指示该节点是否为一个完整的键

class TrieNode {Map<Character, TrieNode> children;boolean isEndOfKey;public TrieNode() {children = new HashMap<>();isEndOfKey = false;}
}

接下来,定义一个前缀树类:
Trie 类:  - insert 方法用于插入一个键
                - collectKeysWithPrefix 方法用于查找以特定前缀开头的所有键
                - collectKeys 方法使用深度优先搜索(DFS)遍历节点,收集所有完整的键

class Trie {private TrieNode root;public Trie() {root = new TrieNode();}// 插入键public void insert(String key) {TrieNode node = root;for (char ch : key.toCharArray()) {node.children.putIfAbsent(ch, new TrieNode());node = node.children.get(ch);}node.isEndOfKey = true;}// 查找以特定前缀开头的所有键public List<String> collectKeysWithPrefix(String prefix) {TrieNode node = root;for (char ch : prefix.toCharArray()) {if (!node.children.containsKey(ch)) {return new ArrayList<>(); // 如果前缀不存在,返回空列表}node = node.children.get(ch);}List<String> keys = new ArrayList<>();collectKeys(node, prefix, keys);return keys;}// 深度优先搜索,收集所有以特定前缀开头的键private void collectKeys(TrieNode node, String currentPrefix, List<String> keys) {if (node.isEndOfKey) {keys.add(currentPrefix);}for (Map.Entry<Character, TrieNode> entry : node.children.entrySet()) {collectKeys(entry.getValue(), currentPrefix + entry.getKey(), keys);}}
}

最后,使用前缀树来存储和查询以 "user:" 开头的键:

public class Main {public static void main(String[] args) {Trie trie = new Trie();trie.insert("user:1", "value1");trie.insert("user:2", "value2");trie.insert("user:3", "value3");trie.insert("admin:1", "value4");// 查找以 "user:" 开头的所有键List<String> userKeys = trie.collectKeysWithPrefix("user:");System.out.println("以 'user:' 开头的键: " + userKeys);}
}

Big Key定期清理

异步删除:定期清理不再使用的 BigKey,以释放内存空间

Redis 4.0+ 可以使用 UNLINK 命令来异步删除一个或多个指定的 key。Redis 4.0 以下可以考虑使用 SCAN 命令结合 DEL 命令来分批次删除

设置TTL:对于经常访问的大键,可以考虑使用缓存策略LRU(最近最少使用)来减轻 Redis 的负担

关于缓存策略可以看这篇文章:Redis的过期策略以及内存淘汰机制-CSDN博客

Big key压缩

对于文本数据,可以考虑使用压缩算法来减小存储空间

Redis 支持使用 LZFQUICKLZGZIP 算法进行压缩

Big Key批处理

如果 Big Key 不能避免,可以考虑使用分批处理的方式来读取和更新数据,比如使用 SCAN 命令

优化持久化配置

RDB:调整 RDB 的备份频率和条件,减少 Big Key 对 RDB 文件大小的影响。
AOF:启用 AOF 的压缩功能,减少 AOF 文件的大小

🔴建议:

  • 避免使用非常长的 Key:理想情况下,Key 的长度应小于 100 字节。
  • 使用复合键:使用多个字段(例如,用户 ID 和帖子 ID)组合成一个键,可以减少单个键的长度。
  • 使用子列表:将大列表拆分成多个子列表,每个子列表的元素较少。
  • 使用 HyperLogLog:HyperLogLog 是一种概率数据结构,可以近似计算大集合中的唯一元素数量,它占用的空间非常小,例如统计页面 UV、网站访问者的唯一 IP 地址、用户的唯一 ID等

6、总结

Redis的Big Key会给Redis带来的意想不到的危害,需要监控、及时发现和处理Big Key。在开发过程中需要选用适当的Redis数据结构开发业务,尽量避免big key

相关文章:

Redis中Big Key该如何解决?

目录 1、Big Key的产生 2、BigKey场景分析 3、Big Key的危害 4、检测 BigKey 5、解决 BigKey 问题 Big Key拆分 &#xff08;1&#xff09;按时间/业务拆分 &#xff08;2&#xff09;按哈希&#xff08;Hash&#xff09;拆分 &#xff08;3&#xff09;按前缀树拆分…...

基于springboot的实习管理系统

TOC springboot207基于springboot的实习管理系统 绪论 1.1研究背景与意义 信息化管理模式是将行业中的工作流程由人工服务&#xff0c;逐渐转换为使用计算机技术的信息化管理服务。这种管理模式发展迅速&#xff0c;使用起来非常简单容易&#xff0c;用户甚至不用掌握相关的…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测

土地利用/土地覆盖数据是生态、环境和气象等领域众多模型的重要输入参数之一。基于遥感影像解译&#xff0c;可获取历史或当前任何一个区域的土地利用/土地覆盖数据&#xff0c;用于评估区域的生态环境变化、评价重大生态工程建设成效等。借助CLUE模型&#xff0c;实现对未来土…...

Rust 之环境搭建

前言 Rust 是一种现代的系统级编程语言&#xff0c;以其内存安全性、高性能和简洁的语法而著称。本文将介绍如何在不同操作系统上搭建 Rust 开发环境&#xff0c;并配置好基础工具&#xff0c;使您能够快速开始 Rust 编程。 1. 安装 Rust Rust 官方推荐使用 rustup 工具来管…...

基于微信小程序地图实现点位标注、覆盖物、地图聊天

目录 小程序部分map标签的使用获取用户经纬度并转换地址地图点击事件覆盖物标注点击并实现弹窗交互数据库及接口部分数据库表结构设计API搭建小程序接口使用注意事项wx.getLocation深入控制地图小程序部分 map标签的使用 创建小程序的步骤这里不再重复赘述,在wxml页面中放一个…...

xxl-job的分片广播+单播

1 介绍一下xxl-job XXL-JOB 是一个分布式任务调度平台&#xff0c;旨在为分布式应用系统提供开箱即用的调度解决方案。它非常易于使用&#xff0c;并具有很高的可扩展性。以下是 XXL-JOB 的详细介绍&#xff0c;包括其核心功能、架构设计、主要组件及其应用场景。 核心功能 简…...

情感分类代码

在进行自然语言处理中的情感分类时&#xff0c;通常需要准备以下几方面的内容&#xff1a; 1. **数据集**&#xff1a;高质量的标注数据集是关键&#xff0c;包括正面、负面和中性情感标记的文本。 2. **情感词典**&#xff1a;可用的情感词典&#xff0c;如SentiWordNet&…...

WPF—常用控件、属性、事件、详细介绍

WPF—常用控件、属性、事件、详细介绍 WPF&#xff08;Windows Presentation Foundation&#xff09;是微软推出的基于Windows 的用户界面框架&#xff0c;属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架&#xff0c;真正做到了分离界面设计人员与开发人…...

Oracle遭遇bug导致共享内存无法分配报ORA-04031错误

1.故障描述 在7月17日上午11时左右&#xff0c;收到告警短信&#xff0c;提示集群节点2宕机&#xff0c;当即登陆该节点进行查看&#xff0c;发现数据库状态正常。但日志里出现大量的ORA-04031报错&#xff0c;提示无法分配shared_pool&#xff0c;当时手动执行shared pool刷新…...

SAP BRIM用于应收账款AR收入中台

SAP BRIM&#xff08;Billing and Revenue Innovation Management&#xff09;是SAP提供的一个综合性解决方案&#xff0c;旨在帮助企业高效管理计费和收入流程。它与SAP ERP系统集成&#xff0c;提供端到端的功能&#xff0c;简化计费流程&#xff0c;自动化收入确认&#xff…...

LVS原理简介

LVS是Linux virtual server的缩写&#xff0c;为linux虚拟服务器&#xff0c;是一个虚拟的服务器集群系统。LVS简单工作原理为用户请求LVS VIP&#xff0c;LVS根据转发方式和算法&#xff0c;将请求转发给后端服务器&#xff0c;后端服务器接收到请求&#xff0c;返回给用户。对…...

Qt五大核心特性之元对象系统

前言 Qt 的元对象系统&#xff08;Meta-Object System&#xff09;是 Qt 框架的核心之一&#xff0c;提供了一些 C 原生不具备的功能(因为在C它们是静态的)&#xff0c;如反射、信号槽机制、属性系统等。通过这个系统&#xff0c;Qt 实现了许多强大的功能&#xff0c;这使得它…...

开放式耳机伤耳朵吗?开放式耳机在一定程度上保护我们的耳朵

开放式耳机通常被认为对耳朵的伤害较小&#xff0c;因为它们不需要插入耳道&#xff0c;从而减少了耳道内的压力和潜在的感染风险。与传统入耳式耳机相比&#xff0c;开放式耳机允许耳朵自然通风&#xff0c;减少耳道内的湿气和热量积聚&#xff0c;这有助于保持耳朵的健康。 然…...

JAVA打车小程序APP打车顺风车滴滴车跑腿源码微信小程序打车系统源码

&#x1f697;&#x1f4a8;打车、顺风车、滴滴车&跑腿系统&#xff0c;一键解决出行生活难题&#xff01; 一、出行新选择&#xff0c;打车从此不再难 忙碌的生活节奏&#xff0c;让我们常常需要快速、便捷的出行方式。打车、顺风车、滴滴车系统&#xff0c;正是为了满足…...

批量智慧:揭秘机器学习中的批量大小

标题&#xff1a;批量智慧&#xff1a;揭秘机器学习中的批量大小 机器学习是人工智能的一个分支&#xff0c;它使得计算机能够从数据中学习并做出决策或预测。在机器学习的过程中&#xff0c;批量大小&#xff08;Batch Size&#xff09;是一个至关重要的超参数&#xff0c;它…...

苹果Vision Pro生态发展:现状、挑战与未来展望

苹果公司以其创新技术和强大的生态系统闻名于世。在最近的财报会议上,CEO蒂姆库克分享了Vision Pro平台的最新进展,引发了业界的广泛关注。本文将深入探讨Vision Pro生态的现状、面临的挑战以及与其他XR平台的对比分析。 一、Vision Pro生态现状 据库克介绍,Vision Pro平台…...

湖南第一师范学院来访炼石,推动密码与数据安全合作

2024年8月11日&#xff0c;为进一步加强交流与合作&#xff0c;深入探讨校企产学研合作&#xff0c;湖南第一师范学院计算机学院院长杨恒伏一行莅临炼石调研指导。湖南第一师范学院计算机学院院长杨恒伏、网络空间安全系主任周聪等专家领导出席。炼石网络创始人兼CEO白小勇对湖…...

全面解析ETL:数据仓库架构中的关键处理过程

目录 一、数据仓库架构中的ETL 二、数据抽取 &#xff08;1&#xff09;逻辑抽取 &#xff08;2&#xff09;物理抽取 &#xff08;3&#xff09;变化数据捕获 三、数据转换 四、数据装载 &#xff08;1&#xff09;提高装载效率 &#xff08;2&#xff09;处理装载失败 五、ET…...

keepalived的介绍与配置

Keepalived是一个轻量级别的高可用解决方案&#xff0c;同时也是一个免费开源的、用C编写的类似于layer3, 4 & 7&#xff08;也有说法认为是layer3, 4 & 5&#xff09;交换机制的软件&#xff0c;主要提供负载均衡和高可用服务。它自动完成检测服务器的状态、故障隔离和…...

二叉树概念与使用

文章目录 一、作用二、二叉树概念特征2.1二叉树概念补充2.1.1度2.1.2深度2.1.3若规定根节点的层数为1&#xff0c;则深度为h的二叉树的最大结点数是2^h-1个结点 三、使用2.1二叉树存储&#xff0c;检索&#xff0c;插入项目 四、 二叉树检索的时间复杂度1. 普通二叉树2. 二叉搜…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...