String

string是最基本的key-value结构,key是唯一标识,value是具体的值,value不仅是字符串,也可以是数字(整数/浮点数),value最大容纳的数据长度是512M

  • string的内部实现是int和SDS,SDS和C语言的字符串不太一样,没有使用C语言的字符串,
    SDS可以保存文本数据,还可以保存二进制数据
  • SDS获取字符串的长度的时间复杂度是O(1)
  • redis的SDS API是安全的,拼接字符串不会照成缓冲区的溢出

常用的指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 插入key
SET {key} value

// 得到key
GET {key}

// 某个key是否存在
EXISTS {key}

// 返回key对应的长度
STRLEN {key}

// 删除KEY
DEL {key}

批量操作

1
2
3
MSET key1 value1 key2 value2

MGET key1 key2

计数器,value为整数时候

1
2
3
4
5
6
7
8
9
10
11
12
13
SET number 0

// 增加1
INCR number

// 将key存储的数字值增加10
INCRBY number 10

// 减少1
DECR number

// 减少10
DECRBY number 10

设置过期,默认永不过期

1
2
3
4
5
6
7
8
9
// 设置key在60s后过期,(key已经存在)
EXPIRE name 60

// 查看数据还有多久过期
TTL name

// 设置key-value类型数据多久过期
SET key value EX 60
SETEX key 60 value

1
SETNX key value

使用场景

  • 使用string来缓存对象
    • 直接缓存整个对象json,例如命令: SET user:1’{“name”: “panic”, “age”: 18}’
    • 采用key进行分离user:ID属性,使用MSET存储,使用MGET获取属性: MSET user:1:name panic user:1:age 18, 读取: MGET user:1:name user:1:age
  • 常规计数:由于redis本身是单线程的,所以执行过程是原子的,因此string数据类型适合计数场景,比如点赞、次数、转发、库存数量等等
    例如文章阅读数量:

    1
    2
    3
    SET article:read:00001 0

    INCR article:read:00001
  • 分布式锁
    set nx实现如果key存在就插入,否则失败,可以用来做分布式唯一标识
    一般是set nx ex/px 时间,
    由于解锁的时候需要确保是加锁的客户端解锁,需要多一个判断,这时候使用lua脚本将操作串起来

    1
    2
    3
    4
    5
    if redis.call("get", KEY[1]) == ARGV[1] then
    return redis.call("del", KEY[1])
    else
    return 0
    end
  • 存储登录态的session信息
    登陆后的信息如果存储在不同的服务器上,会导致登录信息错乱,需要有一个统一的中心管理

List

简单的存储string的列表,
底层数据结构是双向链表或者压缩链表组成的

如果元素小于512个(默认值,可由list-max-ziplist-entries设置)列表中每个元素的值都小于64字节,那么redis会使用压缩链表作为存储的数据结构,否则redis会使用双向链表

redis3.2之后,list用的是quicklist,代替了上面两个
quicklist = ziplist + 双向链表

例如存储a,b,c,d,e,f,g,h
数据格式大概是

1
2
3
4
5
6
7
8
9
quicklist


+--------+ +--------+
| node1 | <-> | node2 |
+--------+ +--------+
│ │
▼ ▼
[a,b,c,d] [e,f,g,h]

可以设置ziplist最大存储数量,小于这个数量可以新增,等于时候开新的节点

为什么这么做?
早期的时候双向链表存储指针太多,内存占用太大

使用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 从左边插入元素,最后插入的元素在最前面
LPUSH key value [value1, value2...]

// 从右边插入元素,最后插入的元素在最后面
RPUSH key value [value1, value2...]

LPOP key
RPOP key

// 返回key中[start, end]元素
LRANGE key start end

// 弹出key,如果没有则阻塞timeout
BLPOP key [key...] timeout
BRPOP key [key...] timeout

使用场景

  • 消息队列
    消息队列取消息时候必须保证消息保序、处理重复消息和保证消息可靠性
1
2
3
4
5
6
                        ------>消费者  
LPUSH BRPUSH |
生产者 -> redis list ---------------->消费者
|
|
------->消费者

处理重复的消息,每个消息做一个全局ID,消费者要记录已经处理过的消息ID,当收到一条消息后,消费者程序可以对比收到的和已经处理过的消息,如果已经处理过,那么消费者程序就不再处理了

保证消息的可靠性: 提供了BRPOPLPUSH指令,拿到了消息后将消息备份在另外一个List中,也叫做List留存

Hash

Hash是key-value集合,value格式是:

1
value = [{field1, value1}, {field2, value2}...]

Hash存储对象比string更加方便

内部实现:
压缩链表或者哈希表

使用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HSET key field value
HGET key field

HMSET key field value [field value ...]
HMGET key field [field ...]
HDEL key field [field ...]

# 返回key里面field的数量
HLEN key

# 返回哈希表key中所有的键值
HGETALL key

# 为hash中key的field的值加n
HINCRBY key field n

使用场景

  • 缓存对象
    hash类型的(key, field, value)的结构与对象(对象ID,属性,值)的结构相似,也可以用来存储对象

    1
    2
    3
    4
    HMSET uid:1 name Tom age 15

    // 拿到uid为1的所有对象的值
    HGETALL uid:1
  • 购物车
    ![[{3AD5584C-7DD5-4AC6-BC57-37CBFDA9D917}.png]]

Set

无序且唯一的键对集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// key中加入member元素,已经存在member则忽略,不存在key的时候新建
SADD key member [member...]

// 从key里面删除元素
SREM key member [member]

// 获取所有的key
SCARD key

// 判断member是否存在于集合key中
SISMEMBER key member

// 从key中随机取出某些元素,元素不删除
SRANDEMEMBER key [count]

// 从集合key中随机选出count个元素,元素从key中删除
SPOP key [count]

SET的运算操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 交集运算
SINTER key [key ...]

// 将交集结果存入新的集合destination中
SINTERSTORE destination key [key...]

// 并集运算
SUNION key [key...]

// 将并集合存入新的destination
SUNIONSTORE destination key [key...]

// 差集
SDIFF key [key..]
// 将差集存入新的destination中
SDIFFSTORE destination key [key...]

应用

  • 点赞
    1
    2
    3
    4
    5
    // uid:1对article:1点赞
    SADD article:1 uid:1

    // uid:2对于article1点赞
    SADD article:1 uid:2
1
2
3
4
5
6
7
8
// 取消点赞
SREM article:1, uid:1

// 获取article:1所有点赞用户
SMEMBERS article:1

// 获取article:1所有点赞用户数量
SCARD article:1
1
2
// 判断用户uid:1是否对文章的article1点赞
SISMEMBER article:1 uid:1
  • 共同关注

    1
    2
    3
    4
    5
    SADD uid:1 5 6 7 8 9
    SADD uid:2 6 7 8 99 992

    // 1和2共同关注的公众号
    SINTER uid:1 uid:2
  • 抽奖

    1
    2
    3
    4
    5
    6
    7
    SADD lucky tom cat nanshou xiangsi

    // 抽取n个人作为x等奖励
    SRANDEMEMBER lucky [数字n]

    // 如果不允许重复中奖,勇SPOP
    SPOP lucky [数字n]

ZSET

比起set多加了一个排序的score(分值),对于Zset来说每个储存元素相当于有两个值组成,一个是有序集合的元素值,一个是排序值

底层结构使用的是跳表,
跳表的实现细节:
插入一个数字时候,使用概率算法随机生成当前插入的层数,尽量保证上面的数字少,下面的数字大,之后从对应层从后往前便利,插入这个数字使得每一层的链表保持递增,同时维护update用来存储上一个更新的forward指针位置,更新每层span使得尽可能平衡
查询一个数字时候从最上层开始,依次遍历到下一个数字比查询的数字大时候跳到下一层,直到找到了或者遍历完了

命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ZADD key score member [[score member] ...]

ZREM key member [member]

ZSCORE key member

ZCARD key

ZINCRBY key increment member

// 正序获取start stop(WITHSCORES表示要不要带分数) 下表
ZRANGE key start stop [WITHSCORES]
// 倒叙获取分数区间
ZREVRANGE key start stop [WITHSCORES]

ZRANGEBYLEX key min max

应用场景

  • 排行榜单
    以点赞排行版为例子
    每次点赞
    1
    2
    SADD article:userlike user1
    ZINCRBY article:userlike 1 user1

统计某个书

1
ZCARD article:userlike

拿到topk

1
2
// 获得最大的三排文章
ZREVRANGE article:userlike 0 2

Bitmap

用的是string,byte数组来存储

1
2
3
4
5
6
7
8
9
// 设置值 value只能是0 / 1
SETBIT key offset value

// 获取值
GETBIT key offset

// 获取范围内value为1的数量,
// start end 以key为单位
BITCOUNT key start end

运算操作

1
2
3
4
5
// AND OR XOR NOT
BITOP [操作类型(AND, OR, XOR)] [result] [key1] [key2], ....

// 返回key中第一次出现value的位置
BITPOS [key] [value]

1
2
3
4
5
6
7
8
9
10
11
12
// 用户100 在20260314 2号 签到
SETBIT uid:sign:100:20260314 2 1

// 检查用户是否签到
GETBIT uid:sign:100:20260314 2

// 统计该用户在6月份签到次数
BITCOUNT uid:sign:100:20260314

// 统计连续签到打卡的
BITOP AND res login:day:1 login:day:2 login:day:3...
BITCOUNT res

HyperLogLog

适合用于小内存存储大量的数据,实现比较玄学,有概率不准确,准确的概率有78%

是用于统计用户登陆的UV

1
2
3
4
5
// 某个key加member
PFADD key member [member1 ...]

// 统计基数
PFCOUNT key

例如

1
2
3
4
5
6
7
8
PFADD login user1
PFADD login user2
PFADD login user3

PFCOUNT login
// 输出3

PFMERGE destkey sourcekey [sourcekey]

GEO

地图用的

Stream

得学