Redis 数据类型

Redis 有哪些数据类型

        Redis 有 String、List、Hash、Set、ZSet、Bitmap、Hyperloglog 等,下面来详细说下这几种类型的底层实现。

1. String

String 底层实现分为两种:

  • 整数:长度小于 21 且能够转化为整数的字符串
  • SDS (Simple Dynamic String 简单动态字符串):len 长度 + free 剩余未使用空间 + buf 字符数组

SDS 的好处:

  1. 可以根据 len 快速获取字符串长度
  2. 当修改字符串长度时可以减少内存分配次数

使用场景:缓存,限流,计数器,分布式锁,分布式 Session

基本命令:

SET key value                           GET key
MSET key value [key value]              MGET [key1 key2]
INCR key                                DECR key
SETEX key second value                  SETNX key value

2. List

List 在 Reids 中主要用于实现队列或栈,在不同版本有不同的实现方式:

  • 旧版本:
    • 数据量小时:ZipList 压缩链表
    • 数据量大时:LinkedList 双向链表
  • 新版本:
    • 数据量小时:ZipList 压缩链表
    • 数据量大时:QuickList 快速链表

ZipList:压缩链表,由一系列特殊编码的连续内存块组成的顺序存储结构,其不固定长度数组,每个元素大小通过元素头的 len 来确定。

QuickList:也是一个链表结构,只不过链表节点维护一个 ZipList,从而压缩内存空间。

使用场景:微博关注人时间轴列表,简单队列

基本命令

LPOP # key 移除第一个元素    RPOP # 移除最后一个元素
LPUSH                   RPUSH
LSET key index value   # 通过索引设置列表元素的值

3. Hash

Hash 是一个类似 Map 的映射结构,其底层有两种实现:

  • 数据量小时:ZipList
  • 数据量大时:HashTable

使用场景:存储用户信息,用户主页访问量,文章点赞数据

基本命令

HGET key field          HGETALL key         HMGET key field1 field2
HSET key field value    HMSET key field1 value1 field2 value2
HSETNX key field value

4. Set

Set 是一个用于去重的数据结构,底层实现:HashTable 的 Key 部分

使用场景:点赞,踩,标签,好友关系

基本命令

SADD key member1 member2
SDIFF key1 key2  # 返回第一个集合与其他集合的差异
SINTER key1 key2  # 返回交集
SREM key member1
SPOP key  # 移除集合的一个随机元素

5. ZSet

ZSet 是一个排序,去重的数据结构框架,其底层有两种实现:

  • 数据量小时:ZipList
  • 数据量大时:SkipList

采用 ZipList 的原因:由于数据量少,O(n) 复杂度的查询和 O(logN) 的查询时间相差不大,同时,ZipList 能很好的压缩内存,节约空间。

SkipList:跳跃表,其根据数据量会分为多层结构,当查询时从上层往下找,复杂度为 O(logN),当插入时,会先找到插入的位置,同时生成一个随机数,来表示此节点要生成多少层。SkipList 相较于二叉搜索树的好处是其不用严格的按照左右节点,通过随机数的大小来判断此节点的层数。

使用场景:排行榜,分页数据

基本命令:

ZADD key score1 member1 score2 member2
ZCOUNT key min max  # 范围内的成员数

6. BitMap

BitMap 通过每一个来记录一些数据的状态,达到压缩内存的效果。

使用场景:用户签到,火车座位在不同站点时的状态

基本命令:

setbit name 1 1
getbit name 1    # 1
setbit name 3 1
bitcount bittest 0 0  # 表示第一个字节(8位)0 的个数

7. HyperLogLog

HyperLogLog 用于基数统计,每个 HyperLogLog 只需要花费 12K 内存,就可以计算接近 2^16 个不同元素的基数,且错误率在 0.82%,这和 set (元素越多内存越大)形成对比。但是 HyperLogLog 只会根据输入元素来计算基数,不会存储元素本身,所以 HyperLogLog 不能输出各个元素。但其也能作为交集,返回元素个数。

基数:在数组中出现过的值,例如:{1, 3, 5, 7, 5, 7, 8} 的基数集为 {1, 3, 5, 7, 8}

底层原理:

  • 假设一个人抛硬币,每轮可以抛任意次,但抛到正面就要结束掉。若它抛到为 001,因为 001 出现的概率为 1/8,于是我们可以断定抛了 8 次。
  • 同理,我们可以根据数组中的数据的二进制位 1 出现的位置,来大概估计这组数据中基数的个数,同时设置多个槽,再根据加权平均值得出最终的结果。

基本命令:

PFADD key element1 element2
PFCOUNT key1 key2  # 查找基数的个数,若多个 key,交集
updatedupdated2022-06-232022-06-23