文章目录
一、Redis 优缺点
Redis (Remote Dictionary Server) 是一个使用 C 语言 编写的,开源的 (BSD许可) 高性能 非关系型 (NoSQL) 的 键值对数据库。
Redis中的主要数据结构有动态字符串(SDS),链表,字典等,但是并没有直接使用这些数据结构实现键值对数据库,而是基于这些数据结构创建了一个对象系统,包括:字符串对象、列表对象,哈希对象,集合对象和有序集合对象,好处就是可以针对不同的使用场景,为对象设置多种不同的数据结构,从而提高对象在不同场景下的使用效率。
优点:
缺点:
二、Redis 的对象类型和编码
Redis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。
对于 Redis 数据库保存的键值对来说,键总是一个字符串对象,值可以是字符串对象,列表对象,哈希对象,集合对象或者有序集合对象。
Redis中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type属性、encoding属性和ptr属性:
对象的 type 属性记录了对象的类型,得到的是值对象的类型,而不是键对象的类型
对象的ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定。
encoding属性记录了对象所使用的编码,也即是说这个对象使用了什么数据结构作为对象的底层实现,这个属性的值可以是表列出的常量的其中一个。
每种类型的对象都至少使用了两种不同的编码
通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一种固定的编码,极大地提升了Redis的灵活性和效率,因为Redis可以根据不同的使用场景来为一个对象设置不同的编码,从而优化对象在某一场景下的效率。
比如:列表有压缩列表和链表两种底层实现
其他类型的对象也会通过使用多种不同的编码来进行类似的优化。
三、五种数据类型
1. String 字符串
字符串对象的编码可以是int、raw或者embstr。
String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。
使用:get 、 set 、 del 、 incr、 decr 等
实战场景:
2. Hash (哈希)
哈希对象的编码可以是ziplist或者hashtable。
是一个map,指值本身又是一种键值对结构
使用:所有hash的命令都是 h 开头的 hget 、hset 、 hdel 等
实战场景:
3. 列表
列表对象的编码可以是ziplist或者linkedlist。
List 说白了就是链表(redis 使用双端链表实现的 List),是有序的,value可以重复,可以通过下标取出对应的value值,左右两边都能进行插入和删除数据。
实战场景:
4. Set 集合
集合对象的编码可以是intset或者hashtable。
集合类型也是用来保存多个字符串的元素,
但和列表不同的是集合中不允许有重复的元素;集合中的元素是无序的,不能通过索引下标获取元素;支持集合间的操作,可以取多个集合取交集、并集、差集。
实战场景:
5. zset 有序集合
有序集合的编码可以是 ziplist 或者 skiplist。
对于跳跃表的底层实现是有序集合元素同时被保存在跳跃表和字典中
举个例子,如果我们只使用字典来实现有序集合,那么虽然以O(1)
复杂度查找成员的分值这一特性会被保留,但是,因为字典以无序的方式来保存集合元素,所以每次在执行范围型操作程序都需要对字典保存的所有元素进行排序,完成这种排序需要至少O(NlogN)
时间复杂度,以及额外的O(N)
内存空间(因为要创建一个数组来保存排序后的元素)。
另一方面,如果我们只使用跳跃表来实现有序集合,那么跳跃表执行范围型操作的所有优点都会被保留,但因为没有了字典,所以根据成员查找分值这一操作的复杂度将从O(1)
上升为O(logN)
因为以上原因,为了让有序集合的查找和范围型操作都尽可能快地执行,Redis选择了同时使用字典和跳跃表两种数据结构来实现有序集合
有序集合和集合有着必然的联系,保留了集合不能有重复成员的特性,区别是,有序集合中的元素是可以排序的,它给每个元素设置一个分数,作为排序的依据。
有序集合存储的是一个键key,一个对应的有序集合
当通过key查找具体的分数时,是先通过key找到对应的有序集合,然后再字典定位到具体的score
实战场景:
详细内容参考:Redis 的五种数据结构
其他:位图(Bitmap),超级日志(HyperLogLog),地理空间(Geospatial)