点击上方“Java之间”,选择“置顶或者星标”

你关注的就是我关心的!

作者:goodspeed

微信公众号:四月(ID:hiiiapril)

在stackoverflow 看到一个问题,Redis strings vs Redis hashes to represent JSON: efficiency?内容如下:

I want to store a JSON payload into redis. There's really 2 ways I can do this:

  1. One using a simple string keys and values.

    key:user, value:payload (the entire JSON blob which can be 100-200 KB)

    SET user:1 payload

  2. Using hashes

    HSET user:1 username "someone"HSET user:1 location "NY"HSET user:1 bio "STRING WITH OVER 100 lines"

Keep in mind that if I use a hash, the value length isn't predictable. They're not all short such as the bio example above.Which is more memory efficient? Using string keys and values, or using a hash?

string 和 hash 直观测试

首先我们先测试用数据测试一下,测试数据结构如下:

values = {    "name": "gs",    "age": 1}

使用for 生成10w个key,key的生成规则为:

for i in range(100000):key = "object:%d" % i

把数据分别以hash 和 string(values 使用 json encode 为string )的形式存入redis。

结果如下:

hash 占用 10.16M

hash 占用 10.15M

这看起来和我们印象中hash 占空间比较大的观念不太一致,这是为什么呢?

这里是因为Redis 的hash 对象有两种编码方式:

  1. ziplist(2.6之前是zipmap)

  2. hashtable

当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist 编码:

  1. 哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节;

  2. 哈希对象保存的键值对数量小于 512 个;

不能满足这两个条件的哈希对象需要使用 hashtable 编码。上述测试数据满足这两个条件,所以这里使用的是ziplist来存储的数据,而不是hashtable。

注意这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value 选项和 hash-max-ziplist-entries 选项的说明。

hash-max-ziplist-entries for Redis >= 2.6hash-max-ziplist-value for Redis >= 2.6

ziplist

ziplist 编码的数据底层是使用压缩列表作为底层数据结构,结构如下:

hash 对象使用ziplist 保存时,程序会将保存了键的ziplist节点推入到列表的表尾,然后再将保存了值的ziplist节点推入列表的表尾。

使用这种方式保存时,并不需要申请多余的内存空间,而且每个Key都要存储一些关联的系统信息(如过期时间、LRU等),因此和String类型的Key/Value相比,Hash类型极大的减少了Key的数量(大部分的Key都以Hash字段的形式表示并存储了),从而进一步优化了存储空间的使用效率。

在这篇redis memory optimization官方文章中,作者强烈推荐使用hash存储数据

Use hashes when possible

Small hashes are encoded in a very small space, so you should try representing your data using hashes every time it is possible. For instance if you have objects representing users in a web application, instead of using different keys for name, surname, email, password, use a single hash with all the required fields.

But many times hashes contain just a few fields. When hashes are small we can instead just encode them in an O(N) data structure, like a linear array with length-prefixed key value pairs. Since we do this only when N is small, the amortized time for HGET and HSET commands is still O(1): the hash will be converted into a real hash table as soon as the number of elements it contains will grow too much (you can configure the limit in redis.conf).

This does not work well just from the point of view of time complexity, but also from the point of view of constant times, since a linear array of key value pairs happens to play very well with the CPU cache (it has a better cache locality than a hash table).

hashtable

hashtable 编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用一个字典键值对来保存:

  • 字典的每个键都是一个字符串对象, 对象中保存了键值对的键;

  • 字典的每个值都是一个字符串对象, 对象中保存了键值对的值。

hashtable 编码的对象如下所示:

第二次测试

values = {"name": "gs","age": 1,"intro": "long..long..long..string"}

第二次测试方式和第一次一样,只是把测试数据中加了一个大的字符串,以保证hash 使用hashtable 的方式存储数据

结果如下:

hashtable: 1.13G

string: 1.13G

基本一样,这里应该主要是Hash类型极大的减少了Key的数量(大部分的Key都以Hash字段的形式表示并存储了),从而进一步优化了存储空间的使用效率。

NOTE: 读取和写入的速度基本一致,差别不大

回到这个问题,对于string 和 hash 该如何选择呢?

我比较赞同下面这个答案:

具体使用哪种数据结构,其实是需要看你要存储的数据以及使用场景。

如果存储的都是比较结构化的数据,比如用户数据缓存,或者经常需要操作数据的一个或者几个,特别是如果一个数据中如果filed比较多,但是每次只需要使用其中的一个或者少数的几个,使用hash是一个好的选择,因为它提供了hget 和 hmget,而无需取出所有数据再在代码中处理。

反之,如果数据差异较大,操作时常常需要把所有数据都读取出来再处理,使用string 是一个好的选择。

当然,最简单的就是听从官方的建议,放心的使用hash 吧。

还有一种场景:如果一个hash中有大量的field(成千上万个),需要考虑是不是使用string来分开存储是不是更好的选择。

参考链接

[1] Redis strings vs Redis hashes to represent JSON: efficiency?: https://stackoverflow.com/questions/16375188/redis-strings-vs-redis-hashes-to-represent-json-efficiency[2] redis memory optimization: https://redis.io/topics/memory-optimization[3] Redis 设计与实现: http://redisbook.com/preview/object/hash.html

最近热文阅读:

1、你是一直认为 count(1) 比 count(*) 效率高么?

2、Java 13新特性抢先看,预计 9 月发布!

3、Spring Boot 中 10 行代码构建 RESTful 风格应用!

4、Spring 为啥默认把Bean设计成单例的?

5、完了!服务器沦为肉鸡了!排查过程!

6、聊一聊 Spring 中的线程安全性

7、分库分表的4个面试连环炮问题!不会就惨了!

8、面试官:用过ThreadLocal吗?它保证线程安全的原理是啥?

9、经典面试题:为什么要把系统拆分成分布式的,为啥要用Dubbo?

10、Java中令人眼花撩乱的数字魔法!

关注公众号,你想要的Java都在这里!

string生成固定长度的哈希_Redis 选择Hash还是String 存储数据?相关推荐

  1. Java 生成固定长度随机中文字符串

    /*** * 生成固定长度随机中文,kuojung * @param n 中文个数 * @return 中文串 */ public static String getRandomChineseStri ...

  2. java随机产生100个大小写字母_Java生成固定长度的随机字符串(以大小写字母和数字)...

    packageorg.jimmy.autosearch2019.test;importjava.util.ArrayList;importjava.util.Random;/***@authorラピス ...

  3. Java生成固定长度的随机字符串(以大小写字母和数字)

    package org.jimmy.autosearch2019.test;import java.util.ArrayList; import java.util.Random;/*** @auth ...

  4. R语言使用seq函数生成数据序列、seq函数在指定范围内生成固定长度的序列、指定数据序列的第一个数值、最后一个数值以及另外一个数据序列(along.with)

    R语言使用seq函数生成数据序列.seq函数在指定范围内生成固定长度的序列.指定数据序列的第一个数值.最后一个数值以及另外一个数据序列(along.with) 目录

  5. python生成固定长度随机数_python日记——random模块

    random random模块用于生成伪随机数. 真正意义上的随机数(或者随机事件)是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的.而计算机中的随机数是所谓的随机函数按照一定算法模拟产生 ...

  6. [C++]char转换为string ,固定长度的char数组转换为string

    char转换为string 固定长度的char数组转换为string 使用socket编程时候,需要将受到的字符串数组转换为string,但是转换后的字符串总会附加一些,转义字符. 直接上code c ...

  7. android string参数最大长度,每日一问 | 我们经常用的 String类型,你知道它最大可以放多长的字符串吗?...

    String被用作常量时,它被编译器当成字面量存放于常量池.常量池中主要存放两大类常量:字面量和符号引用:常量池中的每一个常量都是一个表,字符串常量存于CONSTANT_Utf8_info表(Tip: ...

  8. 生成固定长度的序列号,excel表格自动增加

    =LEFT(A1,8)&REPT("0",8-LEN(DEC2HEX(HEX2DEC(RIGHT(A1,8))+1)))&DEC2HEX(HEX2DEC(RIGHT ...

  9. php随机数字总和固定,php 随机生成固定长度整数、各种服务器请求方法

    搜索热词 1.随机生成整数函数,感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编来看看吧. 经测试代码如下: @H_301_3@/** * 随机生成整数函数(生成位数:$pw_length) ...

最新文章

  1. 大名鼎鼎的Requests库用了什么编码风格?
  2. 使用docker中mysql镜像
  3. Apache Tomcat 5.5 Servlet/JSP 容器
  4. 基元线程同步构造之waithandle中 waitone使用
  5. python安装详细步骤mac_Mac OS X10.9安装的Python2.7升级Python3.3步骤详解
  6. parseInt() 函数 转载
  7. java executor spring_java - Spring TaskExecutor实现 - 堆栈内存溢出
  8. 平方矩阵——3种思路
  9. 冒充云销售的懒虫和毒虫们
  10. 他看了几千份技术简历,愿意把技术简历的秘籍传授给你
  11. android app性能优化大汇总(UI渲染性能优化)
  12. css实现仿element ui配色的小圆圈状态标记
  13. for of与for in的区别
  14. 传圆通老板娘2.3亿元购香港豪宅 税金达5400万
  15. UUess网络电视2007,UUESE免费下载,最新版UUESS官方免费下载 - uuess.org.cn
  16. 钉钉微应用PC端开发
  17. Win10系统导入证书私钥
  18. 计算机性能安全性,第一章 计算机安全与性能 — 计算机性能评价
  19. Mysql 计算时间差、按条件求和、计算百分比
  20. socket用户名登录c语言,用C语言socket登入斗鱼弹幕服务器的问题

热门文章

  1. 抖音的标题写什么内容_看了这篇文章,我才真正明白什么才是英语速成之路!感恩...
  2. 关联规则挖掘算法_#数据挖掘初体验 使用weka做关联规则
  3. 三菱触摸屏usb驱动安装_2020年三菱EXPRESS SWB和LWB:竟然是日系中唯一没有屏幕的面包车...
  4. PCLVisualizer可视化类
  5. 剑指offer:面试题11. 旋转数组的最小数字
  6. 利用python获取指定url在ATS中缓存对象的信息
  7. s-sgdisk源码分析 “--set-alignment=value分区对齐参数”
  8. Linux bash管道符“|”使用介绍与例子
  9. Flutter中集成Font Awesome
  10. redis使用epoll