美文网首页
一次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