redis 基本数据类型适用场景及数据结构

  redisObject

        redis对象由redisObject统一管理,可以理解为redisObject是redis对象的父类,目前版本redisObject代码如下

#define LRU_BITS 24
typedef struct redisObject {
    unsigned type:4;  /* redis数据类型 */
    unsigned encoding:4;        /* redis数据结构类型 */
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time).*/
    int refcount;  /* 引用计数 */
    void *ptr;  /* 指向存储数据的指针 */ 
} robj;

        通过源码可以看出每个redis对象都有一个redisObject,其中type占用4b,encoding4b,lru24b,refcount4B加起来占用8B,64位指针占用8B。也就是说即使什么都不存,redisObject也要占用16B空间。

基本数据类型

String

数据结构

        简单字符串SDS存储,截取部分代码如下

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* 当前sds的长度 */
    uint64_t alloc; /* 为sds分配的内存大小 */
    unsigned char flags; /* 当前sds的类型 */
    char buf[];  /* sds实际存放的数据 */
};

        可以看到,len,alloc,flags都是额外占用的存储空间,为了充分利用空间,redis使用int ,embstr,raw 编码格式对sds内存布局做了优化。

        int :当保存的是 Long 类型整数时,redisObject中指针直接赋值为整数数据,不需要额外的指针再指向整数,节省了指针的空间开销。

        embstr:保存字符串数据,并且字符串<=44 字节,redisObject 与 sds是一块连续的内存区域,避免内存碎片。

        raw :保存字符串数据,并且字符串>44 字节,redisObject与sds分开存储,通过指针引用。

        sds详细信息可以参考https://github.com/antirez/sds 

适用场景

        String类型属于那种万金油类型,什么都能存,比如数组,对象可以转成json然后使用String存储。但这种行为很low,实际开发中还是要选择对应类型。

hash

数据结构

        使用压缩列表或哈希表存储。可通过修改redis.conf配置文件中参数修改

        hash-max-ziplist-entries:压缩列表结构保存的元素最大元素个数,默认512

        hash-max-ziplist-value:压缩列表保存的单个元素的最大长度,默认64

        以上两个条件任意一个不满足则由压缩列表转为哈希表

适用场景

        适合存储结构化数据,比如一级key为用户id,二级key为用户身份证,姓名等属性。但hash结构还有一个优点是可以代替一些特定的String。由于String类型占用内存空间比较大,所以对于一些有序key可以截取存储。例如根据手机号查找特定信息,手机号为13800001111可以根据实际情况截取前几位作为一级key,后几位作为二级key,value存储特定信息。

list

数据结构

        使用快速列表(quicklist),其本质为双向链表+压缩列表组成,由压缩列表保存实际数据,压缩列表满了新建压缩列表通过指针前后连接。默认每个压缩列表8K,可通过修改redis.conf配置文件中参数修改

        list-max-ziplist-size:其参数如下,默认-2,取正值表示每个快速列表有节点有几个压缩列表

        -5: 每个快速列表节点上的压缩列表大小不能超过64 Kb。
        -4: 每个快速列表节点上的压缩列表大小不能超过32 Kb。
        -3: 每个快速列表t节点上的压缩列表大小不能超过16 Kb。
        -2: 每个快速列表t节点上的压缩列表大小不能超过8 Kb,
        -1: 每个快速列表节点上的压缩列表大小不能超过4 Kb。

适用场景

        存储变更频率不高或不需要分页的的数组结构数据。

例如现有list= {A,B,C,D}对于分页数据 
先lrange list 0,1 读取到A,B
删除A,再lrange list 2,3 读取数据时会读取到只能读取到D。这样两次读取丢失了C

        list不适用于消息队列,消息队列可以使用stream类型。

set

数据结构

        使用哈希表或数组存储。可通过修改redis.conf配置文件中参数修改

        set-max-intset-entries :哈希表保存的最大元素个数,默认512,超过此值使用数据保存

适用场景

        set集合当中不允许重复的元素,利用此特性可以做一些取交集,并集,差集操作,比如群聊中判断是否有共同好友,推荐好友等操作

zset

数据结构        

        使用哈希表或跳表存储。可通过修改redis.conf配置文件中参数修改

        zset-max-ziplist-entries:压缩列表结构保存的元素最大元素个数,默认128
        zset-max-ziplist-value :压缩列表保存的单个元素的最大长度,默认64

        以上两个条件任意一个不满足则由压缩列表转为跳表

适用场景

        包括set适用场景,除此之外由于其为有序集合,还可以应用在一些排序列表中

压缩列表

        压缩列表(ziplist)这种数据结构不太常见,是redis为了节约内存开发的,其特点为一个压缩列表可以包含多个节点(entry),每个节点可以保存整数值或字节数组。ziplist结构如下

 <zlbytes> <zltail> <zllen> <entry> <entry> ... <entry> <zlend>

        zlbytes:压缩链表占用的字节数

        zltail:压缩链表头部到最后一个entry的偏移量

        zllen:压缩列表中entry数量

        entry:存储真正数据

        zlend:压缩列表结尾

        entry节点又由多个字段构成,源码中的英文翻译出来效果不太理想,entry中除保存数据外还保存上一个节点长度,当前节点长度,在遍历时不是通过指针建立每个entry的关系,而是通过计算长度获取到每个entry。

        关于压缩列表更多信息可以参考https://github.com/redis/redis/blob/unstable/src/ziplist.c

/* We use this function to receive information about a ziplist entry.
 * Note that this is not how the data is actually encoded, is just what we
 * get filled by a function in order to operate more easily. */
typedef struct zlentry {
    unsigned int prevrawlensize; /* Bytes used to encode the previous entry len*/
    unsigned int prevrawlen;     /* Previous entry len. */
    unsigned int lensize;        /* Bytes used to encode this entry type/len.
                                    For example strings have a 1, 2 or 5 bytes
                                    header. Integers always use a single byte.*/
    unsigned int len;            /* Bytes used to represent the actual entry.
                                    For strings this is just the string length
                                    while for integers it is 1, 2, 3, 4, 8 or
                                    0 (for 4 bit immediate) depending on the
                                    number range. */
    unsigned int headersize;     /* prevrawlensize + lensize. */
    unsigned char encoding;      /* Set to ZIP_STR_* or ZIP_INT_* depending on
                                    the entry encoding. However for 4 bits
                                    immediate integers this can assume a range
                                    of values and must be range-checked. */
    unsigned char *p;            /* Pointer to the very start of the entry, that
                                    is, this points to prev-entry-len field. */
} zlentry;

                

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redis支持五种数据结构类型:字符串(string)、列表(list)、哈希(hash)、集合(sets)、有序集合(sorted sets)。它们可以用于实现缓存、消息队列、计数器、在线聊天室、投票系统、排行榜等应用场景。 ### 回答2: Redis支持多种数据结构类型,常用的有字符串、哈希、列表、集合和有序集合。 1. 字符串(strings):最基本数据结构类型,可以存储字符串、整数或浮点数等。常用场景包括缓存、计数器和分布式锁等。 2. 哈希(hashes):类似于一个关联数组,可以存储多个字段和值的映射关系。适用于存储对象的各个属性,例如用户信息、商品详情等。 3. 列表(lists):支持在头部或尾部添加或删除元素,保持了元素的插入顺序。常用于消息队列、发布订阅系统和任务队列等场景。 4. 集合(sets):无序且唯一的元素集合。适用于需要对元素进行去重或集合操作的场景,例如标签云、社交关系等。 5. 有序集合(sorted sets):元素集合,每个元素都关联了一个分数,用于排序和获取范围内的元素。常见应用包括排行榜、热门文章等。 这些数据结构类型提供了丰富的功能和灵活性,可以根据不同的场景选择适合的数据结构Redis 的快速读写性能和丰富的数据类型使得它成为了很多应用场景的首选,包括缓存、计数器、消息队列、排行榜、实时数据分析等。 ### 回答3: Redis是一款开源的、高性能的非关系型内存数据库,支持多种数据结构类型。常用的Redis数据结构类型有字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。 字符串类型Redis基本数据结构类型,可以存储字符串和整数。它常用于缓存、计数器、共享会话等场景。 哈希类型可以存储多个字段和值的映射关系,类似于关联数组或字典。它适用于存储用户信息、商品信息等结构化的数据。 列表类型是有序的字符串列表,可以在列表的两端进行插入、删除和查找操作。它适合做消息队列、最新消息排行等场景。 集合类型是无序的字符串集合,可以对集合进行交集、并集和差集等操作,也支持添加、删除和查找元素。常用的场景包括社交关系、标签系统等。 有序集合类型是在集合类型的基础上,为每个元素关联一个分数,可以根据分数进行元素排序。它适用于排行榜、按照分数范围查找等场景。 除了以上几种数据结构类型Redis还提供了位图、地理位置等特殊类型,可以应用于统计用户在线时长、地理位置检索等特定需求。 总而言之,Redis提供了多种数据结构类型,每种类型都有其独特的使用场景。根据具体的业务需求,选择适合的数据结构类型可以提升数据处理效率和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值