Redis高级应用:Redis极大节省内存的10个技巧

引言

你是否在工作中遇到过Redis的bigkey导致的内存占用严重、查询耗时大大增加?

同时bigKey还可能导致Redis实例的崩溃,因为内存不够用了,Redis就会不堪重负,像是被大象坐了一样,瞬间崩溃!

所以,大家在使用Redis的时候一定要小心,Redis内存是十分宝贵的资源,我们在使用时,要特别注意对内存资源的合理应用。

下面带大家了解下Redis极大节省内存空间的10个实用技巧。

正文

什么是bigkey

在面试过程中,发现很多人都对bigkey的概念搞错了,认为bigkey是一个key比较大的存储对象。

其实不是的,我们不能用英文直译的方式来理解它。所以这里还是给大家科普下:

bigkey,其实就是Redis中占用大量内存空间的键,具体来说,就是那些因为存储了大量数据,或者单个数据项太大,导致内存占用严重的键。

简单点来说:就是这个redis的某个键(key)存了太多的数据,占用了太多的内存

Redis节省内存的方式就是合理的运用Redis的数据结构,减少redis的bigkey的产生, 以及做好内存的清理和淘汰策略。

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。 这是大佬写的, 7701页的BAT大佬写的刷题笔记,让我offer拿到手软

1、使用Hash数据结构

Hash是Redis提供的一种非常灵活的数据结构,可以存储键值对的集合。 如果我们存储对象类型的数据,建议使用Hsah

假设我们有一个电商网站,需要存储商品的信息,比如商品名称、类目、属性等,这时候就可以用Hash数据结构来存储,一个商品对应一个Hash。

arduino 复制代码
// 使用Hash存储商品信息
String userId = "product:1001";
jedis.hset(userId, "productName", "xxxx");
jedis.hset(userId, "category", "手机");
jedis.hset(userId, "prop", "xxx");

2、使用压缩列表优化小规模列表

当你需要存储的列表元素数量不多时,Redis会自动使用压缩列表来存储,这样可以节省内存空间。

比如在一个论坛系统中,用户发布了一篇文章,我们可以用列表来存储文章的评论,而且这篇文章评论不多的话,就可以充分利用压缩列表的优势。

arduino 复制代码
// 使用压缩列表存储文章评论
String articleId = "article:2001";
jedis.lpush(articleId + ":comments", "评论1", "评论2", "评论3");

3、使用Bitmaps存储布尔值信息

Bitmaps是一种非常紧凑的数据结构,适合存储布尔值信息。

在我们平时开发过程中,会有一些 bool 型数据需要存取,比如用户一年的签到记录,签了是 1,没签是 0,要记录 365 天。如果使用普通的 key/value,每个用户要记录 365 个,当用户上亿的时候,需要的存储空间是惊人的。

为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位,365 天就是 365 个位,46 个字节 (一个稍长一点的字符串) 就可以完全容纳下,这就大大节约了存储空间。

ini 复制代码
// 使用Bitmaps存储用户签到情况
String userId = "user:1001";
int day = 10; // 签到的天数,从0开始计算
jedis.setbit("sign_in:" + day, Long.parseLong(userId), true);

4、使用ZSET存储有序集合

ZSET是Redis中的有序集合数据结构,可以按照指定的分数进行排序。

比如在一个新闻网站中,我们可以使用ZSET来存储新闻文章的阅读量排行榜,分数表示阅读量,文章ID作为成员。

ini 复制代码
// 使用ZSET存储文章阅读量排行榜
String articleId = "article:3001";
jedis.zadd("article:views", 1000, articleId);

5、使用SET存储唯一值

SET数据结构适合存储唯一值,比如用户的喜好标签、商品的标签等。

在一个电商平台中,我们可以使用SET来存储商品的标签,确保每个标签都是唯一的。

arduino 复制代码
// 使用SET存储商品标签
String productId = "product:5001";
jedis.sadd(productId + ":tags", "电子产品", "数码设备", "智能家居");

6、使用HyperLogLog进行基数统计

HyperLogLog是一种用于统计不重复元素数量的算法,在统计网站的UV(独立访客)数量时非常有用。 比如:

如果你负责开发维护一个大型的网站,有一天老板找产品经理要网站每个网页每天的 UV 数据,然后让你来开发这个统计模块,你会如何实现?

如果统计 PV 那非常好办,给每个网页一个独立的 Redis 计数器就可以了,这个计数器的 key 后缀加上当天的日期。这样来一个请求,incrby 一次,最终就可以统计出所有的 PV 数据。

但是 UV 不一样,它要去重,同一个用户一天之内的多次访问请求只能计数一次。这就要求每一个网页请求都需要带上用户的 ID,无论是登陆用户还是未登陆用户都需要一个唯一 ID 来标识。

这时候就可以引入HyperLogLog, HyperLogLog 数据结构就是用来解决这种统计问题的。

HyperLogLog 提供不精确的去重计数方案,虽然不精确但是也不是非常不精确,标准误差是 0.81%,这样的精确度已经可以满足上面的 UV 统计需求了,又大量节省了内存

HyperLogLog 实现中用到的是 16384 个桶,也就是 2^14,每个桶的 maxbits 需要 6 个 bits 来存储,最大可以表示 maxbits=63,于是总共占用内存就是2^14 * 6 / 8 = 12k字节。

ini 复制代码
// 使用HyperLogLog统计网站UV
String today = "2024-04-23";
String userId = "user:1001";
jedis.pfadd("uv:" + today, userId);

7、使用String存储序列化的数据

虽然Redis提供了丰富的数据结构,但有时候我们仍然需要将复杂的数据结构序列化为字符串存储。

比如在一个微博系统中,我们可以将用户的微博对象序列化为JSON字符串,然后存储到Redis中。

ini 复制代码
// 使用String存储序列化后的用户微博对象
UserPost userPost = new UserPost("user:1001", "今天天气真好!", new Date());
String userPostJson = objectMapper.writeValueAsString(userPost);
jedis.set("user:1001:post:1", userPostJson);

8、使用Pipeline批量操作命令

Pipeline是一种批量操作命令的机制,可以减少网络通信开销,提高操作效率。

在需要进行大量操作时,使用Pipeline可以有效节省内存空间和提升性能。

ini 复制代码
//使用Pipeline批量设置键值对
Pipeline pipeline = jedis.pipelined();
for (int i = 0; i < 10000; i++) {
    pipeline.set("key:" + i, "value:" + i);
}
pipeline.sync();

9、定期清理过期数据

定期清理过期数据是保持Redis内存空间有效利用的重要方法之一。通过设置合适的过期时间,并定期清理过期数据,可以释放内存空间。

arduino 复制代码
// 定期清理过期数据
jedis.setex("key:1001", 600, "value");

10、合理设置内存策略

根据实际需求和系统情况,合理设置Redis的内存策略,比如最大内存限制、淘汰策略等,可以更好地管理和利用内存空间。

本文总结

Redis内存是非常宝贵的资源,我们在日常开发中,要合理运用Redis的数据结构以达到节省内存的目的。

最后说一句(求关注,求赞,你的鼓励是我创作的最大动力)

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。 这是大佬写的, 7701页的BAT大佬写的刷题笔记,让我offer拿到手软

本文,已收录于,我的技术网站 cxykk.com:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享

求一键三连:点赞、分享、收藏

点赞对我真的非常重要!在线求赞,加个关注我会非常感激!

相关推荐
萌面小侠Plus2 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
ketil272 小时前
Ubuntu 安装 redis
redis
王佑辉3 小时前
【redis】redis缓存和数据库保证一致性的方案
redis·面试
Karoku0663 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
gorgor在码农4 小时前
Redis 热key总结
java·redis·热key
想进大厂的小王4 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
Java 第一深情4 小时前
高性能分布式缓存Redis-数据管理与性能提升之道
redis·分布式·缓存
人工智能培训咨询叶梓6 小时前
探索开放资源上指令微调语言模型的现状
人工智能·语言模型·自然语言处理·性能优化·调优·大模型微调·指令微调
CodeToGym8 小时前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
无尽的大道8 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化