当前位置: 代码网 > it编程>数据库>Redis > Redis节省内存的十个技巧分享

Redis节省内存的十个技巧分享

2024年05月26日 Redis 我要评论
引言你是否在工作中遇到过redis的bigkey导致的内存占用严重、查询耗时大大增加?同时bigkey还可能导致redis实例的崩溃,因为内存不够用了,redis就会不堪重负,像是被大象坐了一样,瞬间

引言

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

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

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

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

正文

什么是bigkey

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

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

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

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

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

1、使用hash数据结构

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

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

// 使用hash存储商品信息
string userid = "product:1001";
jedis.hset(userid, "productname", "xxxx");
jedis.hset(userid, "category", "手机");
jedis.hset(userid, "prop", "xxx");

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

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

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

// 使用压缩列表存储文章评论
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 个字节 (一个稍长一点的字符串) 就可以完全容纳下,这就大大节约了存储空间。

// 使用bitmaps存储用户签到情况
string userid = "user:1001";
int day = 10; // 签到的天数,从0开始计算
jedis.setbit("sign_in:" + day, long.parselong(userid), true);

4、使用zset存储有序集合

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

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

// 使用zset存储文章阅读量排行榜
string articleid = "article:3001";
jedis.zadd("article:views", 1000, articleid);

5、使用set存储唯一值

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

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

// 使用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字节。

// 使用hyperloglog统计网站uv
string today = "2024-04-23";
string userid = "user:1001";
jedis.pfadd("uv:" + today, userid);

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

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

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

// 使用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可以有效节省内存空间和提升性能。

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

9、定期清理过期数据

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

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

10、合理设置内存策略

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

本文总结

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

以上就是redis节省内存的十个技巧分享的详细内容,更多关于redis节省内存技巧的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com