存储在Redis中的数据多大比较合适 您所在的位置:网站首页 redis的sortset排序会卡 存储在Redis中的数据多大比较合适

存储在Redis中的数据多大比较合适

2024-02-10 05:13| 来源: 网络整理| 查看: 265

存储在Redis中的数据多大比较合适 背景过大的数据对 Redis 的影响『过大』的定义是什么结论

背景

本文是工作中应对一个实际业务场景的调研总结过程。在使用 redis 作为数据缓存的时候,一个 key 里面需要存储许多个 map 结构。

缓存需要序列化后存储在redis,这时候就出现了两种方案:

将多个map结构分开序列化,N 个 map N个 key:map1:{“foo”:“bar”}; map2: {“foo”:“bar”}… mapN:{“foo”:“bar”},好处是可以对不同 map 增量更新到redis。

将所有map整体序列化为一个大key: cache: “{“map1”:{“foo”:“bar”}… “mapN”:{“foo”:“bar”}”,好处是从 redis 读取到数据的时候,反序列化要比方案1快。

过大的数据对 Redis 的影响

哪到底选哪个方案呢?这两个方案对 redis 的影响如何呢?万事不决先 google。

首先看到 Redis 官方的说法是:『A String value can be at max 512 Megabytes in length.』。当然我们不能这么任性的真的扔这么大的数据进去,还觉得没问题。过大的 key 和 value 有两个问题:

Redis 是一个内存数据库,如果容量过大的 key 和 value 首先会导致服务器中的内存碎片。这会影响 Redis 的内存分配的效率,进一步导致内存的使用率下降。

容量过大的 key 和 value 还有这样几个影响:

a. 这些过大的数据需要更多的时间去传输数据,对网络缓存、带宽都有影响

b. 过大的数据传输可能会导致其他的请求超时:

假设客户端设置的超时时间是 1 秒。如果应用同时请求 ‘A’ 和 ‘B’ 两个 key。通常我们会使用 pipelining 的方法,这时 A 和 B 会逐个等待服务器对它们的响应。如果 A 的响应数据过大,它可能会吃掉其他请求的超时时间。如下图例子,如果 A 的响应数据过大,它会吃掉其他请求的超时时间 A B Timeout 影响

c. 如果是经常访问的数据,以上的影响会更加经常发生。

所以当 key 和 value 过大的时候,可能更需要优化数据结构,将 key 和 value 的值都变小。

『过大』的定义是什么

然而到底多大的 key 和 value 算大?我们上面描述的两种方案到底哪个好些? 这个时候就需要使用一些性能测试工具来评估一下实际的影响,恰好 Redis 有官方的 redis-benchmark工具。它类似 Apache 的 ab测试。

redis-benchmark 使用示例:

redis-benchmark -n 1000000 -t set,get -P 16 -q SET: 718390.81 requests per second GET: 864304.25 requests per second

回到对应到上面说的两个方案,使用 SCRIPT LOAD 命令,利用 lua 脚本构造我们想要的数据。这里使用 10000 次操作,每100次一个pipeline 命令提交。

方案1,多个map分别序列化后存储:

redis-benchmark -n 10000 -P 100 -q SCRIPT LOAD "local bulk = {}; local s = '{\'foo\':\'bar\',\'foo1\':\'bar1\',\'foo2\':\'bar2\',\'foo3\':\'bar3\'}'; for i=0,10,1 do bulk[i] = s; end; redis.call('HMSET', 'foo', unpack(bulk));" 结果:> 370370.38 requests per second

方案2,一个大string

redis-benchmark -n 10000 -P 100 -q SCRIPT LOAD "local plain = '' local s = '{\'foo\':\'bar\',\'foo1\':\'bar1\',\'foo2\':\'bar2\',\'foo3\':\'bar3\'}'; for i=0,10,1 do plain= plain..s; end; redis.call('HMSET', 'foo', 'cache', plain);" 结果:> 208333.33 requests per second

可以看到,我们开头提到的业务场景下,方案1要快了不少。

那对于一般的场景结论是什么呢?到底什么时候需要拆分,什么时候用一个大的序列化 string 节约CPU资源呢?

结论

建议是大于 50k 的数据,就优先选择拆分吧。具体情况可以结合上面的流程,逐个分析:

redis 本身剩余存储空间够吗?这类数据频率大不大,带宽和超时会是问题吗?用redis-benchmark跑一下实际业务场景,看性能是否满足需求。

本文是搬运我自己博客到 CSDN 的第一篇,原文点此。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有