Redis的特性是“快”。一方面是因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快。另一方面归功于它的数据结构。键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是Redis快速处理的基础。

一、键值数据库基本架构

1. 访问框架

访问模式通常有两种:一种是通过函数库调用的方式供外部调用,比如提供**.so动态链接库链接到我们自己的程序中,提供键值存储功能;另一种是通过网络框架以Socket通信的形式对外提供键值对操作**,这种形式可以提供更加广泛的键值存储服务。

2. 索引模块

索引的作用是让键值数据库根据key找到相应value的存储位置,进而执行操作。常见的索引类型有哈希表B+树字典树等。

一个哈希表就是一个数组,数组的每个元素成为一个哈希桶,每个哈希桶中保存了键值对数据。哈希桶中的元素保存的并不是值本身,是指向具体指的指针。

Redis是通过链式哈希的方式解决哈希冲突问题,即同一个哈希桶中的多个元素用一个链表来保存,它们之间用指针连接

Redis使用了一个全局哈希表来保存所有键值对,同时还有一个哈希表用来交替rehash以扩充哈希桶数量。rehash分为三步:

  • 为哈希表2分配更大的空间,比如当前哈希表的2倍。
  • 将哈希表1中的数据重新映射到哈希表2中。
  • 释放哈希表1中的空间

当从哈希表1中切换到哈希表2后,可以保存更多的数据,原来的哈希表1留着下一次扩容备用。

为了避免一次性把哈希表1中的数据迁移到哈希表2造成Redis线程阻塞,Redis采用渐进式rehash避免这个问题。渐进式即每处理一个请求时,从哈希表1中的第一个索引位置开始,顺带着将这个索引位置上的所有entries拷贝到哈希表2中

3. 操作模块

索引模块根据key找到相应value的存储位置,然后根据不同操作对value的数据结构执行不同的逻辑。

  • get操作根据value的存储位置找到value值即可。
  • set操作找到value位置后需要分配内存并赋值。
  • delete操作找到value位置后需要释放内存。

4. 存储模块

对每一个键值对都进行落盘保存操作能使数据更加可靠,但是每次写盘对性能影响很大。如果周期性的将内存中的键值数据落盘能避免频繁落盘操作的性能影响,但是数据有丢失的风险。

以上基本结构仅仅是简略信息,更加详细信息随着后面学习逐渐补充

二、Redis数据结构

底层数据结构一共有6种,分别是简单动态字符串双向链表压缩列表哈希表跳表整数数组

Redis数据类型使用了一个或多个底层数据结构:

  • String:简单动态字符串。
  • List:双向链表、压缩列表。
  • Hash:压缩列表、哈希表。
  • Sorted Set:压缩列表、跳表。
  • Set:哈希表、整数数组。