本文转载自微信公众号《程序员小凡》,作者范米莉。转载本文请联系程序员小凡公众号.redis的hash的基本命令暂且不多说。我们直接在redis的hash结构中输入文本。有这样的现象:127.0.0.1:6379>hsetuser:001namejohnage25sexman(integer)3127.0.0.1:6379>hgetalluser:0011)"name"2)"john"3)"age"4)"25"5)"sex"6)"man"Wefirstsetthename,age,andsexattributesforuser:001,andthengetallofthemthroughhgetallproperties,italllooksnormalbutthen127.0.0.1:6379>hsetuser:002namejohnage25sexmanextraxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(integer)4127.0.0.1:6379>hgetalluser"2)4)"hgetalluser:0021)"hgetalluser:0021)"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"5)"sex"6)"man"7)"age"8)"25"我们设置了一个额外的属性foruser:002,而且设置的值比较大,然后发现我们在使用hgetall获取所有属性的时候,返回的顺序并不是按照我们设置的属性的顺序,这是为什么呢?其实主要是因为哈希数据结构的底层实现为字典(dict),which也是redisDb用来存储k-v的数据结构。当数据量比较小的时候,或者单个元素比较少的时候,底层存储在ziplist中,可以通过下面的参数hash-max-ziplist-e设置数据大小和元素个数阈值ntries512//ziplist元素个数超过512个,会改为hashtable编码hash-max-ziplist-value64//当单个元素大小超过64bytes时,会改为hashtable编码对于上面的例子,主要原因是单个元素的大小超过了改为64byte,所以改为hashtable编码,导致hgetall获取属性的顺序与设置的顺序不一样。其实很多同学也有一个疑问。hash和string类型的本质区别是什么?其实我们从源码中可以看出,对于string类型,string类型是基于RedisDb的。如果字符串数量不断增加,会导致dicttht部分不断rehash。对于hash类型,hash不存在dictht连续rehash的问题。也有优点和缺点。比如hash不能给某个key设置过期时间,redis有一个很大的忌讳,就是不要让某个key过大容易阻塞,所以我个人比较推荐string方式
