Redis 基础数据结构(四)

这一节我们介绍Hash(字典)数据类型

一、hash(字典)简单介绍

1、Redis的hash相当于java语言里面的HashMap,内部存储了很多键值对,实现结构也和HashMap是类似的,都是基于数组+链表实现的二维结构。

2、不同的是Redis的字典结构只能存储字符串。

3、Redis的rehash操作采用了渐进式resha策略,渐进式rehash会在rehash操作时,保留新旧两个hash结构,查询时会同时查询两个hash结构,在后续的定时任务以及hash指令操作时,渐进地将旧的数据迁移到新的hash结构中。

4、hash结构也可以用来存储用户信息,与字符串需要一次性全部序列化整个对象不同,hash可以对用户结构中每个单独的字段进行存储。这样当我们需要获取用户信息时,可以部分获取,避免浪费网络流量。

5、hash结构的存储消耗要高于单个字符串,所以在使用hash存储还是使用字符串存储时,要注意权衡。

6、hash结构中单个的key也可以进行计数操作,对应的指令是hincrby,和incr的使用方法基本一致。

com.xiaozhameng.aliyun:6379> hset books java 'think in java' python 'python cookbook'
(integer) 2
com.xiaozhameng.aliyun:6379> hset books golang 'learning go programming'
(integer) 1
com.xiaozhameng.aliyun:6379> hgetall books
1) "java"
2) "think in java"
3) "python"
4) "python cookbook"
5) "golang"
6) "learning go programming"
com.xiaozhameng.aliyun:6379> hlen books
(integer) 3
com.xiaozhameng.aliyun:6379> hget books java
"think in java"
com.xiaozhameng.aliyun:6379> hset user-zhameng age 26
(integer) 1
com.xiaozhameng.aliyun:6379> hincrby user-zhameng age 1
(integer) 27
com.xiaozhameng.aliyun:6379> 

二、字典(hash)内部实现

1、字典是Redis中使用较为频繁的复合数据结构,除了hash结构会用到字典外,整个redis数据库的所有key和value也组成了一个全局字典。带有过期时间的key的集合也是一个字典,zset集合中存储value和score值的映射关系也是通过字典结构来实现的。

struct RedisDb {
	dict* dict;		// all keys key => value
	dict* expires;	// all expired keys key=>long(timestamp)
}

struct zset {
	dict *dict;		// all values values=>score
	zskiplist *zsl;
}

2、字典结构的内部包含了两个hashtable,通常情况下只有一个hashtable有值,但是在字典扩容缩容时,需要分配新的hashtable,然后进行渐进式搬迁。这时候两个hashtable存储的分别是旧的hashtable和新的hashtable,搬迁结束后,旧的hashtable被删除,新的hashtable取而代之。

3、字典数据类型的hashtable结构和java的HashMap 几乎是一样的,都是通过一维数组加上二维链表实现的,采用分桶的方式解决hash冲突。

4、渐进式rehash,大字典的扩容是比较耗时的,需要重新申请数组,然后将旧字典中所有链表中的元素重新搬迁到新的数组下面,这是一个O(n)时间复杂度的操作,所以redis使用了渐进式rehash,虽然搬迁的过程变长了,但是肯定能搬完。你可能有疑问,既然redis的搬迁操作是在后续的hash操作中发生的,那么当客户端闲下来的时候,没有指令触发搬迁,redis的搬迁就停止了吗? 当然不是的,redis设计了定时任务对字典进行主动搬迁。

5、查找过程也是类似java中的查找。这里不做赘述。

6、扩容条件,正常情况下,当hash表中的元素个数等于一维数组的长度时,就会触发扩容,扩容新数组的长度是原来容量的二倍。不过如果redis正在做bgsave,为了减少内存页的过多分离(Copy On Write),redis尽量不去扩容,但是如果hash表已经非常满了,元素的个数已经达到了一维数组长度的5倍,这个时候就会强制扩容。

7、缩容,缩容的条件是元素个数低于数组长度的10%,缩容不会考虑redis的bgsave操作。

8、Redis Bgsave 命令用于在后台异步保存当前数据库的数据到磁盘的操作。BGSAVE 命令执行之后立即返回 ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

 

参考博客:https://www.jianshu.com/p/658365f0abfc

参考书籍:redis深度历险-核心原理与应用实战

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值