Redis刚出来时就比较受欢迎的主要原因之一就是丰富的数据结构,相比memcache的key-value,Redis的数据结构不仅为redis-server服务,同时主要是让程序员使用更方便,减少网络传输,降低程序设计复杂性,虽然redis为我们做了这么多,但我们需要了解其中一些实现机制,避免因为使用不合理造成Redis性能降低。
Redis主要数据结构包含了redis的字符串、链表、字典、Set等。
一、Redis字符串
Redis字符串叫做SDS,SDS封装了C语言的字符串,提高了一些命令性能、提供更多的api以及内存方面更合理的管理以及提供二进制数等安全管理。
提供给api的开发文档中区分普通字符串、字节作为key、value的命令,以及同时获取单个或者多个数据的命令。
二、Redis链表
Redis的链表是双向无环链表,redis-server内部很多功能基于redis链表实现,为了节约内存,如果redisObject的type 成员值是 REDIS_LIST 类型的,则当该list 的 elem数小于配置值: hash-max-ziplist-entries 或者elem_value字符串的长度小于 hash-max-ziplist-value, 则可以编码成 REDIS_ENCODING_ZIPLIST 类型存储,以节约内存. 否则采用 Dict 来存储。
Reids链表的api除了提供有基本list api以外,还提供queue的api。
三、Redis集合和有序集合
Redis 集合(set)使用REDIS_ENCONDING_INT与REDIS_ENCONDING_HT两种编码方式,当redis的set存入整数时(或默认整数个数大于512个)set编码方式为REDIS_ENCODING_INTSET,否则为集合的初始编码REDIS_ENCODING_HT。
Redis为了实现有序集合(sorted)使用了跳跃表+哈希表作为数据结构实现,跳跃表的排序是按照分值大小排序,当分值相同时候,按照元素大小进行排序。
四、Redis字典
Redis的字典使用哈希表作为存储,当出现哈希冲突时,哈希表使用链地址法解决冲突,每个字典有两个哈希表,一个是平时使用,另外一个作为rehash使用,redis使用渐进式rehash来实现扩容,避免rehash带来庞大计算量导致CPU过高,短时间无法提供服务。
五、其它
type keyname 可以查询对象的类型,object encoding keyname可以查询对应的编码,object refcount keyname可以查询对象引用个数,object idletime keyname可以查询对象的空闲时间,单位为秒。
ziplist特性是存储空间小,当数据量较小时候访问速度较快,但是数据量大时会影响插入速度。
| 类型 | 编码 | 对象 |
|---|---|---|
| REDIS_STRING | REDIS_ENCODING_INT | 整数字符串 |
| REDIS_STRING | REDIS_ENCODING_EMBSTR | embstar动态字符串(不能修改) |
| REDIS_STRING | REDIS_ENCODING_RAW | 动态字符串 |
| REDIS_LIST | REDIS_ENCODING_ZIPLIST | 压缩列表实现的列表对象 |
| REDIS_LIST | REDIS_ENCODING_LINKDELIST | 链表实现的列表对象 |
| REDIS_HASH | REDIS_ENCODING_ZIPLIST | 压缩集合实现的哈希表 |
| REDIS_HASH | REDIS_ENCODING_HT | 字典实现的哈希表 |
| REDIS_SET | REDIS_ENCODING_INTSET | 整数集合 |
| REDIS_SET | REDIS_ENCODING_HT | 字典集合 |
| REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 压缩列表实现的有序集合 |
| REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 跳跃表和字典实现的有序集合 |