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

 更新时间:2024年04月28日 08:39:31   作者:江小北  
你是否在工作中遇到过Redis的bigkey导致的内存占用严重、查询耗时大大增加?同时bigKey还可能导致Redis实例的崩溃,因为内存不够用了,所以本文给大家介绍了Redis极大节省内存的10个技巧,需要的朋友可以参考下

引言

你是否在工作中遇到过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节省内存技巧的资料请关注脚本之家其它相关文章!

相关文章

  • redis单节点安装与配置方式

    redis单节点安装与配置方式

    这篇文章主要介绍了redis单节点安装与配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 浅析PHP分布式中Redis实现Session的方法

    浅析PHP分布式中Redis实现Session的方法

    这篇文章主要介绍了PHP分布式中Redis实现Session的方法,文中详细介绍了两种方法的使用方法,并给出了测试的示例代码,有需要的朋友可以参考借鉴,下面来一起看看吧,
    2016-12-12
  • Redis 实现同步锁案例

    Redis 实现同步锁案例

    这篇文章主要介绍了Redis 实现同步锁案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 基于redis乐观锁实现并发排队

    基于redis乐观锁实现并发排队

    这篇文章主要介绍了基于redis乐观锁实现并发排队的相关资料,需要的朋友可以参考下
    2022-12-12
  • Redis 脚本和连接命令示例详解

    Redis 脚本和连接命令示例详解

    Redis脚本是一种可以实现复杂任务的脚本语言,可以用来快速履行复杂任务,灵活处理数据管理和管理复杂的利用场景,这篇文章主要介绍了Redis 脚本和连接命令,需要的朋友可以参考下
    2023-09-09
  • 虚拟机linux安装redis实现过程解析

    虚拟机linux安装redis实现过程解析

    这篇文章主要介绍了虚拟机linux安装redis实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Redis利用互斥锁解决缓存击穿问题

    Redis利用互斥锁解决缓存击穿问题

    使用互斥锁可以有效防止缓存击穿的情况发生,它能够保证在缓存失效时,只有一个线程或者进程能够去加载数据,其余的请求都会等待这个加载过程完成,虽然这种方式会牺牲一部分性能,但它大大提高了系统的稳定性和可用性
    2024-08-08
  • Redis缓存-序列化对象存储乱码问题的解决

    Redis缓存-序列化对象存储乱码问题的解决

    这篇文章主要介绍了Redis缓存-序列化对象存储乱码问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • jwt+redis实现登录认证的示例代码

    jwt+redis实现登录认证的示例代码

    在登录业务代码中,当用户登录成功时,生成一个登录凭证存储到redis中,本文主要介绍了jwt+redis实现登录认证的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Redis基础学习之管道机制详析

    Redis基础学习之管道机制详析

    这篇文章主要给大家介绍了关于Redis基础学习之管道机制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11

最新评论