美文网首页
一次redis内存使用缩小10倍的实验

一次redis内存使用缩小10倍的实验

作者: 提米锅锅 | 来源:发表于2019-12-05 22:56 被阅读0次

redis面试题有一个出现频率很高的问题是,你们用什么数据结构,如果你回答hash表,那么面试官马上会追问为什么?老实说手写红黑树确实有些面试造火箭,但是redis有没用过hash优化内存,真的是一个菜鸟和高手的分水岭,我上一个实验你就能看出有多大的意义。

测试场景:

我们有三十万个简单的key,value就是1到300000,默认情况我们用key value的方式直接存入redis,这也是一般小公司未优化的实现方式。

    public  void  run(){
        for(int i=1;i<300000;i++){
            redisTemplateFastJson.opsForValue().set("key" +i, i, 5, TimeUnit.MINUTES);
        }
    }

内存占用是31.56M


image.png

用hash的方式再做一次。

将三十万个key,用key值除于100的结果为hash表的索引,将余数作为hash表的field。所以三十万个key将得到3000个hash表,每个hash表有100个元素。

代码如下

    public  void  runForZiplist(){
        for(int i=1;i<300000;i++){
            Integer left = (i/100);
            Integer mod = (i%100);
            String hash = "hash_"+ left;
            HashOperations<String, String, Integer> vo = redisTemplateFastJson.opsForHash();
            vo.put(hash, mod.toString(), i);
        }
    }

查看redis内存占用,只用了3.57M

image.png

用了hash后取值方式需要做一些变化:

    public void getHash(){
        HashOperations<String, String, Integer> vo = redisTemplateFastJson.opsForHash();
        for(int i=1; i<1000;i++){
            Integer left = (i/100);
            Integer mod = (i%100);
            String hash = "hash_"+ left;
            log.info("key:" +i +" value:"+vo.get(hash, mod.toString())); ;
        }
    }

可以看到取到的value值是正确的,只是多加了2行原始key到新key的转换代码,性能没有损失,内存占用却大大减少,原因就是hash结构在key和value符合一定条件下会用ziplist结构存储,超过这个条件才会用普通的字典存放,而ziplist因为其特殊的结构是可以省内存的。

建议点击查看redis中ziplist的介绍

image.png

需要注意的是,ziplist是连续储存,从100个filed里取一个是也是顺序查找,所以如果一个hash表存上万个值,取值肯定是会变慢,程序在设计key的分裂算法时候需要注意,一般几百个就差不多了。

相关文章

网友评论

      本文标题:一次redis内存使用缩小10倍的实验

      本文链接:https://www.haomeiwen.com/subject/ydnjgctx.html