在Redis中存储3000万条记录

时间:2018-12-01 18:53:54

标签: redis

我想知道存储这些数据的最有效方法。

我每天需要跟踪30-50百万个数据点。它需要非常快的读写速度,所以我正在使用redis。

数据仅需要持续24小时,此时将EXPIRE

数据看起来像是键/值hash

{
  "statistics:a5ded391ce974a1b9a86aa5322ea9e90": {
    xbi: 1,
    bid: 0.24024,
    xpl: 25.0,
    acc: 40,
    pid: 43,
    cos: 0.025,
    xmp: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    clu: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

我用很多x替换了实际的字符串,但这是字符串的正确长度。

到目前为止,根据我的计算...。这将使用数百GB的内存。看起来正确吗?

这主要是短暂的日志记录数据,很重要,但不足以尝试支持写入磁盘或故障转移。我很乐意将其保留在1台机器上,如果这样可以简化操作。

在这种情况下减少内存空间的最佳方法是什么?有没有更好的方法可以做到这一点? Redis是否在单个实例上支持300GB?

2 个答案:

答案 0 :(得分:2)

在redis.conf中-将hash-max-ziplist-value设置为比字段'xmp'的长度大1的值。然后重新启动Redis,并观察您的内存明显下降。

默认值为64。增加该值会在修改或在哈希中添加新字段时提高cpu利用率。但是您的用例似乎仅是创建的,在那种情况下增加设置应该没有任何缺点。

答案 1 :(得分:1)

  

这将使用数百GB的内存。看起来正确吗?

  

redis是否在单个实例上支持300GB?

  

有没有更好的方法可以做到这一点?

您可以尝试以下方法:

避免使用哈希

由于始终使用HGETALL获取日志的所有字段,因此无需将日志另存为HASHHASHSTRING消耗更多的内存。

您可以将所有字段序列化为一个字符串,并将日志另存为键值对:

SET 'statistics:a5ded391ce974a1b9a86aa5322ea9e90' '{xbi: 1, bid: 0.24024, and other fields}'

@Sripathi Krishnan的答案提供了另一种避免HASH的方法,即配置Redis将HASH编码为ZIPLIST。如果您不与其他应用程序共享Redis,则是一个好主意。否则,此修改可能会导致其他问题。

压缩数据

为了减少内存使用,您可以尝试压缩数据。 Redis可以存储二进制字符串,因此您可以使用gzip,snappy或其他压缩算法将日志文本压缩为二进制字符串,然后将其保存到Redis。

通常,当输入较大时,可以获得更好的压缩率。因此,最好压缩整个日志,而不是一个一个地压缩每个字段。

副作用是日志的生产者和使用者需要花费一些CPU来压缩和解压缩数据。但是,通常这不是问题,并且可以减少一些网络带宽。

批量写入和批量读取

如上所述,如果您想获得更好的压缩效果,则应该获得更大的输入量。因此,如果您可以批量写入多个日志,则可以压缩该批日志以获得更好的压缩效果。

  1. 将多个日志压缩为一个批次:compress(log1, log2, log3) -> batch1: batch-result
  2. 将批处理结果作为键值对放入Redis:SET batch1 batch-result
  3. 为批次建立索引:MSET log1 batch1 log2 batch1 log3 batch1

当您需要获取日志时:

  1. 搜索索引以获取批处理密钥:GET log1-> batch1
  2. 获取批处理结果:GET batch1->批处理结果
  3. 解压缩批处理结果并从结果中查找日志

最后一种方法是最复杂的方法,额外的索引将花费一些额外的内存。但是,它可以大大减少数据的大小。

这些方法还能实现什么,很大程度上取决于您的日志。您应该做很多基准测试:)