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

背景

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

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

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

  2. 将所有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 有两个问题:

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

  2. 容量过大的 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 的数据,就优先选择拆分吧。具体情况可以结合上面的流程,逐个分析:

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

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

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值