Skip to content

Commit 6d4586a

Browse files
committed
[docs update]redis数据类型分为2篇
1 parent 9b32598 commit 6d4586a

File tree

3 files changed

+139
-144
lines changed

3 files changed

+139
-144
lines changed

docs/database/redis/redis-data-structures.md docs/database/redis/redis-data-structures-01.md

+27-141
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
你可以自己本机安装 redis 或者通过 redis 官网提供的[在线 redis 环境](https://try.redis.io/)来实际体验 Redis。
2-
3-
![try-redis](./images/redis-all/try-redis.png)
4-
51
你可以在 Redis 官网上找到 Redis 数据结构非常详细的介绍:[Redis Data Structures](https://redis.com/redis-enterprise/data-structures/) 。未来随着 Redis 新版本的发布,可能会有新的数据结构出现,通过查阅 Redis 官网对应的介绍,你总能获取到最靠谱的信息。
62

7-
## 基本数据结构
8-
9-
### String(字符串)
3+
## String(字符串)
104

11-
#### 介绍
5+
### 介绍
126

137
String 是 Redis 中最简单同时也是最常用的一个数据结构。
148

@@ -18,7 +12,7 @@ String 是一种二进制安全的数据结构,可以用来存储任何类型
1812

1913
虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 **简单动态字符串**(Simple Dynamic String,**SDS**)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。
2014

21-
#### 常用命令
15+
### 常用命令
2216

2317
| 命令 | 介绍 |
2418
| ------------------------------ | -------------------------------- |
@@ -89,33 +83,33 @@ OK
8983
(integer) 56
9084
```
9185

92-
#### 应用场景
86+
### 应用场景
9387

94-
**需要存储数据的场景**
88+
**需要存储常规数据的场景**
9589

9690
- 举例 :缓存 session、token、图片地址、序列化后的对象(相比较于 Hash 存储更节省内存)。
9791
- 相关命令 : `SET``GET`
9892

9993
**需要计数的场景**
10094

101-
- 举例 :用户单位时间的请求数(简单限流可以用到)、
95+
- 举例 :用户单位时间的请求数(简单限流可以用到)、页面单位时间的访问数。
10296
- 相关命令 :`SET``GET``INCR``DECR`
10397

10498
**分布式锁**
10599

106100
利用 `SETNX key value` 命令可以实现一个最简易的分布式锁(存在一些缺陷,通常不建议这样实现分布式锁)。
107101

108-
### List(列表)
102+
## List(列表)
109103

110-
#### 介绍
104+
### 介绍
111105

112106
Redis 中的 List 其实就是链表数据结构的实现。我在 [线性数据结构 :数组、链表、栈、队列](https://javaguide.cn/cs-basics/data-structure/linear-data-structure.html) 这篇文章中详细介绍了链表这种数据结构,我这里就不多做介绍了。
113107

114108
许多高级编程语言都内置了链表的实现比如 Java 中的 `LinkedList`,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 List 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
115109

116110
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220719124413287.png)
117111

118-
#### 常用命令
112+
### 常用命令
119113

120114
| 命令 | 介绍 |
121115
| --------------------------- | ------------------------------------------ |
@@ -182,30 +176,30 @@ Redis 中的 List 其实就是链表数据结构的实现。我在 [线性数据
182176
(integer) 3
183177
```
184178

185-
#### 应用场景
179+
### 应用场景
180+
181+
**信息流展示**
182+
183+
- 举例 :最新文章、最新动态。
184+
- 相关命令 : `LPUSH``LRANGE`
186185

187186
**消息队列**
188187

189188
Redis List 数据结构可以用来做消息队列,只是功能过于简单,不建议这样做。
190189

191190
相对来说,Redis 5.0 新增加的一个数据结构 `Stream` 更适合做消息队列一些,只是功能依然非常简陋。和专业的消息队列相比,还是有很多欠缺的地方比如消息丢失和堆积问题不好解决。
192191

193-
**信息流展示**
194-
195-
- 举例 :最新文章、最新动态。
196-
- 相关命令 : `LPUSH``LRANGE`
192+
## Hash(哈希)
197193

198-
### Hash(哈希)
199-
200-
#### 介绍
194+
### 介绍
201195

202196
Hash 是一个 String 类型的 field 和 value 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。
203197

204198
Hash 类似于 JDK1.8 前的 `HashMap`,内部实现也差不多(数组 + 链表)。不过,Redis 的 Hash 做了更多优化。
205199

206200
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220719124421703.png)
207201

208-
#### 常用命令
202+
### 常用命令
209203

210204
| 命令 | 介绍 |
211205
| ----------------------------------------- | -------------------------------------------------------- |
@@ -244,40 +238,24 @@ OK
244238
"GuideGeGe"
245239
```
246240

247-
#### 应用场景
241+
### 应用场景
248242

249243
**对象数据存储场景**
250244

251245
- 举例 :用户信息、商品信息、文章信息、购物车信息。
252246
- 相关命令 :`HSET` (设置单个字段的值)、`HMSET`(设置多个字段的值)、`HGET`(获取单个字段的值)、`HMGET`(获取多个字段的值)。
253247

254-
String 存储还是 Hash 存储对象数据更好呢?
255-
256-
- String 存储的是序列化后的对象数据,存放的是整个对象。Hash 是对对象的每个字段单独存储,可以获取部分字段的信息,也可以修改或者添加部分字段,节省网络流量。如果对象中某些字段需要经常变动或者经常需要单独查询对象中的个别字段信息,Hash 就非常适合。
257-
- String 存储相对来说更加节省内存,缓存相同数量的对象数据,String 消耗的内存约是 Hash 的一半。并且,存储具有多层嵌套的对象时也方便很多。如果系统对性能和资源消耗非常敏感的话,String 就非常适合。
258-
259-
在绝大部分情况,我们建议使用 String 来存储对象数据即可!
260-
261-
那购物车信息用 String 存储还是 Hash 存储更好呢?
262-
263-
购物车信息建议使用 Hash 存储:
264-
265-
- 用户 id 为 key
266-
- 商品 id 为 field,商品数量为 value
248+
## Set(集合)
267249

268-
由于购物车中的商品频繁修改和变动,这个时候 Hash 就非常适合了!
269-
270-
### Set(集合)
271-
272-
#### 介绍
250+
### 介绍
273251

274252
Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺序但都唯一,有点类似于 Java 中的 `HashSet` 。当你需要存储一个列表数据,又不希望出现重复数据时,Set 是一个很好的选择,并且 Set 提供了判断某个元素是否在一个 Set 集合内的重要接口,这个也是 List 所不能提供的。
275253

276254
你可以基于 Set 轻易实现交集、并集、差集的操作,比如你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。这样的话,Set 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
277255

278256
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220719124430264.png)
279257

280-
#### 常用命令
258+
### 常用命令
281259

282260
| 命令 | 介绍 |
283261
| ------------------------------------- | ----------------------------------------- |
@@ -342,7 +320,7 @@ Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺
342320
1) "value1"
343321
```
344322

345-
#### 应用场景
323+
### 应用场景
346324

347325
**需要存放的数据不能重复的场景**
348326

@@ -363,15 +341,15 @@ Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺
363341
- 举例 :抽奖系统、随机。
364342
- 相关命令:`SPOP`(随机获取集合中的元素并移除,适合不允许重复中奖的场景)、`SRANDMEMBER`(随机获取集合中的元素,适合允许重复中奖的场景)。
365343

366-
### Sorted Set(有序集合)
344+
## Sorted Set(有序集合)
367345

368-
#### 介绍
346+
### 介绍
369347

370348
Sorted Set 类似于 Set,但和 Set 相比,Sorted Set 增加了一个权重参数 `score`,使得集合中的元素能够按 `score` 进行有序排列,还可以通过 `score` 的范围来获取元素的列表。有点像是 Java 中 `HashMap``TreeSet` 的结合体。
371349

372350
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220719124437791.png)
373351

374-
#### 常用命令
352+
### 常用命令
375353

376354
| 命令 | 介绍 |
377355
| --------------------------------------------- | ------------------------------------------------------------ |
@@ -451,7 +429,7 @@ value1
451429
2
452430
```
453431

454-
#### 应用场景
432+
### 应用场景
455433

456434
**需要随机获取数据源中的元素根据某个权重进行排序的场景**
457435

@@ -469,98 +447,6 @@ value1
469447
- 举例 :优先级任务队列。
470448
- 相关命令 :`ZRANGE` (从小到大排序) 、 `ZREVRANGE` (从大到小排序)、`ZREVRANK` (指定元素排名)。
471449

472-
## 特殊数据结构
473-
474-
### Bitmap
475-
476-
#### 介绍
477-
478-
Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 Bitmap 本身会极大的节省储存空间。
479-
480-
#### 常用命令
481-
482-
`setbit``getbit``bitcount``bitop`
483-
484-
```bash
485-
# SETBIT 会返回之前位的值(默认是 0)这里会生成 7 个位
486-
> setbit mykey 7 1
487-
(integer) 0
488-
> setbit mykey 7 0
489-
(integer) 1
490-
> getbit mykey 7
491-
(integer) 0
492-
> setbit mykey 6 1
493-
(integer) 0
494-
> setbit mykey 8 1
495-
(integer) 0
496-
# 通过 bitcount 统计被被设置为 1 的位的数量。
497-
> bitcount mykey
498-
(integer) 2
499-
```
500-
501-
#### 应用场景
502-
503-
适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)
504-
505-
**用户行为分析**
506-
很多网站为了分析你的喜好,需要研究你点赞过的内容。
507-
508-
```bash
509-
# 记录你喜欢过 001 号小姐姐
510-
> setbit beauty_girl_001 uid 1
511-
```
512-
513-
**统计活跃用户**
514-
515-
使用时间作为 key,然后用户 ID 为 offset,如果当日活跃过就设置为 1
516-
517-
那么我该如何计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只要有一天在线就称为活跃),有请下一个 redis 的命令
518-
519-
```bash
520-
# 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
521-
# BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数
522-
BITOP operation destkey key [key ...]
523-
```
524-
525-
初始化数据:
526-
527-
```bash
528-
> setbit 20210308 1 1
529-
(integer) 0
530-
> setbit 20210308 2 1
531-
(integer) 0
532-
> setbit 20210309 1 1
533-
(integer) 0
534-
```
535-
536-
统计 20210308~20210309 总活跃用户数: 1
537-
538-
```bash
539-
> bitop and desk1 20210308 20210309
540-
(integer) 1
541-
> bitcount desk1
542-
(integer) 1
543-
```
544-
545-
统计 20210308~20210309 在线活跃用户数: 2
546-
547-
```bash
548-
> bitop or desk2 20210308 20210309
549-
(integer) 1
550-
> bitcount desk2
551-
(integer) 2
552-
```
553-
554-
**用户在线状态**
555-
556-
对于获取或者统计用户在线状态,使用 Bitmap 是一个节约空间且效率又高的一种方法。
557-
558-
只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。
559-
560-
### HyperLogLog
561-
562-
### Stream
563-
564450
## 参考
565451

566452
- Redis Data Structures :https://redis.com/redis-enterprise/data-structures/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
### Bitmap
2+
3+
#### 介绍
4+
5+
Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 Bitmap 本身会极大的节省储存空间。
6+
7+
#### 常用命令
8+
9+
`setbit``getbit``bitcount``bitop`
10+
11+
```bash
12+
# SETBIT 会返回之前位的值(默认是 0)这里会生成 7 个位
13+
> setbit mykey 7 1
14+
(integer) 0
15+
> setbit mykey 7 0
16+
(integer) 1
17+
> getbit mykey 7
18+
(integer) 0
19+
> setbit mykey 6 1
20+
(integer) 0
21+
> setbit mykey 8 1
22+
(integer) 0
23+
# 通过 bitcount 统计被被设置为 1 的位的数量。
24+
> bitcount mykey
25+
(integer) 2
26+
```
27+
28+
#### 应用场景
29+
30+
适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)
31+
32+
**用户行为分析**
33+
很多网站为了分析你的喜好,需要研究你点赞过的内容。
34+
35+
```bash
36+
# 记录你喜欢过 001 号小姐姐
37+
> setbit beauty_girl_001 uid 1
38+
```
39+
40+
**统计活跃用户**
41+
42+
使用时间作为 key,然后用户 ID 为 offset,如果当日活跃过就设置为 1
43+
44+
那么我该如何计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只要有一天在线就称为活跃),有请下一个 redis 的命令
45+
46+
```bash
47+
# 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
48+
# BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数
49+
BITOP operation destkey key [key ...]
50+
```
51+
52+
初始化数据:
53+
54+
```bash
55+
> setbit 20210308 1 1
56+
(integer) 0
57+
> setbit 20210308 2 1
58+
(integer) 0
59+
> setbit 20210309 1 1
60+
(integer) 0
61+
```
62+
63+
统计 20210308~20210309 总活跃用户数: 1
64+
65+
```bash
66+
> bitop and desk1 20210308 20210309
67+
(integer) 1
68+
> bitcount desk1
69+
(integer) 1
70+
```
71+
72+
统计 20210308~20210309 在线活跃用户数: 2
73+
74+
```bash
75+
> bitop or desk2 20210308 20210309
76+
(integer) 1
77+
> bitcount desk2
78+
(integer) 2
79+
```
80+
81+
**用户在线状态**
82+
83+
对于获取或者统计用户在线状态,使用 Bitmap 是一个节约空间且效率又高的一种方法。
84+
85+
只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。
86+
87+
### HyperLogLog
88+
89+
### Stream

0 commit comments

Comments
 (0)