文章目录
- 前言
- 一、Redis是什么?
- 二、Redis数据读取
- 三、Redis数据存储
- 1.String
- 2.List
- 3.Hash
- 4.Set
- 5.Sorted Set
- 总结
前言
本文主要记录Redis的数据读取和存储,以下均基于Redis 3.2以上的版本。
一、Redis是什么?
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。其支持五大数据存储类型,提供高性能的数据读取,常用作于缓存架构。并且支持集群化部署,满足服务高可用的需求。
二、Redis数据读取
为保证读取高性能,Redis的数据均储存于内存中,且Redis采用单线程读写方式,也使得Redis不会出现线程不安全的问题。Redis的数据存储格式采用Key-Value设计,在读取的时候,根据Key获取来获取Value操作也相应的变得简单和快捷。
三、Redis数据存储
Redis通过dic维护了多个Key-value的映射关系来实现数据的存储,这个映射关系的Key是String类型,而Value可以是多种数据类型。Redis提供了五种Value类型,分别为String、List、Hash、Set、Sorted Set。为了满足这五种数据类型的存储,Redis又采用了多种数据结构来保证数据存储。以下通过分析每种数据类型所采用的数据结构来分析Redis数据的存储。
1.String
String是Redis中简单的一种数据类型,其通常用于简单数据缓存、计数等,其底层实现为sds(一种可动态分配内存的字符串)和long。
一般情况下String的底层采用的是sds,由于Redis的数据主要存储在内存空间,所以其设计会尽可能的节约内存空间,所以如果当存储的类型为数值型的话,Redis则会转换成long型存储,这样可大大的节省内存空间,并且更加方便的实现计数等功能。
如果先set了一个数值类型的值,再在同一个Key 设置一个字符串的话,Redis底层就会直接转换成sds来存储了。
2.List
List 的实现为一个双向链表,一般用作队列使用存储列表类型的值,其支持在队列两端进行push和pop操作,以及其任意位置的存取操作。可用于好友列表、推送列表的实现。
List的底层实现方式为quicklist。quicklist是一个双向链表,包含有多个节点,其每个节点均是一个ziplist,ziplist的内存是一整块连续内存,储存效率高,内存随便少,但修改的效率很低。双向链接的修改效率高,但其内存开销大, 内存碎片多。于是quicklist将二者的优点结合起来实现。具体的可参考:http://zhangtielei.com/posts/blog-redis-quicklist.html
3.Hash
Hash可用与存储对象以及对象的字段值,对象的一个字段对应一个hash结构,能够很方便的操作一个对象。
Hash的底层实现有两种,分别为ziplist和dic(字典)。当数据量比较少时,底层采用ziplist的方式进行存储结构。当数据超过配置的条件之一时,底层将会转化为dic进行存储。配置如下:
- hash-max-ziplist-entries 512:Hash中的filed-value项大于512时,底层转换为dic
- hash-max-ziplist-value 64:当value值长度超过64时,底层转换为dic。
之所以会这样设计,是因为当ziplist数据量过大时,ziplist有以下两个缺点,
- 由于ziplist是一整块连续内存,当数据量大时,可能会频繁的realloc触发内存的拷贝,内存拷贝会占用更大的空间,大大的降低了性能
- 当ziplist的数据项过多时,其查询效率就会变得很低,因为ziplist查询是遍历查询的。
4.Set
Set是一个不允许有重复值得无序集合,其区别于List的有以下几点功能:
- Set可提供全局去重操作
- Redis可基于Set实现集合的交集、并集和差集,可实现共同好友等之内的集合之间操作的功能
Set的底层实现为intset(有序整数集合)和dic,当满足以下条件时,Redis采用intset结构来实现Set,否则就是用dic来实现Set
- 存储是整数类型的数据时,采用intset
- 存储的数据条数小于512个时,采用intset
Set集合会采用intset结构来存储,主要是因为intset 和 ziplist类似,内存空间碎片少,并且查找效率高。具体可参考:http://zhangtielei.com/posts/blog-redis-intset.html
5.Sorted Set
Sorted Set是一个有序集合,其区分于Set的功能是其提供了一个权重参数score,集合中的元素按照score来进行排序。可用来实现排行榜的功能
Sorted Set的底层实现为ziplist和zset(dic+skiplist),当满足以下条件时,则使用ziplist,否则使用zset
- 集合项的个数小于128个
- 集合中每个数据的小于64字节
当数据量大时,ziplist的查询效率会变低。但dic的查询效率也不高,为了保证高效的性能,Redis采用dic+skiplist结构来实现Sorted Set,skiplist提供高效的查询。具体可参考:http://zhangtielei.com/posts/blog-redis-skiplist.html
总结
以上解释了Redis五大基本数据类型的使用和存储原理,可以看出Redis在数据存储和查询的设计上均偏向于内存的优化和查询的高效,这也是Redis为什么能够以单线程模式支持超10w/s的查询效率的原因。