疯狂的小鸡

Redis入门-基本数据类型

字数统计: 1.4k阅读时长: 5 min
2018/10/05 Share

此篇文章仅从理论上介绍Redis的基本数据类型,有关各类型的具体操作,可见Redis常用命令总结
更多Redis入门系列文章,参见Redis入门-大纲

RedisObject

Redis内部使用一个redisObject对象来表示所有的key,value。

type代表一个value对象具体是何种数据类型,有5种基本数据类型,分别是:String、List、Set、Hash、SortedSet(ZSet)。

encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:”123” “456”这样的字符串。

redisObject中的encoding

1
2
3
4
5
6
7
8
9
10
\#define OBJ_ENCODING_RAW 0     /* Raw representation */
\#define OBJ_ENCODING_INT 1 /* Encoded as integer */
\#define OBJ_ENCODING_HT 2 /* Encoded as hash table */
\#define OBJ_ENCODING_ZIPMAP 3 /* Encoded as zipmap */ // 已废弃
\#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
\#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
\#define OBJ_ENCODING_INTSET 6 /* Encoded as intset */
\#define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
\#define OBJ_ENCODING_EMBSTR 8 /* Embedded sds string encoding */
\#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists *

type与encoding对照表
type与encoding对照表

String

value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。也可以以json字符串形式存储对象。

实现方式:字符串对象的编码可以是int、raw或者embstr。如果一个字符串的内容可以转换为long,那么该字符串就会被转换成为long类型,对象的ptr就会指向该long,并且对象类型也用int类型表示。普通的字符串有两种,embstr和raw。embstr应该是Redis 3.0新增的数据结构,在2.8中是没有的。如果字符串对象的长度小于39字节,就用embstr对象。否则用传统的raw对象。

embstr的创建只需分配一次内存,而raw为两次(一次为sds分配对象,另一次为object分配对象,embstr省去了第一次, SDS是redis自定义的一种简单动态字符串)。相对地,释放内存的次数也由两次变为一次。embstr的objet和sds放在一起,更好地利用缓存带来的优势。
需要注意的是,redis并未提供任何修改embstr的方式,即embstr是只读的形式。对embstr的修改实际上是先转换为raw再进行修改。

Hash

这里value存放的是HashMap<String,String>,比较方便的就是操作其中的某个字段。例如在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。

实现方式: Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为ziplist,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

List

使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。 LIST还可以很好的完成排队,先进先出的原则。

实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。在Redis 3.2版本之前,一般的链表使用LINKDEDLIST编码。在Redis 3.2版本开始,所有的链表都是用QUICKLIST编码。两者都是使用基本的双端链表数据结构,区别是QUICKLIST每个节点的值都是使用ZIPLIST进行存储的。

Set

因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。当一个集合只包含整数值元素, 并且这个集合的元素数量不多时, Redis 就会使用整数集合(INTSET)作为集合键的底层实现。

Sorted Set

sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

CATALOG
  1. 1. RedisObject
  2. 2. String
  3. 3. Hash
  4. 4. List
  5. 5. Set
  6. 6. Sorted Set