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

字节玄铁师
• 阅读 2994

前言

本章接着上一节继续介绍 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.

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

部分源码:

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,一般情况下只是用一个.如图所示:

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

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

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

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

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

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

点赞
收藏
评论区
推荐文章
peter peter
4年前
Go-连接Redis-学习go-redis包
Redis介绍Redis是一个开源的内存数据结构存储,常用作数据库、缓存和消息代理。目前它支持的数据结构有诸如string、hash、list、set、zset、bitmap、hyperloglog、geospatialindex和stream。Redis内置了复制、Lua脚本、LRU清除、事务和不同级别的磁盘持久性,并通过RedisSentinel
Stella981 Stella981
3年前
Redis 哈希(Hash)
Redishash是一个string类型的field和value的映射表,hash特别适合用于存储对象。Redis中每个hash可以存储2的32次方1键值对(40多亿)。redis127.0.0.1:6379HMSETw3ckeyname"redistutorial"description"redisb
Wesley13 Wesley13
3年前
Java连接redis的使用示例
Java连接redis的使用示例        Redis是开源的keyvalue存储工具,redis通常用来存储结构化的数据,因为redis的key可以包含String、hash、listset和sortedlist。        Redisserver目前最稳定的版本是2.8.9,可以到官网http://redis.io/downlo
Stella981 Stella981
3年前
Django 之redis的应用
redis概述redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string,list列表队列和栈,set集合,sortedset有序集合,hash(hash表))
Stella981 Stella981
3年前
Redis学习笔记#5:Hashes
Hashes是由字段和对应值组成的maps对象,字段和值都是String类型。Hashes非常适合存储对象(比如用户的姓名,年龄等字段)!(https://img2018.cnblogs.com/blog/581445/201908/58144520190808085154492238468204.png)每个hash可以存储232 
Wesley13 Wesley13
3年前
2.Redis数据类型
Redis中存储数据是通过keyvalue存储的,对于value的类型有以下几种:字符串Hash类型ListSetSortedSet(zset)注:在redis中的命令语句中,命令是忽略大小写的,而key是不忽略大小写的。1String类型1.1  命令
Stella981 Stella981
3年前
Redis——基础数据结构
摘抄自《redis深度历险》。  Redis提供了5种基础数据结构,分别是String,list,set,hash和zset。1、String  Redis所有的键都是String。Redis的String是动态字符串,内部结构类似Java的ArrayList和CSTL中的Vector。内部分配的容量capacity一般高
Stella981 Stella981
3年前
Redis的主从复制
一、redis的五种数据类型:string是字符串类型,是redis最基本的数据类型。哈希类型hash,hash特别适合存储对象列表类型list,按照插入顺序排序集合类型set,不允许有重复数据有序集合类型zset,不允许有重复数据二、redis主从复制为了避免服务器停机导致数据库数据丢失,为了避免单点故障,我们需
Stella981 Stella981
3年前
Redis为什么这么快
Redis简介Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件它支持多种类型的数据结构,如字符串(String),散列(Hash),列表(List),集合(Set),有序集合(SortedSet或者是ZSet)与范围查询,Bitmaps,Hyperloglogs和
3A网络 3A网络
2年前
Redis 存储对象信息是用 Hash 还是 String
Redis存储对象信息是用Hash还是StringRedis内部使用一个RedisObject对象来表示所有的key和value,RedisObject中的type,则是代表一个value对象具体是何种数据类型,它包含字符串(String)、链表(List)、哈希结构(Hash)、集合(Set)、有序集合(Sortedset)。
京东云开发者| Redis数据结构(二)-List、Hash、Set及Sorted Set的结构实现
1引言之前介绍了Redis的数据存储及String类型的实现,接下来再来看下List、Hash、Set及SortedSet的数据结构的实现。2ListList类型通常被用作异步消息队列、文章列表查询等;存储有序可重复数