Redis常用数据结构和存储结构-Hash

2021/7/21 2:06:14

本文主要是介绍Redis常用数据结构和存储结构-Hash,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

redis数据类型

String、Hash、Set、List、ZSet、Hyperloglog、Geo、Streams

2. Hash 哈希

内部结构,结合String的图,只是ptr指向其它数据结构,type为HASH

redis的哈希对象的底层存储可以使用ziplist(压缩列表)和hashtable。当hash对象可以同时满足一下两个条件时,哈希对象使用ziplist编码。
哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
哈希对象保存的键值对数量小于512个

ziplist

在这里插入图片描述

redis ziplist数据结构

ziplist的数据结构主要包括两层,ziplist和zipEntry。

ziplist包括zip header、zip entry、zip end三个模块。

zip entry由prevlen、encoding&length、value三部分组成。
prevlen主要是指前面zipEntry的长度,coding&length是指编码字段长度和实际- 存储value的长-
度,value是指真正的内容。 每个key/value存储结果中key用一个zipEntry存储,value用一个zipEntry存储。
每当有新的键值对加入到压缩列表时,程序会先将保存了键的压缩列表节点推入到压缩列表的表尾,然后再将保存了值的压缩列表节点推入到表尾。因此,保存了同一键值对的两个节点总是挨在一起。保存键的节点在前,保存值的节点在后。先添加到压缩列表的键值对放在表头方向,而后来添加的键值对放在表尾方向。

在这里插入图片描述
在这里插入图片描述

hashtable

在这里插入图片描述

压缩列表数据结构,从最底层到最高层dictEntry - dictht - dict

在这里插入图片描述

代码结构
/*Hash表一个节点包含Key,Value数据对 */
typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next; /* 指向下一个节点, 链接表的方式解决Hash冲突 */
} dictEntry;
 
/* 存储不同数据类型对应不同操作的回调函数 */
typedef struct dictType {
    unsigned int (*hashFunction)(const void *key);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} dictType;
 
typedef struct dictht {
    dictEntry **table; /* dictEntry*数组,Hash表 */
    unsigned long size; /* Hash表总大小 */
    unsigned long sizemask; /* 计算在table中索引的掩码, 值是size-1 */
    unsigned long used; /* Hash表已使用的大小 */
} dictht;
 
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2]; /* 两个hash表,rehash时使用*/
    long rehashidx; /* rehash的索引, -1表示没有进行rehash */
    int iterators; /*  */
} dict;
为什么定义两个dictht(两个hash表)?

redis默认使用ht[0],ht[1] 不会初始化和分配空间。
如果hash表节点数过多,就需要进行扩容。redis里这种操作叫rehash rehash步骤:

  1. 为ht[1]分配空间
  2. 将ht[0]的数据迁移到ht[1]上
  3. 释放ht[0]的空间
优点
  • 相关值存储在一个key中,节省内存空间
  • 只使用一个key,减少key冲突
  • 需要批量获取值时,只需要一个命令,减少IO
缺点
  • 不能给单独一个field设置过期时间
  • field多时,无法分布到多个节点
操作命令

1 HDEL key field2 [field2] 删除一个或多个哈希表字段
2 HEXISTS key field 查看哈希表 key中,指定的字段是否存在。
3 HGET key field 获取存储在哈希表中指定字段的值
4 HGETALL key获取在哈希表中指定 key 的所有字段和值
5 HINCRBY key field increment 为哈希表 key中的指定字段的整数值加上增量 increment 。
6 HINCRBYFLOAT key field increment 为哈希表 key中的指定字段的浮点数值加上增量 increment 。
7 HKEYS key 获取所有哈希表中的字段
8 HLEN key获取哈希表中字段的数量
9 HMGET key field1 [field2] 获取所有给定字段的值
10 HMSET key field1 value1 [field2 value2 ] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
11 HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。
12 HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值。
13 HVALS key 获取哈希表中所有值
14 HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的键值对。



这篇关于Redis常用数据结构和存储结构-Hash的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程