Redis 有哪些数据类型?( 二 )

集合类型(Set)和列表类型(List)的区别如下:

  • 列表可以存储重复元素,集合只能存储非重复元素;
  • 列表是按照元素的先后顺序存储元素的,而集合则是无序方式存储元素的 。
5.有序集合类型有序集合类型 (Sorted Set) 相比于集合类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值 。有序集合的存储元素值也是不能重复的,但分值是可以重复的 。
当我们把学生的成绩存储在有序集合中时,它的存储结构如下图所示:
Redis 有哪些数据类型?

文章插图
 
有序集合类型的使用如下:
127.0.0.1:6379> zadd zset1 3 golang 4 sql 1 redis # 添加数据(integer) 3127.0.0.1:6379> zrange zset 0 -1 # 查询所有数据1) "redis"2) "MySQL"3) "JAVA"复制有序集合的经典使用场景如下:
  • 学生成绩排名;
  • 粉丝列表,根据关注的先后时间排序 。
考点分析关于 Redis 数据类型的这个问题,对于大多数人既熟悉又陌生,熟悉的是每天都在使用 Redis 存取数据,陌生的是对于 Redis 的数据类型知之甚少,因为对于普通的开发工作使用字符串类型就可以搞定了 。但是善用 Redis 的数据类型可以到达意想不到的效果,不但可以提高程序的运行速度又可以减少业务代码,可谓一举两得 。
例如我们经常会把用户的登录信息存储在 Redis 中,但通常的做法是先将用户登录实体类转为 JSON 字符串存储在 Redis 中,然后读取时先查询数据再反序列化为 User 对象,这个过程看似没什么问题,但我们可以有更优的解决方案来处理此问题,比如我们可以使用 Hash 存储用户的信息,这样就无需序列化的过程了,并且读取之后无需反序列化,直接使用 Map 来接收就可以了,这样既提高了程序的运行速度有省去了序列化和反序列化的业务代码 。
与此知识点相关的面试题还有以下几个:
  • 有序列表的实际存储结构是什么?
  • 除了五种基本的数据类型之外,还有什么数据类型?
知识扩展有序列表的内部实现有序集合是由 ziplist (压缩列表) 或 skiplist (跳跃表) 组成的 。
ziplist 介绍当数据比较少时,有序集合使用的是 ziplist 存储的,如下代码所示:
127.0.0.1:6379> zadd myzset 1 db 2 redis 3 mysql(integer) 3127.0.0.1:6379> object encoding myzset"ziplist"复制从结果可以看出,有序集合把 myset 键值对存储在 ziplist 结构中了 。有序集合使用 ziplist 格式存储必须满足以下两个条件:
  • 有序集合保存的元素个数要小于 128 个;
  • 有序集合保存的所有元素成员的长度都必须小于 64 字节 。
如果不能满足以上两个条件中的任意一个,有序集合将会使用 skiplist 结构进行存储 。接下来我们来测试以下,当有序集合中某个元素长度大于 64 字节时会发生什么情况? 代码如下:
127.0.0.1:6379> zadd zmaxleng 1.0 redis(integer) 1127.0.0.1:6379> object encoding zmaxleng"ziplist"127.0.0.1:6379> zadd zmaxleng 2.0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(integer) 1127.0.0.1:6379> object encoding zmaxleng"skiplist"复制通过以上代码可以看出,当有序集合保存的所有元素成员的长度大于 64 字节时,有序集合就会从 ziplist 转换成为 skiplist 。
小贴士:可以通过配置文件中的 zset-max-ziplist-entries(默认 128)和 zset-max-ziplist-value(默认 64)来设置有序集合使用 ziplist 存储的临界值 。
skiplist 介绍skiplist 数据编码底层是使用 zset 结构实现的,而 zset 结构中包含了一个字典和一个跳跃表,源码如下:
typedef struct zset {dict *dict;zskiplist *zsl;} zset;复制跳跃表的结构如下图所示:
Redis 有哪些数据类型?

文章插图
 
根据以上图片展示,当我们在跳跃表中查询值 32 时,执行流程如下: