Redis学习(一) —— 数据结构

一、string

Redis字符串是可修改字符串,在内存中以字节数组形式存在。

下面是string在源码中的定义,SDS(Simple Dynamic String)

struct SDS<T> {
  T capacity; // 数组容量
  T len; // 数组长度
  byte flags; // 特殊标识位,不理睬它
  byte[] content; // 数组内容
}

Redis规定字符串的长度不超过512M。

Redis字符串的两种存储方式:

  • 长度特别短,使用emb形式存储
  • 长度超过44,使用raw形式存储

扩容策略

字符串长度小于1M之前,扩容采用加倍策略,保留100%的冗余空间。(从源码中可以看到是现有的数组长度len+设定的容量大小capacity)
字符串长度超过1M后,每次扩容只多分配1M大小的冗余空间。


sds sdscatlen(sds s, const void *t, size_t len) {
    size_t curlen = sdslen(s);  // 原字符串长度

    // 按需调整空间,如果 capacity 不够容纳追加的内容,就会重新分配字节数组并复制原字符串的内容到新数组中
    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL; // 内存不足
    memcpy(s+curlen, t, len);  // 追加目标字符串的内容到字节数组中
    sdssetlen(s, curlen+len); // 设置追加后的长度值
    s[curlen+len] = '\0'; // 让字符串以\0 结尾,便于调试打印,还可以直接使用 glibc 的字符串函数进行操作
    return s;
}

二、 list

Redis的列表常用来做异步队列使用。

右边进,左边出是队列。

rpush books python java golang
lpop books

右边进,右边出是栈。

rpush books python java golang
rpop books

三、hash

Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。

789766-20190523102704025-786023364.png

hset books java "think in java"
hgetall books

Redis相比于Java的HashMap不同的是,采取了渐进式rehash,为的是不堵塞服务。

什么是渐进式rehash?

创建新的hashtable,同时保留旧的hashtable,并且通过定时任务将旧的hashtable中的key-value转移到新的hashtable,查询时,会同时查询新旧hashtable,等到完全转移完成,再将旧的删除掉。

789766-20190523103008525-749134289.png

这里思考一个问题?Java中的rehash,要怎么处理?不是渐进式的,那如何保证在rehash时进行查询,获取到正确的值?

四、set

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值NULL。

set 结构可以用来存储活动中奖的用户 ID,因为有去重功能,可以保证同一个用户不会中奖两次

五、zset

底层实现?

zset类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。它的内部实现用的是一种叫做「跳跃列表」的数据结构。

参考文档

[1]: 天下无难试之Redis面试刁难大全
[2]: Redis 深度历险:核心原理与应用实践
[3]: 十二张图带你了解 Redis 的数据结构和对象系统

转载于:https://www.cnblogs.com/fonxian/p/10899393.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值