Redis(一):数据结构 |
您所在的位置:网站首页 › 字典是一种什么类型 › Redis(一):数据结构 |
前言
从本文开始,我将分享一下近期自学 Redis 的学习笔记,其中大部分来源于极客时间的《Redis核心技术与实战》和小林coding。 我将在后续文章中陆续介绍以下内容:Redis自定义的数据结构、数据类型,线程模型、持久化、内存管理、通信、网络IO、并发问题、事务、主从架构、发布订阅机制、哨兵机制、切片集群、缓存问题、性能问题等。 概览-Redis是什么Redis 的全称为 Remote Dictionary Server,远程数据服务。是使用 C 语言编写的。 Redis 是一种基于内存的键值对数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 Redis 的快,一方面得益于内存的快,另一方面是由于 Redis 的底层架构和许多自定义的高效数据结构。相较于同样基于内存的键值对数据库 Memcache,Redis 有更多的数据类型,能够满足更多的应用场景。 底层架构Redis 中的数据就是一个个键值对,其中的 key 是字符串对象,而 value 可以是许多类型对象(String、List、Hash 等,后续会讲到)。Redis 使用了一个哈希表「dictht」来保存所有键值对。 Redis 存储数据所涉及到的数据结构如下图所示: dictht 和 dictEntry 的结构如下: typedef struct dictht { //哈希表数组 dictEntry **table; //哈希表大小 unsigned long size; //哈希表大小掩码,用于计算索引值 unsigned long sizemask; //该哈希表已有的节点数量 unsigned long used; } dictht; typedef struct dictEntry { //键值对中的键 void *key; //键值对中的值 union { void *val; uint64_t u64; int64_t s64; double d; } v; //指向下一个哈希表节点,形成链表 struct dictEntry *next; } dictEntry;dictEntry 结构里键值对中的值是一个「联合体 v」定义的,因此,键值对中的值可以是一个指向实际值的指针,或者是一个无符号的 64 位整数或有符号的 64 位整数或 double 类的值。这么做的好处是可以节省内存空间,因为当「值」是整数或浮点数时,就可以将值的数据内嵌在 dictEntry 结构里,无需再用一个指针指向实际的值,从而节省了内存空间。 哈希冲突什么是哈希算法? 哈希算法也叫散列算法,一般来说满足这样的关系:f(data)=key,输入任意长度的 data 数据,经过哈希算法处理后输出一个定长的数据 key。同时这个过程是不可逆的,无法由 key 逆推出 data。 什么是哈希冲突? 哈希冲突就是多个不同的 key 通过哈希算法计算出了相同的 data。再优秀的哈希算法,也仍然可能存在哈希冲突,数据量越大,哈希冲突的可能性越高。 举一个最简单的例子,假如哈希算法采用对 8 取模这个操作,那么所有整数类型的 key 通过这个哈希算法都能得出 0~7 这八个值中的一个,就能分配到相应的哈希槽中去了。但是会有多个值会被分配到同一个哈希槽中(比如 1 和 9、2 和 10)。 Redis 为了解决哈希冲突,在哈希表槽位(dictEntry)中维护了一个链表,当多个 key 映射到同一个槽位时,这些键值对就会形成一个链表。 哈希表的大小不变,所以随着数据量的增加,哈希冲突率会越来越高,带来的影响是查找的速度会越来越慢(因为每次都要遍历一个长链表)。Redis 使用了 rehash 策略来解决这个问题,后续会详细讲解。 查找数据在进行哈希表操作时,首先对 key 进行哈希计算,根据哈希值(对应的是数组的下标)找到对应的槽位(dictEntry),然后遍历该槽位的链表,查找与 key 相同的节点。如果哈希冲突率较低,链表的长度较短,那么整个过程的时间复杂度大约为常数级别,即 O(1)。 redisObjectRedis 中定义了许多类型对象,如 String、List、Hash、Set 等,每个对象都由 redisObject 结构表示。 对象结构里包含的成员变量: type,4bit,标识该对象是什么类型的对象;encoding,4bit,标识该对象使用了哪种底层的数据结构;ptr,8B,指向底层数据结构的指针。lru,24bit,记录了这个对象最后一次被访问的时间以及访问频次,用于淘汰过期的键值对;refcount,4B,记录了对象的被引用计数,用于内存管理;一个 redisObject 对象的大小为 16 字节,除了指针外的数据有时统称为元数据,元数据和指针各占 8B。 最后本文介绍了 Redis 底层的数据结构,Redis 存储数据是使用哈希表的,所以能够实现快速地查询数据。下一节将介绍 Redis 实现的各种数据结构。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |