资讯专栏INFORMATION COLUMN

你确定不来了解一下Redis中 Hash的原理吗

MockingBird / 3324人阅读

摘要:前言本章接着上一节继续介绍的基础数据结构中的字典基本介绍也可以用来存储用户信息和不同的是可以对用户信息的每个字段多带带存储则需要序列化用户的所有字段后存储并且需要以整个字符串的形式获取用户而可以只获取部分数据从而节约网络流量不过内存占用要大于

前言

本章接着上一节继续介绍 Redis 的基础数据结构中的Hash字典.

基本介绍

Hash 也可以用来存储用户信息,和 String 不同的是 Hash 可以对用户信息的每个字段多带带存储,String 则需要序列化用户的所有字段后存储.并且 String 需要以整个字符串的形式获取用户,而 hash可以只获取部分数据,从而节约网络流量.不过 hash 内存占用要大于 String,这是 hash 的缺点.

> hset books java "Effective java"
(integer) 1
> hset books golang "concurrency in go"
(integer) 1
> hget books java
"Effective java"
> hset user age 17
(integer) 1
>hincrby user age 1    #单个 key 可以进行计数 和 incr 命令基本一致
(integer) 18

Redis 中的 Hash和 Java的 HashMap 更加相似,都是数组+链表的结构.当发生 hash 碰撞时将会把元素追加到链表上.值得注意的是在 Redis 的 Hash 中 value 只能是字符串.

内部原理

看完基本介绍之后,我们先来了解下 hash 的内部结构.第一维是数组,第二维是链表.组成一个 hashtable.

部分源码:

struct dictht {
    dictEntry **table;            //entry 数组
    long size;            //数组长度
    long used            //数组中的元素个数
    ...
}
struct dictEntry{
    void *key;                //hash 的 key
    void *val;                //hash 的 value
    dictEntry *next;            //下一个dictEntry 链表结构
}

在 Java 中 HashMap 扩容是个很耗时的操作,需要去申请新的数组,为了追求高性能,Redis 采用了渐进式 rehash 策略.这也是 hash 中最重要的部分.

渐进式 rehash

在 hash 的内部包含了两个hashtable,一般情况下只是用一个.如图所示:

在扩容的时候 rehash 策略会保留新旧两个 hashtable 结构,查询时也会同时查询两个 hashtable.Redis会将旧 hashtable 中的内容一点一点的迁移到新的 hashtable 中,当迁移完成时,就会用新的 hashtable 取代之前的.当 hashtable 移除了最后一个元素之后,这个数据结构将会被删除.如图所示:

数据搬迁的操作放在 hash 的后续指令中,也就是来自客户端对 hash 的指令操作.一旦客户端后续没有指令操作这个 hash.Redis就会使用定时任务对数据主动搬迁.

正常情况下,当 hashtable 中元素的个数等于数组的长度时,就会开始扩容,扩容的新数组是原数组大小的 2 倍.如果 Redis 正在做 bgsave(持久化) 时,可能不会去扩容,因为要减少内存页的过多分离(Copy On Write).但是如果 hashtable 已经非常满了,元素的个数达到了数组长度的 5 倍时,Redis 会强制扩容.

当hashtable 中元素逐渐变少时,Redis 会进行缩容来减少空间占用,并且缩容不会受 bgsave 的影响,缩容条件是元素个数少于数组长度的 10%.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37247.html

相关文章

  • 确定不来了解一下Redis Hash原理

    摘要:前言本章接着上一节继续介绍的基础数据结构中的字典基本介绍也可以用来存储用户信息和不同的是可以对用户信息的每个字段单独存储则需要序列化用户的所有字段后存储并且需要以整个字符串的形式获取用户而可以只获取部分数据从而节约网络流量不过内存占用要大于 前言 本章接着上一节继续介绍 Redis 的基础数据结构中的Hash字典. 基本介绍 Hash 也可以用来存储用户信息,和 String 不同的是...

    Thanatos 评论0 收藏0
  • 确定不来了解Redis 跳跃表原理

    摘要:前言本章将介绍中和的基本使用和内部原理因为这两种数据结构有很多相似的地方所以把他们放到一章中介绍并且重点介绍内部一个很重要的数据结构跳跃表基本介绍先来看看中集合很像中键值对无序唯一不为空值重复无序是中最特别的基础数据结构其他几个都能和大致对 前言 本章将介绍 Redis中 set 和 zset的基本使用和内部原理.因为这两种数据结构有很多相似的地方所以把他们放到一章中介绍.并且重点介绍...

    BigTomato 评论0 收藏0
  • 确定不来了解Redis 跳跃表原理

    摘要:前言本章将介绍中和的基本使用和内部原理因为这两种数据结构有很多相似的地方所以把他们放到一章中介绍并且重点介绍内部一个很重要的数据结构跳跃表基本介绍先来看看中集合很像中键值对无序唯一不为空值重复无序是中最特别的基础数据结构其他几个都能和大致对 前言 本章将介绍 Redis中 set 和 zset的基本使用和内部原理.因为这两种数据结构有很多相似的地方所以把他们放到一章中介绍.并且重点介绍...

    2i18ns 评论0 收藏0
  • 确定不来了解一下Redis列表原理

    摘要:前言在上一章中我们介绍了的一些内部原理在这一章中我们再来讨论在五种数据结构中的基本使用和一些内部实现基本介绍的呢相当于中的也是双向链表具有一些和同样的特征比如插入和删除一条很快时间复杂度为获取头结点和尾节点也很快时间复杂度也为随机读取则相对 前言 在上一章中我们介绍了 String 的一些内部原理,在这一章中我们再来讨论在五种数据结构中 List 的基本使用和一些内部实现. 基本介绍 ...

    big_cat 评论0 收藏0
  • 确定不来了解一下Redis列表原理

    摘要:前言在上一章中我们介绍了的一些内部原理在这一章中我们再来讨论在五种数据结构中的基本使用和一些内部实现基本介绍的呢相当于中的也是双向链表具有一些和同样的特征比如插入和删除一条很快时间复杂度为获取头结点和尾节点也很快时间复杂度也为随机读取则相对 前言 在上一章中我们介绍了 String 的一些内部原理,在这一章中我们再来讨论在五种数据结构中 List 的基本使用和一些内部实现. 基本介绍 ...

    elliott_hu 评论0 收藏0

发表评论

0条评论

MockingBird

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<