Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。

在关系型数据库如MySQL中,表的结构比较复杂会包含很多个字段。可以使用查询语句实现非常复杂的查询需求,而Redis中只能包含键和值两部分,只能通过键来查询或添加值。Redis 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。并且Redis的数据是存储在内存中的,所以它的速度非常快。

Redis数据类型

字符串

列表

列表支持存储一组数据,有两种实现方法:

压缩列表

压缩列表是Redis设计的一种数据存储结构,类似数组。通过一篇连续的内存空间来存储数据,并且允许存储的数据大小不同。但要求列表中数据个数不超过512个并且每个数据小于64字节。

具体的结构也很简单:数组由连续的单元组成,其中每个单元第一个字节记录该单元数据位的长度,从第二个字节开始存储实际的数据。此外数组头部还有一个字节记录数组元素的个数。

采用压缩列表的优点是:

  • 连续的内存空间,读取效率非常高;
  • 压缩的结构节省内存;
  • 一个列表中支持不同类型的数据。

但是值得注意的是,压缩列表并不能像常规的列表一样支持随机访问,Redis在读取数据时,一般是按照键获取整个列表的数据。

双向循环链表

当列表中的数据量比较大的时候,Redis中的列表就需要使用双向循环链表来实现。这里的双向循环链表与常规的有点区别,它额外定义了一个list结构体用于组织链表的首、尾指针、长度等信息。

字典

字典类型用来存储一组数据对,即每个数据对都包含键和值两部分。同样的,字典类型也有两种实现方式:

压缩列表

这里压缩列表的限制条件还是一样的,只能存储比较小的数据量。具体的数据结构组织方式与列表类似,不同点就是单元中的数据由一部分变成了键和值两部分。

散列表

Redis使用MurmurHash2作为哈希函数,优点就是运行速度快、随机性好。使用链表法解决哈希冲突,并且Redis还支持动态扩容和缩容。

集合

集合用于存储一组不重复的数据,集合类型也有两种实现方式:有序数组和散列表。

当要存储的数据都是整数且数据个数不超过512个时Redis就会采用有序数组的方式实现集合。不满足这两个条件时,采用散列表来实现集合。

有序集合

有序集合与集合的不同之处在于,每个数据都会附带一个分数,通过分数的大小再借助跳表实现快速的按照分数大小、区间获取数据。同样的,有序集合还有另外的实现方式:压缩列表。

数据持久化

数据持久化有两种实现方式:

第一种,清除原有的数据结构,只存储数据。还原时在重新将数据组织成原来的数据结构;

第二种,保留原来的数据结构格式,将数据按照原有格式存储。

Redis采用的是第一种的实现方式,这种方式还原的时候会比较耗费时间并且在恢复散列表时,还需要重新计算哈希值。

实际操作中Redis数据持久化有两种操作方式:

RDB持久化

将某个时间点的所有数据都存放到硬盘上 , 这样可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。

AOF持久化

将写命令添加到 AOF 文件(Append Only File)的末尾 ,使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘 。