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 即列表,可以从两端压入或者弹出元素,还可以对单个或者多个元素进行修剪,只保留一个范围内的元素。
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 即包含键值对的无序散列表,可以添加、获取、移除单个键值对;获取所有键值对;检查某个键是否存在。
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 可以轻易实现交集、并集、差集的操作。比如:将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。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 即有序集合 (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 即位图。用一个 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适合需要保存状态信息(比如是否签到、是否登录 ...)并需要进一步对这些信息进行分析的场景。
很多网站会对用户进行行为分析,比如记录用户是否点赞过某个视频。
> setbit AoTeMan_mp4 用户id 1
# 用户id 为 AoTeMan_mp4 视频点赞可以使用时间作为 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
对于获取或者统计用户在线状态,使用 BITMAP 是一个节约空间且效率又高的一种方法。
只需要一个 key,然后用户 id 为 offset,如果在线就设置为 1,不在线就设置为 0。