Skip to content

Latest commit

 

History

History
319 lines (232 loc) · 7.51 KB

File metadata and controls

319 lines (232 loc) · 7.51 KB

Redis 数据类型

STRING

简介

STRING 可以存储字符串、整数或者浮点数, 既可以对整个字符串或者字符串的其中一部分执行操作,也可以对整数和浮点数执行自增或者自减操作。

Redis 底层构建了一种简单动态字符串(Simple Dynamic String,SDS)。相比于 C 的原生字符串,SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度时间复杂度为 O(1)(C 字符串为 O(N)),除此之外,SDS 的 API 是安全的,不会造成缓冲区溢出。

常用命令

  • 普通字符串的基本操作:

    > set hello world
    OK
    > get hello
    "world"
    > exists hello
    (integer) 1
    > del hello
    (integer) 1
    > get hello
    (nil)s
  • 批量设置:

    > mset key1 value1 key2 value2
    OK
    > mget key1 key2
    1) "value1"
    2) "value2"
  • 计数器:

    > set number 1
    OK
    > incr number
    (integer) 2
    127.0.0.1:6379> get number
    "2"
    127.0.0.1:6379> decr number
    (integer) 1
    127.0.0.1:6379> get number
    "1"
  • 过期(默认永不过期):

    > expire key  60 # 设置 key 在 60s 后过期
    (integer) 1
    > setex key 60 value 
    # 设置 key-value 值且 key 在 60s 后过期 (setex:[set] + [ex]pire)
    OK
    > ttl key # 查看数据还有多久过期
    (integer) 56

应用场景

一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等等。

LIST

简介

LIST 即列表,可以从两端压入或者弹出元素,还可以对单个或者多个元素进行修剪,只保留一个范围内的元素。

Redis 的 LIST 的底层实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。

常用命令

  • rpush/lpop 实现队列:

    > rpush myList value1
    (integer) 1
    > rpush myList value2 value3
    (integer) 3
    > lpop myList
    "value1"
    > lrange myList 0 1
    1) "value2"
    2) "value3"
    > lrange myList 0 -1 # 查看列表中的所有元素,-1表示倒数第一
    1) "value2"
    2) "value3"
    > llen myList        # 查看列表长度
    (integer) 2
  • rpush/rpop 实现栈:

    > rpush myList2 value1 value2 value3
    (integer) 3
    > rpop myList2
    "value3"

应用场景

发布与订阅或者说消息队列、慢查询。

HASH

简介

HASH 即包含键值对的无序散列表,可以添加、获取、移除单个键值对;获取所有键值对;检查某个键是否存在。

Redis 底层实现类 JDK1.8 前的 HashMap(数组+链表)。

常用命令

> hmset user name "a" description "student" age "12"
OK
> hexists user name                   # 查看 key 对应的value 中指定的字段是否存在
(integer) 1
> hget user name
"a"
> hget user age
"12"
127.0.0.1:6379> hgetall user
1) "name"
2) "a"
3) "description"
4) "student"
5) "age"
6) "12"
> hkeys user
1) "name"
2) "description"
3) "age"
127.0.0.1:6379> hvals user
1) "a"
2) "student"
3) "12"
> hset user name "b"
> hget user name
"b"

应用场景

系统中对象数据的存储。

SET

简介

SET 即无序集合。当需要存储一个列表数据,又不希望出现重复数据时,SET 是一个很好的选择。基于 SET 可以轻易实现交集、并集、差集的操作。比如:将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能,求交集即可。

常用命令

> sadd mySet value1 value2
(integer) 2
> sadd mySet value1
(integer) 0
> smembers mySet
1) "value1"
2) "value2"
> scard mySet            # 查看 set 的长度
(integer) 2
> sismember mySet value1 # 检查某个元素是否存在 set 中,只能接收单个元素
(integer) 1
> sadd mySet2 value2 value3
(integer) 2
> sinterstore mySet3 mySet mySet2 # 获取 mySet 和 mySet2 的交集并存放在 mySet3 中
(integer) 1
127.0.0.1:6379> smembers mySet3
1) "value2"

应用场景

存放不能重复的数据以及需要获取多个数据源交集和并集等场景

ZSET

简介

ZSET 即有序集合 (sorted set) ,增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。

常用命令

> zadd myZset 3.0 value1       # 添加元素到 sorted set 中 3.0 为权重
(integer) 1
> zadd myZset 2.0 value2 1.0 value3
(integer) 2
127.0.0.1:6379> zcard myZset   # 查看 sorted set 中的元素数量
(integer) 3
> zscore myZset value1  # 查看某个 value 的权重
"3"
> zrange  myZset 0 -1  # 顺序输出某个范围区间的元素,0 -1 表示输出所有元素
1) "value3"
2) "value2"
3) "value1"
> zrange  myZset 0 1 # 顺序输出某个范围区间的元素,0 为 start  1 为 stop
1) "value3"
2) "value2"
> zrevrange myZset 0 1 # 逆序输出某个范围区间的元素,0 为 start  1 为 stop
1) "value1"
2) "value2"

应用场景

需要对数据根据某个权重进行排序的场景。比如在直播系统中,在线用户列表,各种礼物排行榜等。

BITMAP

简介

BITMAP 即位图。用一个 bit 位来标记某个元素对应的 value,而 key 即是该元素。我们知道 8 个 bit 可以组成一个 byte,所以 BITMAP 本身会极大的节省储存空间:

假设在 32 位操作系统中,从 20 亿个随机整数中找出某个数 m。

Java 中,如果每个数字用 int 存储,占用的空间约为

(2000000000*4/1024/1024/1024) ≈ 7.45 G

如果按位存储,20亿个数就是 20 亿位,占用空间约为

(2000000000/8/1024/1024/1024) ≈ 0.23 G

常用命令

> setbit mykey 7 1   # setbit 会返回之前位的值(默认是 0)
(integer) 0
> setbit mykey 7 0
(integer) 1
> getbit mykey 7
(integer) 0
> setbit mykey 6 1
(integer) 0
> setbit mykey 8 1
(integer) 0
> bitcount mykey     # 通过 bitcount 统计被被设置为 1 的位的数量
(integer) 2

应用场景

适合需要保存状态信息(比如是否签到、是否登录 ...)并需要进一步对这些信息进行分析的场景。

场景 1:用户行为分析

很多网站会对用户进行行为分析,比如记录用户是否点赞过某个视频。

> setbit AoTeMan_mp4 用户id 1
# 用户id 为 AoTeMan_mp4 视频点赞

场景 2:统计活跃用户

可以使用时间作为 key,用户 id 为 offset,如果用户当日活跃过就设置为 1。

计算某几天/月/年的活跃用户(我们约定:统计时间内只要有一天在线就称为活跃)

举个例子:

  • 初始化数据:

    用户 1 在 20210908、20210909 两天活跃过,用户 2 在 20210908 这一天活跃过

    > setbit 20210908 1 1
    (integer) 0
    > setbit 20210908 2 1
    (integer) 0
    > setbit 20210909 1 1
    (integer) 0
  • 统计 20210308~20210309 每天都活跃用户数:

    > bitop and active1 20210308 20210309 
    # bittop 命令支持 and、or、not 、xor 这四种操作
    (integer) 1
    > bitcount active1
    (integer) 1
  • 统计 20210308~20210309 活跃用户数:

    127.0.0.1:6379> bitop or active2 20210308 20210309
    (integer) 1
    127.0.0.1:6379> bitcount active2
    (integer) 2

场景 3:用户在线情况

对于获取或者统计用户在线状态,使用 BITMAP 是一个节约空间且效率又高的一种方法。

只需要一个 key,然后用户 id 为 offset,如果在线就设置为 1,不在线就设置为 0。