zoukankan      html  css  js  c++  java
  • Redis内存最优使用

    背景:有一个接入系统专门对采集到的微博、文章、微信、报刊、论坛、博客等等的数据进行解析,到目前为止已经大概存有3亿多的量

    需求:我们需要通过图片的ID号得到对应图片作者是谁(这个可以随意)

    问题:那么我们如何通过redis来解决这个问题并进行优化呢?

    首先,这个通过图片ID反查用户UID的应用有以下几点需求:

    • 查询速度要足够快
    • 数据要能全部放到内存里,最好是一台EC2的 high-memory 机型就能存储(17GB或者34GB的,68GB的太浪费了)
    • 支持持久化,这样在服务器重启后不需要再预热

      首先否定了数据库存储的方案,保持了KISS原则(Keep It Simple and Stupid),因为这个应用根本用不到数据库的update功能,事务功能和关联查询等等牛X功能,所以不必为这些用不到的功能去选择维护一个数据库。

      于是我们选择了Redis,Redis是一个支持持久化的内存数据库,所有的数据都被存储在内存中(忘掉VM吧),而最简单的实现就是使用Redis的String结构来做一个key-value存储就行了。像这样:

    > HSET "mediabucket:1155" "1155315" "939"
    > HGET "mediabucket:1155" "1155315"
    > "939"

      其中1155315是图片ID,939是用户ID,我们将每一张图片ID为作key,用户uid作为value来存成key-value对。然后进行了测试,将数据按上面的方法存储,1,000,000数据会用掉70MB内存; 300,000,000张照片就会用掉21GB的内存。对比预算的17GB还是超支了。

      (其实这里我们可以看到一个优化点,我们可以将key值前面相同的media去掉,只存数字,这样key的长度就减少了,减少key值对内存的开销【注:Redis的key值不会做字符串到数字的转换,所以这里节省的,仅仅是media:这6个字节的开销】经过实验,内存占用会降到50MB,总的内存占用是15GB,是满足需求的,但是继续改进仍然有必要)

      于是向Redis的开发讨论组询问优化方案,得到的回复是使用Hash结构。具体的做法就是将数据分段,每一段使用一个Hash结构存储,由于Hash结构会为单个Hash元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在上面的String结构里是不存在的。而这个一定数量是由配置文件中的hash-zipmap-max-entries参数来控制的。经过我们的实验,将hash-zipmap-max-entries设置为1000时,性能比较好,超过1000后HSET命令就会导致CPU消耗变得非常大。

      于是改变了方案,将数据存成如下结构:

    > HSET "mediabucket:1155" "1155315" "939"
    > HGET "mediabucket:1155" "1155315"
    > "939"

      图片ID为7为,通过取其前四位为Hash结构的key值,保证了每个Hash内部只包含3位的key,也就是1000个。

      再做一次实验,结果是每1,000,000个key只消耗了16MB的内存。总内存使用也降到了5GB,满足了应用需求。

      (同样的,这里我们还是可以再进行优化,首先是将Hash结构的key值变成纯数字,这样key长度减少了12个字节,其次是将Hash结构中的subkey值变成三位数,这又减少了4个字节的开销,如下所示。经过实验,内存占用量会降到10MB,总内存占用为3GB)

    > HSET "1155" "315" "939"
    > HGET "1155" "315"
    > "939"

      优化无止境,只要肯琢磨。希望你在使用存储产品时也能如此爱惜内存。

  • 相关阅读:
    ch_6802 車的放置
    ch_POJ2182 Lost Cows
    ch_4201 楼兰图腾
    luogu_P3368【模板】树状数组 2
    门面
    建造者
    模板方法
    状态
    抽象工厂
    工厂方法
  • 原文地址:https://www.cnblogs.com/liang1101/p/6263009.html
Copyright © 2011-2022 走看看